简体   繁体   English

即使 class 文件丢失或有错误,在第一次主动使用此 class 之前,预加载 class 不会报告错误?

[英]Preloading class will not report an error until this class is first actively used even though the class file is missing or has errors?

I was reading the article below and had a question about the following passage:我正在阅读下面的文章,并对以下段落有疑问:

The jvm specification allows a class loader to preload a class when it expects it to be used,If encountered during preloading.class file is missing or has errors,The class loader must report a linkerror when the program first actively uses the class. The jvm specification allows a class loader to preload a class when it expects it to be used,If encountered during preloading.class file is missing or has errors,The class loader must report a linkerror when the program first actively uses the class. If this class has not been actively used by the program,Then the class loader will not report an error.如果这个 class 没有被程序主动使用,那么 class 加载器不会报错。

Given the following code:给定以下代码:

public class MyTest1 {
    public static void main(String[] args) {
            System.out.println(MyChild1.str); 
    }
}

class MyParent1 {
    public static  String str = "hello world";
    static {
        System.out.println("MyParent1 static block");
    }
}
class MyChild1 extends MyParent1 {
    public static String str2 = "welcome";
    static {
        System.out.println("MyChild1 static block");
    }
}

The operation result is:运行结果为:

MyParent1 static block
hello world

MyChild1 is not used actively but is loaded. MyChild1 未主动使用,但已加载。

[Loaded com.yc.test.classloader.MyParent1 from 
file:/C:/Users/nhn/IdeaProjects/demo/out/production/demo/]
[Loaded com.yc.test.classloader.MyChild1 from 
file:/C:/Users/nhn/IdeaProjects/demo/out/production/demo/]

But when I run the code above after removing the class file of MyChild1, NoClassDefFoundError occurred.但是当我在删除 MyChild1 的 class 文件后运行上面的代码时,发生了 NoClassDefFoundError。

Exception in thread "main" java.lang.NoClassDefFoundError: com/yc/test/classloader/MyChild1
    at com.yc.test.classloader.MyTest1.main(MyTest1.java:5)
Caused by: java.lang.ClassNotFoundException: com.yc.test.classloader.MyChild1
    at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:418)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:355)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:351)
    ... 1 more

The operation result contradicts with the passage.运算结果与文章相矛盾。 Why?为什么?

https://www.tutorialfor.com/blog-228663.htm https://www.tutorialfor.com/blog-228663.htm

This cited article is wrong, even with these undefined terms like “preload” and “when the program first actively uses the class”.这篇引用的文章是错误的,即使有这些未定义的术语,如“预加载”和“当程序第一次主动使用类时”。

If “preload” is supposed to mean eagerly resolving referenced classes, we can refer to the Java Language Specification, §12.1.2.如果“预加载”应该意味着急切地解析引用的类,我们可以参考 Java 语言规范, §12.1.2。 :

An implementation may resolve symbolic references from a class or interface that is being linked very early, even to the point of resolving all symbolic references from the classes and interfaces that are further referenced, recursively.实现可以解析来自 class 的符号引用或很早就被链接的接口,甚至可以递归地解析来自进一步引用的类和接口的所有符号引用。 (This resolution may result in errors from these further loading and linking steps.) (此解决方案可能会导致这些进一步的加载和链接步骤出错。)

It then states about the potential errors:然后它说明了潜在的错误:

The only requirement on when resolution is performed is that any errors detected during resolution must be thrown at a point in the program where some action is taken by the program that might, directly or indirectly, require linkage to the class or interface involved in the error.何时执行解析的唯一要求是解析期间检测到的任何错误必须在程序中执行某些操作的点抛出,这些操作可能直接或间接地需要链接到 class 或涉及错误的接口. Using the "static" example implementation choice described above, loading and linkage errors could occur before the program is executed if they involved a class or interface mentioned in the class Test or any of the further, recursively referenced, classes and interfaces.使用上述“静态”示例实现选择,如果加载和链接错误涉及 class 或 class 测试中提到的接口或任何进一步的递归引用的类和接口,则可能会在程序执行之前发生加载和链接错误

So it's definitely wrong to say that loading or linkage errors were only reportable “when the program first actively uses the class”, even when the article didn't care to explain what constitutes an active use.因此,说加载或链接错误仅在“程序第一次主动使用类时”才可报告是绝对错误的,即使这篇文章并不关心什么是主动使用。

As explained in this answer , initialization is performed under well defined conditions and the behavior of your program is understandable when overcoming the common confusion of loading and initialization .正如这个答案中所解释的,初始化是在明确定义的条件下执行的,当克服加载初始化的常见混淆时,程序的行为是可以理解的。 To evaluate the expression MyChild1.str , loading of the class MyChild1 is unavoidable and only after the class has been loaded, it is possible to determine that it doesn't have a field str but a superclass that has.要评估表达式MyChild1.str ,加载 class MyChild1是不可避免的,并且只有在加载 class 之后,才能确定它没有字段str而是具有的超类。 So while it will be unavoidably loaded it will not get initialized , as neither of the specified actions (like the access to a static field) has been performed.因此,虽然它不可避免地会被加载,但它不会被初始化,因为没有执行任何指定的操作(如访问static字段)。

As you can recognize from your stack trace, the NoClassDefFoundError has been thrown right before evaluating the expression MyChild1.str , which is already as lazy as possible.从堆栈跟踪中可以看出, NoClassDefFoundError在评估表达式MyChild1.str之前已被抛出,该表达式已经尽可能懒惰了。 Valid places to throw the error would have been the beginning of the method's execution, the loading and resolving of the Mytest1 class, or, as the linked part of the specification says, even before the execution of the entire program starts.引发错误的有效位置是方法执行的开始, Mytest1 class 的加载和解析,或者,正如规范的链接部分所说,甚至在整个程序的执行开始之前。

While the point of loading and resolving and hence, the point of throwing the error, is left to the particular implementation, all valid implementations will agree in throwing the error before coming to evaluate the expression MyChild1.str .虽然加载和解决点以及引发错误的点留给特定的实现,但所有有效的实现都会同意在评估表达式MyChild1.str之前引发错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 即使存在.class文件也没有类错误 - No class error even though the .class files are present Eclipse-即使Java文件存在编译错误,也会自动生成类文件 - Eclipse - class file is generated automatically even though java file has compilation error 即使应用程序引用了该类,该类的类成员仍会被垃圾回收 - Class member of a class is garbage collected even though the Application has a reference to it 找不到主类:即使Manifest指定了该类,Java也会出错 - Getting Could not find the main class: error in Java even though Manifest has the class specified 即使定义了类和参数,Java也找不到符号错误? - Java cannot find symbol errors even though class and parameters has been defined? 即使我在清单文件中定义了Main-class,也会出现“错误:找不到或加载类” - Getting “Error: Could not find or load class” even though I have the Main-class defined in a Manifest File ClassNotFoundException 即使 jar tvf 显示“缺少”类 - ClassNotFoundException even though jar tvf shows the 'missing' class 错误告诉我运行类中的方法未定义,即使它是 - Error telling me that the method in my run class is undefined even though it is 计时码表是空的,即使父类已将其初始化 - Chronometer is null even though parent class initialised it 即使我注册也没有注册Kryonet类 - Kryonet class not registered even though I register
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM