java接口中表示错误的,为什么包含一个方法的类调用缺少的接口在未使用的代码中会导致Java类加载错误?...

我看到一些似乎与JVM规范不一致的类加载行为,我想知道这是否是一个错误.或者如果没有,希望有人可以解释为什么.

下面的示例代码简单地从其main方法打印出hello.它有一个未使用的方法,它包含一个方法调用方法,该方法声明它将一个“C”(这是一个接口)作为参数.

当执行main(在类路径中没有A,B和C)时,将为C接口引发ClassNotFound错误.(注意C在运行时从来不是实际需要的,因为它仅在一个永远不执行的方法中被引用).

这似乎违反了JVM规范

Java VM规范第2.17.1节第2版说:

The only requirement regarding 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

Java VM规范第2.17.3节第2版说:

The Java programming language allows an implementation flexibility as to when linking activities (and, because of recursion, loading) take place, provided that the semantics of the language are respected, that a class or interface is completely verified and prepared before it is initialized, and that errors detected during linkage are thrown at a point in the program where some action is taken by the program that might require linkage to the class or interface involved in the error.

注意:如果我将定义中的参数类型更改为类而不是接口,则代码将正确加载并执行.

/**

* This version fails, the method call in neverCalled() is to a method whose

* parameter definition is for an Interface

*/

public class Main {

public void neverCalled(){

A a = new A();

B b = new B(); // B implements C

//method takeInter is declared to take paramters of type Interface C

//This code is causes a ClassNotFound error do be thrown when Main

//is loaded if A, B, and C is not in the class path

a.takeInter(b);

}

public static void main(String[] args) {

System.out.println("Hello...");

}

}

/**

* This version runs, the method call in neverCalled() is to a method whose

* parameter definition is for a Class

*/

public class Main {

public void neverCalled(){

A a = new A();

B b = new B(); // B implements C

//method takeInter is declared to take paramters of type Interface C

//This code is causes a ClassNotFound error do be thrown when Main

//is loaded if A, B, and C is not in the class path

a.takeClass(b);

}

public static void main(String[] args) {

System.out.println("Hello...");

}

}

public class A {

public void takeClass(B in){};

public void takeInter(C in){}

}

public class B implements C {}

public interface C {}

埃德,

我没有故意试图把引用从上下文中抽出出来,我认为是相关的部分.感谢您帮助我尝试了解这一点.

无论如何,这个规范对我来说似乎很清楚.它表示错误必须抛在一个点上.在阅读了Java虚拟机的第8章之后,我阅读了VM规范,所以也许这样对我的解释有所了解.

As described in Chapter 7, “The Lifetime of a Class,” different implementations of the Java virtual machine are permitted to perform resolution at different times during the execution of a program. An implementation may choose to link everything up front by following all symbolic references from the initial class, then all symbolic references from subsequent classes, until every symbolic reference has been resolved. In this case, the application would be completely linked before its main() method was ever invoked. This approach is called early resolution. Alternatively, an implementation may choose to wait until the very last minute to resolve each symbolic reference. In this case, the Java virtual machine would resolve a symbolic reference only when it is first used by the running program. This approach is called late resolution. Implementations may also use a resolution strategy in-between these two extremes.

Although a Java virtual machine implementation has some freedom in choosing when to resolve symbolic references, every Java virtual machine must give the outward impression that it uses late resolution. No matter when a particular Java virtual machine performs its resolution, it will always throw any error that results from attempting to resolve a symbolic reference at the point in the execution of the program where the symbolic reference was actually used for the first time. In this way, it will always appear to the user as if the resolution were late. If a Java virtual machine does early resolution, and during early resolution discovers that a class file is missing, it won’t report the class file missing by throwing the appropriate error until later in the program when something in that class file is actually used. If the class is never used by the program, the error will never be thrown.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值