字节码文件位置是:“D:\ginazhou\lib\com\itheima\my\Student.class”
- test1()正常
- test2()报错:java.lang.NoClassDefFoundError:
com/itheima/my/Student (wrong name: Student)
java.lang.NoClassDefFoundError: com/itheima/my/Student (wrong name: Student)
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:756)
at java.lang.ClassLoader.defineClass(ClassLoader.java:635)
at classloader.broken.BreakClassLoader1.loadClass(BreakClassLoader1.java:55)
at classloader.broken.BreakClassLoader1.test2(BreakClassLoader1.java:82)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38)
at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:232)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:55)
上源代码:
/**
* 打破双亲委派机制 - 自定义类加载器
*/
public class BreakClassLoader1 extends ClassLoader {
private String basePath;
private final static String FILE_EXT = ".class";
public void setBasePath(String basePath) {
this.basePath = basePath;
}
private byte[] loadClassData(String name) {
try {
String tempName = name.replaceAll("\\.", Matcher.quoteReplacement(File.separator));
FileInputStream fis = new FileInputStream(basePath + tempName + FILE_EXT);
try {
return IOUtils.toByteArray(fis);
} finally {
IOUtils.closeQuietly(fis);
}
} catch (Exception e) {
System.out.println("自定义类加载器加载失败,错误原因:" + e.getMessage());
return null;
}
}
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
Class<?> clazz = findLoadedClass(name);
if (clazz != null) {
return clazz;
}
// 委派给父加载器
if (name.startsWith("java.")) {
return super.loadClass(name);
}
// 加载类文件
byte[] data = loadClassData(name);
if (data == null) {
throw new ClassNotFoundException("Failed to load class: " + name);
}
// 定义类
return defineClass(name, data, 0, data.length);
}
@Test
public void test1() throws ClassNotFoundException {
BreakClassLoader1 classLoader1 = new BreakClassLoader1();
classLoader1.setBasePath("D:\\ginazhou\\lib\\com\\itheima\\my\\");
System.out.println(classLoader1);
System.out.println(classLoader1.getParent());
System.out.println(getSystemClassLoader());
Class<?> clazz1 = classLoader1.loadClass("Student");
System.out.println(clazz1);
System.out.println(clazz1.getClassLoader());
}
@Test
public void test2() throws ClassNotFoundException {
BreakClassLoader1 classLoader1 = new BreakClassLoader1();
classLoader1.setBasePath("D:\\ginazhou\\lib\\");
System.out.println(classLoader1);
System.out.println(classLoader1.getParent());
System.out.println(getSystemClassLoader());
Class<?> clazz1 = classLoader1.loadClass("com.itheima.my.Student");
System.out.println(clazz1);
System.out.println(clazz1.getClassLoader());
}
}
问题:问题出在 defineClass() 方法中的第一个参数,即类的简单名称。只需要传类的简单名称Student就行,不要传全限定名 com.itheima.my.Student!!
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
Class<?> clazz = findLoadedClass(name);
if (clazz != null) {
return clazz;
}
// 委派给父加载器
if (name.startsWith("java.")) {
return super.loadClass(name);
}
// 加载类文件
byte[] data = loadClassData(name);
if (data == null) {
throw new ClassNotFoundException("Failed to load class: " + name);
}
// 定义类(修改此处!!)
String[] str= name.split("\\.");
return defineClass(str[str.length-1], data, 0, data.length);
}
运行成功