[color=red]自己实现了一个classLoader,代码如下[/color]
[color=red]类 SuC [/color]
package com.load;
public class SuC {
}
[color=red]接口 InterTest [/color]
package com.load;
public interface InterTest {
}
[color=red]类 TestIt[/color]
package com.load;
public class TestIt extends SuC implements InterTest {
}
[color=red]主类 MyClassLoader[/color]
[size=medium]package com.load;
import java.io.InputStream;
import java.lang.reflect.Method;
public class MyClassLoader extends ClassLoader{
public Class create() throws Exception{
[color=green] //装载TestIt这个类[/color]
InputStream is = this.getClass().getClassLoader().getResourceAsStream("com/load/TestIt.class");
int le = is.available();
byte[] b = new byte[le];
is.read(b, 0, le);
Class cls = defineClass("com.load.TestIt",b,0,b.length);
[color=green]//使用反射看看app加载器里是否装载[/color]
ClassLoader classLoader = getSystemClassLoader();
Method method = ClassLoader.class.getDeclaredMethod("findLoadedClass", String.class);
method.setAccessible(true);
Object ccl = method.invoke(classLoader, "com.load.SuC");
[color=green]//输出一下[/color] System.out.println(ccl);
System.out.println(((Class)ccl).getClassLoader());
System.out.println(findLoadedClass("com.load.SuC").getClassLoader());
[color=green]//装载TestIt的父类[/color] InputStream iss = this.getClass().getClassLoader().getResourceAsStream("com/load/SuC.class");
int lee = iss.available();
byte[] bb = new byte[lee];
iss.read(bb, 0, lee);
Class clss = defineClass("com.load.SuC",bb,0,bb.length);
return cls;
}
public static void main(String []args) throws Exception{
MyClassLoader myCla = new MyClassLoader();
myCla.create();
}
}[/size]
[size=medium][color=darkred] main方法中调用create方法,装载TestIt这个类,没有问题,利用反射输出一下,发现TestIt的父类SuC已经被系统类加载器加载。此时再去用defineClass加载SuC的字节流,则会抛出异常。[/color][/size]
[color=red]class com.load.SuC
sun.misc.Launcher$AppClassLoader@19821f
sun.misc.Launcher$AppClassLoader@19821f
Exception in thread "main" java.lang.LinkageError: loader (instance of com/load/MyClassLoader): attempted duplicate class definition for name: "com/load/SuC"
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(Unknown Source)
at java.lang.ClassLoader.defineClass(Unknown Source)
at com.load.MyClassLoader.create(MyClassLoader.java:30)
at com.load.MyClassLoader.main(MyClassLoader.java:45)[/color]
[color=red] 如果不加载SuC就没事。
或者SuC放在TestIt之前也没事,此时调整一下代码[/color][size=medium]package com.load;
import java.io.InputStream;
import java.lang.reflect.Method;
public class MyClassLoader extends ClassLoader{
public Class create() throws Exception{
InputStream iss = this.getClass().getClassLoader().getResourceAsStream("com/load/SuC.class");
int lee = iss.available();
byte[] bb = new byte[lee];
iss.read(bb, 0, lee);
Class clss = defineClass("com.load.SuC",bb,0,bb.length);
InputStream is = this.getClass().getClassLoader().getResourceAsStream("com/load/TestIt.class");
int le = is.available();
byte[] b = new byte[le];
is.read(b, 0, le);
Class cls = defineClass("com.load.TestIt",b,0,b.length);
ClassLoader classLoader = getSystemClassLoader();
Method method = ClassLoader.class.getDeclaredMethod("findLoadedClass", String.class);
method.setAccessible(true);
Object ccl = method.invoke(classLoader, "com.load.SuC");
System.out.println(findLoadedClass("com.load.SuC").getClassLoader());
System.out.println(ccl);
System.out.println(((Class)ccl).getClassLoader());
return cls;
}
public static void main(String []args) throws Exception{
MyClassLoader myCla = new MyClassLoader();
myCla.create();
}
}[/size]
[color=red]输出com.load.MyClassLoader@c17164
null
Exception in thread "main" java.lang.NullPointerException
at com.load.MyClassLoader.create(MyClassLoader.java:32)
at com.load.MyClassLoader.main(MyClassLoader.java:42)[/color]
[size=medium][color=darkred]我想问的是为什么SuC做为父类在TestIt被加载后,它自己被系统classloader加载。为何用在MyClassLoader里用defineClass再去加载字节流会出现java.lang.LinkageError的异常呢?MyClassLoader的实例应该没有加载过SuC。[/color][/size]