在Java中查找依赖项的准确时间

在Java中查找依赖项的准确时间,java,jar,dependencies,Java,Jar,Dependencies,Java什么时候在运行时查找Jar文件的依赖项 在开始运行时? 当它试图初始化具有某些依赖项的类时? 或者其他时间?我很确定它发生在编译时。如果不满足所有要求和依赖项,就无法获得代码的编译版本 对于已编译的jar,我准备了两个类: public class Test { public static void main(String[] args) { System.out.println("T1: Hello world"); Test2.greet();

Java什么时候在运行时查找Jar文件的依赖项

在开始运行时?
当它试图初始化具有某些依赖项的类时?

或者其他时间?

我很确定它发生在编译时。如果不满足所有要求和依赖项,就无法获得代码的编译版本

对于已编译的jar,我准备了两个类:

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

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

$ 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异常。所以,回答您的问题:依赖关系将在运行时进行检查。

我非常确定它发生在编译时。如果不满足所有要求和依赖项,就无法获得代码的编译版本

对于已编译的jar,我准备了两个类:

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

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

$ 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异常。因此,回答您的问题:将在运行时检查依赖项。

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


Java指定的唯一一件事是初始化类的时间,这与加载它完全不同。

没有指定加载.class文件的确切时间。据您所知,即使在
main
方法开始执行之前,类路径中的所有类文件都可能被加载

Java指定的唯一一件事是初始化类的时间,这与加载类完全不同。

上面说(我的重点是):

本规范允许在链接活动(以及由于递归,加载)发生时实现灵活性,前提是尊重语言的语义,在初始化类或接口之前完全验证和准备类或接口,并且在链接过程中检测到的错误会在程序中的某个点抛出,在该点上,程序会执行某些操作,这些操作可能需要链接到错误所涉及的类或接口

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

现在,规范说JVM可以做一系列的事情,但是很明显,任何给定的JVM都可以做一件特定的事情。Marko的回答是“即使在
main
方法开始执行之前,类路径中的所有类文件都可能被加载”,他是对的,但事实上没有JVM真正做到这一点

我相信Sun JVM中实际发生的事情是尽可能晚地加载内容。每当一个类被初始化时,它所引用的任何类都需要被加载和验证,但是它们不需要被初始化,直到它们自己被实际使用为止。我理解这不是一个非常详细或权威的答案。

作者说(我的重点):

本规范允许在链接活动(以及由于递归,加载)发生时实现灵活性,前提是尊重语言的语义,在初始化类或接口之前完全验证和准备类或接口,并且在链接过程中检测到的错误会在程序中的某个点抛出,在该点上,程序会执行某些操作,这些操作可能需要链接到错误所涉及的类或接口

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

现在,规范说JVM可以做一系列的事情,但是很明显,任何给定的JVM都可以做一件特定的事情。Marko的回答是“即使在
main
方法开始执行之前,类路径中的所有类文件都可能被加载”,他是对的,但事实上没有JVM真正做到这一点


我相信Sun JVM中实际发生的事情是尽可能晚地加载内容。每当一个类被初始化时,它所引用的任何类都需要被加载和验证,但是它们不需要被初始化,直到它们自己被实际使用为止。我明白这不是一个非常详细或权威的答案。

显然,这不是我的答案!它在编译时需要所有依赖项,但我说的是运行时。考虑一个JAR文件的“复制版本”。好吧,我想这听起来很简单。我很快会添加新答案。显然,这不是我的答案!它在编译时需要所有依赖项,但我说的是运行时。考虑一个JAR文件的“复制版本”。好吧,我想这听起来很简单。我很快会添加新的答案。