记类初始化一个神奇的地方
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了,那么这个异常都会在这个类初始化的时候被加载,如果不初始化这个类,那么异常也不会被加载。