NoClassDefFoundError异常分析 & 类的立即加载
现象:Java进程启动后,在new TestClassByJxn()对象时,抛出异常:java.lang.NoClassDefFoundError: com/jxn/TestClassByJxn
原因:
java进程启动后,并不会立即加载TestClassByJxn类,当new TestClassByJxn()对象时,jvm去加载TestClassByJxn这个类的时候发现找不到该类对应的class文件,故抛出异常。
分析:
java进程启动的时候,classpath下是存在TestClassByJxn.class文件的,
当java进程启动后,classpath下的TestClassByJxn.class文件被删除了。
如果在删除TestClassByJxn.class文件之前TestClassByJxn类没有被加载过,那么之后在加载TestClassByJxn类时,就会抛NoClassDefFoundError的异常。
解决:
在java进程启动后,主动加载该类。
ClassLoader.getSystemClassLoader().loadClass("com.jxn.TestClassByJxn");
补充:
/**
* 立即加载classpath下的jar包中指定包名下的所有类。
*
* 注意:以jar包形式直接启动的java进程,其classpath即该jar包。
*/
public class MyClassloader {
public static void loadJxnClass() {
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
try {
Enumeration<URL> urls = classLoader.getResources("com/jxn/test");
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
if ("jar".equals(url.getProtocol())) {
JarURLConnection jarURLConnection = (JarURLConnection) url.openConnection();
JarFile jarFile = jarURLConnection.getJarFile();
if (jarFile == null) {
continue;
}
Enumeration<JarEntry> jarEntries = jarFile.entries();
while (jarEntries.hasMoreElements()) {
JarEntry jarEntry = jarEntries.nextElement();
String jarEntryName = jarEntry.getName();
if (jarEntryName.endsWith(".class") && jarEntryName.startsWith("com/jxn/test")) {
String className =
jarEntryName.substring(0, jarEntryName.lastIndexOf(".")).replaceAll("/", ".");
classLoader.loadClass(className);
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 立即加载非classpath下jar包中指定的类。
*/
public void loadClass(String className) throws Exception {
// 新建一个URLClassLoader
ClassLoader classLoader = new URLClassLoader(new URL[]{}, ClassLoader.getSystemClassLoader());
// jar包的路径
File jarFile = new File("jar包的路径");
// 通过反射的方式调用URLClassLoader的addURL方法。
Method addURL = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
addURL.setAccessible(true);
addURL.invoke(classLoader, jarFile.toURI().toURL());
// 加载指定的类
classLoader.loadClass(className);
}