浏览 4089 次
锁定老帖子 主题:Class loading之惑
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2007-01-25
问题是这样,假设有一个class A,在它的某个方法test()中引用了class B, 如果A在运行的过程没有执行到test(),根据load class on demand的原理,B就不会没load。 代码如下: java 代码
打开verbose选项可以看到B并不会被load,符合我们的习惯性认识。但是如果现在加入一个interface C,在test()方法中创建一个C的实例,并调用该实例的某个方法,就可以看到即使test()方法没有执行,C依然会被load到虚拟机中! java 代码
摘一段执行的log: …… [Loaded java.security.cert.Certificate from C:\jdk150_04_for_netbeans\jre\lib\rt.jar] [Loaded A from file:/D:/eclipse-SDK-3.2-win32/workspace/cl/] [Loaded C from file:/D:/eclipse-SDK-3.2-win32/workspace/cl/] hello class loading [Loaded java.lang.Shutdown from C:\jdk150_04_for_netbeans\jre\lib\rt.jar] [Loaded java.lang.Shutdown$Lock from C:\jdk150_04_for_netbeans\jre\lib\rt.jar] 如果不用匿名类,而使用一个具体的C的实现CImpl,情况会略有不同:如果引用的是interface,即C c= new CImpl(); C依然会被load进来,如果引用是实现类,即CImpl c = new CImpl(); 则C和CImpl都不会被load。 查了language spec也没有找到理论依据,那位给解释解释这是什么原因造成的? 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2007-01-25
应该是虚拟机进行字节码验证的时候对类型进行检查引起的。
如果用接口C引用CImpl,classloader应该会载入C和CImpl来检查C是否能够引用CImpl。 如果是用CImpl引用CImpl的话,就不需要载入来进行验证了。 这个是我推测的,不一定正确。 |
|
返回顶楼 | |
发表时间:2007-01-26
foxty 写道 应该是虚拟机进行字节码验证的时候对类型进行检查引起的。
谢谢,但是我的问题是:为什么方法test()并没有被执行,接口C却被载入了呢?因为即使我使用匿名类,接口C依然会被载入进来。
如果用接口C引用CImpl,classloader应该会载入C和CImpl来检查C是否能够引用CImpl。 如果是用CImpl引用CImpl的话,就不需要载入来进行验证了。 这个是我推测的,不一定正确。 |
|
返回顶楼 | |
发表时间:2007-01-26
内部匿名类随类装载而装载,由于内部匿名类是继承法了接口C, 在装载过程中必须认识"C"才能装匿名类.
|
|
返回顶楼 | |
发表时间:2007-01-26
都是高手
|
|
返回顶楼 | |
发表时间:2007-01-27
it's tricky, should avoid?
|
|
返回顶楼 | |
发表时间:2007-01-28
terrine 写道 foxty 写道 应该是虚拟机进行字节码验证的时候对类型进行检查引起的。
谢谢,但是我的问题是:为什么方法test()并没有被执行,接口C却被载入了呢?因为即使我使用匿名类,接口C依然会被载入进来。如果用接口C引用CImpl,classloader应该会载入C和CImpl来检查C是否能够引用CImpl。 如果是用CImpl引用CImpl的话,就不需要载入来进行验证了。 这个是我推测的,不一定正确。 虚拟机进行字节码验证的时候会对整个类的字节码进行验证,所以这里跟你执行不执行没有关系。 |
|
返回顶楼 | |
发表时间:2007-01-28
foxty,假设这里只有一句
C c = new CImpl(); 并不使用变量c(c作为参数或者调用c的方法),可以看到C和CImpl都不会被装载进来。你所说的对字节码进行验证指的是什么呢?按照你之前的说法,这里依然用接口C引用了CImpl,C和CImpl就应该也被装载进来才对。 |
|
返回顶楼 | |