我在j2se1.4+tomcat5.5下,自己写了一个ClassLoader,后来用内存调试工具一看,每次我自己的ClassLoader运行完,都不能被GC。仔细一看,觉得问题如下:MyClassLoader引用了一个ProtectionDomain对象,而这个ProtectionDomain对象内部又存放着一个指向MyClassLoader的引用。这样就形成了循环引用:MyClassLoader->ProtectionDomain->MyClassLoader. java代码: public class MyClassLoader extends ClassLoader {
private HashMap classDatas;
private ClassLoader parent;
public MyClassLoader(HashMap classDatas, ClassLoader parent){
super(parent);
this.classDatas = classDatas;
this.parent = parent;
}
public Class loadClass(String name) throws ClassNotFoundException{
Class clazz;
try {
clazz= parent.loadClass(name);
}catch (ClassNotFoundException e) {
byte[] data = (byte[])classDatas.get(name);
if (data == null || data.length == 0) {
throw new ClassNotFoundException(name);
}
clazz = defineClass(name, data, 0, data.length);
resolveClass(clazz);
}
if ( clazz == null ){
throw new ClassNotFoundException(name);
}
return clazz;
}
} 首先:MyClassLoader->ProtectionDomain的产生:
ProtectionDomain是在基类ClassLoader中定义的,所以MyClassLoader也就拥有了一个ProtectionDomain的引用。
第二:ProtectionDomain->MyClassLoader的产生:
在基类的defineClass(...)中,会构造一个ProtectionDomain的对象,构造时,会把当前的class loader的实例传进去。这样ProtectionDomain就拥有了一个MyClassLoader的引用。 所以MyClassLoader->ProtectionDomain->MyClassLoader的循环应用产生了。 而在这种情况下,GC不会自动回收MyClassLoader对象。就会出现memory leak了。
private HashMap classDatas;
private ClassLoader parent;
public MyClassLoader(HashMap classDatas, ClassLoader parent){
super(parent);
this.classDatas = classDatas;
this.parent = parent;
}
public Class loadClass(String name) throws ClassNotFoundException{
Class clazz;
try {
clazz= parent.loadClass(name);
}catch (ClassNotFoundException e) {
byte[] data = (byte[])classDatas.get(name);
if (data == null || data.length == 0) {
throw new ClassNotFoundException(name);
}
clazz = defineClass(name, data, 0, data.length);
resolveClass(clazz);
}
if ( clazz == null ){
throw new ClassNotFoundException(name);
}
return clazz;
}
} 首先:MyClassLoader->ProtectionDomain的产生:
ProtectionDomain是在基类ClassLoader中定义的,所以MyClassLoader也就拥有了一个ProtectionDomain的引用。
第二:ProtectionDomain->MyClassLoader的产生:
在基类的defineClass(...)中,会构造一个ProtectionDomain的对象,构造时,会把当前的class loader的实例传进去。这样ProtectionDomain就拥有了一个MyClassLoader的引用。 所以MyClassLoader->ProtectionDomain->MyClassLoader的循环应用产生了。 而在这种情况下,GC不会自动回收MyClassLoader对象。就会出现memory leak了。
看你的代码,为什么不用组合,要用继承呢