记类初始化一个神奇的地方

2018-05-31  本文已影响11人  言西枣

情况:
在使用Class.forName进行动态加载类的时候,默认对类进行了初始化,

Class.forName("org.reflections.serializers.XmlSerializer");

然后初始化的过程抛出了一个异常如下:

Exception in thread "main" java.lang.NoClassDefFoundError: org/dom4j/DocumentException
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:264)
    at jdk.load.Debug.main(Debug.java:16)
Caused by: java.lang.ClassNotFoundException: org.dom4j.DocumentException
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    ... 3 more

虽然说类路径下确实没有dom4j的包,但是去看了一下类的源码,并没有任何的类初始化代码,也只有一个方法里抛出了DocumentException这个异常,那么为什么初始化XmlSerializer会加载这个类呢

public class XmlSerializer implements Serializer {

    public Reflections read(InputStream inputStream) {
        Reflections reflections;
        try {
            Constructor<Reflections> constructor = Reflections.class.getDeclaredConstructor();
            constructor.setAccessible(true);
            reflections = constructor.newInstance();
        } catch (Exception e) {
            reflections = new Reflections(new ConfigurationBuilder());
        }

        try {
            Document document = new SAXReader().read(inputStream);
            for (Object e1 : document.getRootElement().elements()) {
                Element index = (Element) e1;
                for (Object e2 : index.elements()) {
                    Element entry = (Element) e2;
                    Element key = entry.element("key");
                    Element values = entry.element("values");
                    for (Object o3 : values.elements()) {
                        Element value = (Element) o3;
                        reflections.getStore().getOrCreate(index.getName()).put(key.getText(), value.getText());
                    }
                }
            }
        } catch (DocumentException e) {
            throw new ReflectionsException("could not read.", e);
        } catch (Throwable e) {
            throw new RuntimeException("Could not read. Make sure relevant dependencies exist on classpath.", e);
        }

        return reflections;
    }
}

于是自己写了一小段代码,TestClass只包括了一个抛出这个异常的方法,进行试验,发现初始化类的时候,确实加载了这个异常类:



在方法中去掉catch语句之后,就不会加载这个类了。

总结一下:类中的方法抛出了checked异常之后,无论是throws或者catch了,那么这个异常都会在这个类初始化的时候被加载,如果不初始化这个类,那么异常也不会被加载。

上一篇下一篇

猜你喜欢

热点阅读