(需要真懂JVM的高人)Java隐式类加载的结果在JVM中是不是有缓存,怎么规避

赵建勇 发布于 2014/07/25 21:35
阅读 868
收藏 1

【Gopher China万字分享】华为云的Go语言云原生实战经验!>>>

Java隐式类加载的结果在JVM中是不是有缓存,在什么doc中有说明?

为什么显示类加载可以成功的时候,隐式类加载还是失败。

下面代码,运行结果是什么?

package test;

import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.concurrent.atomic.AtomicInteger;

public class Test {

    public static void main(String[] args) throws Exception {
        
        MyClassLoader myClassLoader = new MyClassLoader();
        
        Class cClass = myClassLoader.loadClass("test.C");
        Object cObject = cClass.newInstance();
        Method printMethod = cClass.getMethod("print");
        
        testImplicitClassLoad(cObject, printMethod);
        
        testExplicitClassLoad(myClassLoader);
    }
    
    private static void testImplicitClassLoad(Object cObject, Method printMethod) {
        for (int i = 0; i < 3; i++) {
            System.out.println("==============testImplicitClassLoad=====================");
            try {
                printMethod.invoke(cObject);
            } catch (Exception e) {
                System.out.println("implicit class load failed. " + e.getCause());
            }
        }
    }
    
    private static void testExplicitClassLoad(ClassLoader classLoader) throws ClassNotFoundException {
        System.out.println("==============testExplicitClassLoad=====================");
        System.out.println("test.B loaded..." + classLoader.loadClass("test.B"));
        System.out.println("test.A loaded..." + classLoader.loadClass("test.A"));
    }
}

class MyClassLoader extends URLClassLoader {
    
    private AtomicInteger count = new AtomicInteger(0);
    
    public MyClassLoader() {
        super(getMyURLs(), null);
    }
    
    private static URL[] getMyURLs() {
        URL[] urls = {Thread.currentThread().getContextClassLoader().getResource("")};
        return urls;
    }
    
    @Override
    protected Class<?> loadClass(String name, boolean resolve)
            throws ClassNotFoundException {
        //System.out.println(name);
        
        if (name.contains("A") && count.getAndIncrement() == 0)
        {
            throw new ClassNotFoundException("A");
        }
        
        return super.loadClass(name, resolve);
    }
}

package test;

public class A {
    public void print() {
        System.out.println("A");
    }
}

package test;

public class B extends A{
    @Override
    public void print() {
        System.out.println("B");
    }
}

package test;

public class C {
    public void print() {
        new B().print();
    }
}

+++++++++++++++++++JDK5++++++++++++++++++++

==============testImplicitClassLoad=====================
implicit class load failed. java.lang.NoClassDefFoundError: test/A
==============testImplicitClassLoad=====================
B
==============testImplicitClassLoad=====================
B
==============testExplicitClassLoad=====================
test.B loaded...class test.B
test.A loaded...class test.A

+++++++++++++++++++++++++++++++++++++++++++++++++

++++++++++++++++JDK6/JDK7/JDK8++++++++++++++++++++++

==============testImplicitClassLoad=====================
implicit class load failed. java.lang.NoClassDefFoundError: test/A
==============testImplicitClassLoad=====================
implicit class load failed. java.lang.NoClassDefFoundError: test/B
==============testImplicitClassLoad=====================
implicit class load failed. java.lang.NoClassDefFoundError: test/B
==============testExplicitClassLoad=====================
test.B loaded...class test.B
test.A loaded...class test.A

+++++++++++++++++++++++++++++++++++++++++++++++++


加载中
0
大萌王朝首席槽点师
大萌王朝首席槽点师
请看java语言规范
赵建勇
赵建勇
你这个回答太忽悠了…怎么的也要说请看jvm规范吧…呵呵
0
赵建勇
赵建勇

我大概知道原因了。jvm的规范就是说了,第一次加载失败后,类就处于错误的状态,后续的加载 都会失败。

Java虚拟机规范(JavaSE7)-5.5 初始化

===============================

如果C的Class对象显示它处于一个错误的状态,就不再初始化了。释放LC并抛出NoClassDefFoundError异常。

===============================

见:http://stackoverflow.com/questions/6352215/java-why-java-lang-noclassdeffounderror-caused-by-static-field-initializ-failur

0
赵建勇
赵建勇
但是,为什么JDK5不是这样呢? 为什么手工加载成功后,不自动回复呢?
OSCHINA
登录后可查看更多优质内容
返回顶部
顶部