现在运行之前,我删除了从类路径依赖的jar。我在方法init()中引用了类“dummyexception”的'ClassNotFoundException',而不是方法init2()中的用法。
类dummy2
只会在init方法执行时加载。尽管dummyexcetion
是一个catch参数,所以JVM处理这个类,就像java方法一样。对于dummyexception
类全名被放置到JVM * .class文件constant_pool和JVM检查级别的可用性之前dummy
加载。
让我们来看一个例子:
public class Dummy {
public void init(){
DummyExternal dummy = new DummyExternal();
try {
dummy.run();
} catch(DummyException e) {
} catch(Exception e){ }
}
public void init2(){
new Runnable() {
@Override
public void run() {
DummyExternal dummy = new DummyExternal();
try {
dummy.run();
} catch(DummyException e) {
e.printStackTrace();
} catch(Exception e){}
}
}.run();
}
public static void main(String[] args){
System.out.println("hello world");
}
}
public class DummyException extends RuntimeException {
private static final long serialVersionUID = 2049347223914508696L;
static {
System.out.println("DummyException");
}
}
public class DummyExternal implements Runnable {
static {
System.out.println("DummyExternal");
}
@Override
public void run() {
System.out.println("DummyExternal");
}
}
在输出我们将有:
-RW-R - R-- 1个taky人员756B 5月19日08:26虚拟$ 1.class
-RW-R - R-- 1个taky人员956B 5月19日08:26 Dummy.class
-RW-R - R-- 1个taky人员545B 5月19日08:26 DummyException.class
-RW-R - R-- 1个taky人员569B 5月19日08:26 DummyExternal.class
命令java Dummy
打印hello world
。所以没有加载DummyExternal
或DummyException
类。
删除DummyExternal
类文件:rm DummyExternal.class
。 java Dummy
的结果不变。
让我们删除DummyException
类文件:rm DummyException.class
。
和java Dummy
执行后,我们收到有趣的堆栈跟踪。
Exception in thread "main" java.lang.NoClassDefFoundError: DummyException
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2442)
at java.lang.Class.getMethod0(Class.java:2685)
at java.lang.Class.getMethod(Class.java:1620)
at sun.launcher.LauncherHelper.getMainMethod(LauncherHelper.java:494)
at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:486)
Caused by: java.lang.ClassNotFoundException: DummyException
at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
... 6 more
此行为是因为异常处理机制。如果class是catch参数,则生成异常处理程序,处理异常时应处理这些异常处理程序。异常处理机制与方法调用类似,ClassLoader在加载类之前从常量池中解析DummyException
。
您的代码示例在这里值得一千字。 – Perception
谁在调用'init()'或'init2()'? –
@RaviTrivedi假设init()和init2()从来没有调用 – Taky