在Java中寻找依赖的确切时间

时间:2012-08-11 09:53:46

标签: java jar dependencies

当Java正好在运行时查找Jar文件的依赖项时?

在开始运行时? 当它试图初始化一个具有某种依赖性的类时?
还是其他任何时间?

3 个答案:

答案 0 :(得分:3)

未指定加载.class文件的时间。众所周知,即使在main方法开始执行之前,类路径中的所有类文件也可能被加载。

Java指定的唯一内容是当一个类初始化时,这与加载它完全不同。

答案 1 :(得分:1)

Java Language Specification, §12.3说(我的重点):

  

此规范允许实现灵活性,以便何时发生链接活动(,并且由于递归,加载),前提是语言的语义得到尊重,类或接口完全在初始化之前进行验证和准备,并且在链接期间检测到的错误被抛出到程序中的某个点,程序可能需要链接到错误中涉及的类或接口。

     

例如,实现可以选择单独解析类或接口中的每个符号引用,仅在使用它时(延迟或延迟解析),或者在验证类时立即解析它们(静态解析) )。这意味着在一些实现中,在初始化类或接口之后,解析过程可以继续。

现在,规范说JVM 可以做一系列的事情,但显然,任何给定的JVM 做了一件特别的事情。 Marko的回答说“类似路径中的所有类文件甚至可以在main方法开始执行之前加载”,而且他是对的,但事实是没有JVM实际上这样做。

我相信Sun JVM中实际发生的事情是尽可能晚地加载。每当初始化一个类时,它所引用的任何类都需要加载和验证,但它们不需要在实际使用之前进行初始化。我感谢这不是一个非常详细或权威的答案。

答案 2 :(得分:0)

我很确定它会在编译时发生。您不会在不满足所有要求和依赖性的情况下获得代码的编译版本。

如果是编译jar,我已经准备了两个类:

public class Test {
    public static void main(String[] args) {
        System.out.println("T1: Hello world");
    Test2.greet();
    }
}

public class Test2 {
    public static void greet() {
        System.out.println("T2: Hello world");
    }
}

首次尝试运行导出的项目:

$ java -jar test.jar
T1: Hello world
T2: Hello world

然后,从我的jar文件中删除Test2.class然后再次运行它:

$ java -jar test-mod.jar
T1: Hello world
Exception in thread "main" java.lang.NoClassDefFoundError: Test2
        at Test.main(Test.java:6)
Caused by: java.lang.ClassNotFoundException: Test2
        at java.net.URLClassLoader$1.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        ... 1 more

T1测试通过,然后出现NoClassDefFoundError异常。因此,回答您的问题:将在运行时检查依赖项。