现在在运行之前,我从类路径中删除了依赖 jar。对于方法 init() 中引用的类“dummyexception”而不是方法 init2() 中的用法,我得到了“ClassNotFoundException”。
dummy2
只有在执行 init 方法时才会加载类。尽管dummyexcetion
是一个catch参数,所以JVM处理这个类,作为java方法。类的全名dummyexception
放在 jvm *.class 文件constant_pooldummy
中,JVM 在加载之前检查类的可用性。
让我们考虑一个例子:
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 Dummy$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 参数,则生成异常处理程序,在处理异常时应解决该异常处理程序。异常处理机制类似于方法调用和类加载器DummyException
在类加载之前从常量池中解析。