Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/310.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 卸载类加载器_Java_Garbage Collection_Classloader - Fatal编程技术网

Java 卸载类加载器

Java 卸载类加载器,java,garbage-collection,classloader,Java,Garbage Collection,Classloader,我的最终目标是能够在类已经加载到JVM之后重新加载它们 在阅读了下面的答案之后,我一直在尝试实现我自己的类加载器,它本身为它加载的每个类创建一个不同的类加载器实例(它自己的相同类型) 因此,结果是每个类装入器一个类 这样做的目的是能够GC类,也就是它的所有实例,然后卸载它的类加载器,并且能够从它的字节中重新加载相同的类 问题是-我可以看到我的类实例正在使用finalize()方法进行垃圾收集,但我无法让我的类加载器卸载或进行垃圾收集。 是否有任何代码示例,一个简单的测试,来说明如何实现它 谢谢,

我的最终目标是能够在类已经加载到JVM之后重新加载它们

在阅读了下面的答案之后,我一直在尝试实现我自己的类加载器,它本身为它加载的每个类创建一个不同的类加载器实例(它自己的相同类型)

因此,结果是每个类装入器一个类

这样做的目的是能够GC类,也就是它的所有实例,然后卸载它的类加载器,并且能够从它的字节中重新加载相同的类

问题是-我可以看到我的类实例正在使用finalize()方法进行垃圾收集,但我无法让我的类加载器卸载或进行垃圾收集。
是否有任何代码示例,一个简单的测试,来说明如何实现它

谢谢,任何帮助都将不胜感激

编辑


更清楚地说,我对代码示例感兴趣,其中新对象的实例化是通过“new()”操作数进行的,并且类装入器没有在main中显式地重新装入类,而是在调用下一个“new()”之后。

如果没有更多的引用,则应该对类装入器进行垃圾收集。我从@PeterLawrey(谢谢)(它做的事情和你的一样),在自定义类加载器
finalize()
方法中放入一个日志,瞧,类加载器在加载的类是gc之后被垃圾收集:

 /* Copyright (c) 2011.  Peter Lawrey
 *
 * "THE BEER-WARE LICENSE" (Revision 128)
 * As long as you retain this notice you can do whatever you want with this stuff.
 * If we meet some day, and you think this stuff is worth it, you can buy me a beer in return
 * There is no warranty.
 */


import java.lang.reflect.Field;
import java.net.URL;
import java.net.URLClassLoader;

public class LoadAndUnloadMain {
    public static void main(String... args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, InterruptedException {
        URL url = LoadAndUnloadMain.class.getProtectionDomain().getCodeSource().getLocation();
        final String className = LoadAndUnloadMain.class.getPackage().getName() + ".UtilityClass";
        {
            ClassLoader cl;
            Class clazz;

            for (int i = 0; i < 2; i++) {
                cl = new CustomClassLoader(url);
                clazz = cl.loadClass(className);
                loadClass(clazz);

                cl = new CustomClassLoader(url);
                clazz = cl.loadClass(className);
                loadClass(clazz);
                triggerGC();
            }
        }
        triggerGC();
    }

    private static void triggerGC() throws InterruptedException {
        System.out.println("\n-- Starting GC");
        System.gc();
        Thread.sleep(100);
        System.out.println("-- End of GC\n");
    }

    private static void loadClass(Class clazz) throws NoSuchFieldException, IllegalAccessException {
        final Field id = clazz.getDeclaredField("ID");
        id.setAccessible(true);
        id.get(null);
    }

    private static class CustomClassLoader extends URLClassLoader {
        public CustomClassLoader(URL url) {
            super(new URL[]{url}, null);
        }

        @Override
        protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
            try {
                return super.loadClass(name, resolve);
            } catch (ClassNotFoundException e) {
                return Class.forName(name, resolve, LoadAndUnloadMain.class.getClassLoader());
            }
        }

        @Override
        protected void finalize() throws Throwable {
            super.finalize();
            System.out.println(this.toString() + " - CL Finalized.");
        }
    }
}

class UtilityClass {
    static final String ID = Integer.toHexString(System.identityHashCode(UtilityClass.class));
    private static final Object FINAL = new Object() {
        @Override
        protected void finalize() throws Throwable {
            super.finalize();
            System.out.println(ID + " Finalized.");
        }
    };

    static {
        System.out.println(ID + " Initialising");
    }
}
/*版权所有(c)2011。彼得·劳瑞
*
*“啤酒用具许可证”(第128版)
*只要你保留这个通知,你可以用它做任何你想做的事情。
*如果有一天我们见面,你觉得这些东西值得,你可以给我买杯啤酒作为回报
*没有担保。
*/
导入java.lang.reflect.Field;
导入java.net.URL;
导入java.net.URLClassLoader;
公共类LoadAndUnloadMain{
publicstaticvoidmain(String…args)抛出ClassNotFoundException、NoSuchFieldException、IllegalAccessException、interruptedeexception{
URL URL=LoadAndUnloadMain.class.getProtectionDomain().getCodeSource().getLocation();
最后一个字符串className=LoadAndUnloadMain.class.getPackage().getName()+“.UtilityClass”;
{
类加载器cl;
课堂讨论;
对于(int i=0;i<2;i++){
cl=新CustomClassLoader(url);
clazz=cl.loadClass(类名);
载荷等级(clazz);
cl=新CustomClassLoader(url);
clazz=cl.loadClass(类名);
载荷等级(clazz);
triggerGC();
}
}
triggerGC();
}
私有静态void triggerGC()引发InterruptedException{
System.out.println(“\n——启动GC”);
gc();
睡眠(100);
System.out.println(“--GC结尾\n”);
}
私有静态void loadClass(Class clazz)抛出NoSuchFieldException、IllegalAccessException{
最终字段id=clazz.getDeclaredField(“id”);
id.setAccessible(true);
id.get(null);
}
私有静态类CustomClassLoader扩展了URLClassLoader{
公共CustomClassLoader(URL){
超级(新URL[]{URL},空);
}
@凌驾
受保护类loadClass(字符串名称,布尔解析)引发ClassNotFoundException{
试一试{
返回super.loadClass(名称、解析);
}catch(classnotfounde异常){
返回Class.forName(name、resolve、LoadAndUnloadMain.Class.getClassLoader());
}
}
@凌驾
受保护的void finalize()抛出可丢弃的{
super.finalize();
System.out.println(this.toString()+“-CL定稿”);
}
}
}
类实用类{
静态最终字符串ID=Integer.toHexString(System.identityHashCode(UtilityClass.class));
私有静态最终对象final=新对象(){
@凌驾
受保护的void finalize()抛出可丢弃的{
super.finalize();
System.out.println(ID+“Finalized.”);
}
};
静止的{
System.out.println(ID+“初始化”);
}
}

IBMJ9VM中,情况有所不同,因为类加载器卸载只在全局gc期间发生。这可能会导致全局gc中出现大量暂停时间,并在存在大量数据时导致内存不足
正在创建的类加载器。我在JMXMP中遇到了这个问题,其中为类型为
MBeanServerRequestMessage.CREATE_MBEAN_LOADER_PARAMS
的每个远程消息创建了
com.sun.jmx.remote.opt.util.OrderClassLoaders
classloader的一个实例

谢谢,我对通过“new()”操作数显示类实例的代码示例更感兴趣,很抱歉我的问题不清楚,我将对其进行编辑。当您通过自定义
ClassLoader
加载类时,您将得到一个
class
对象。不可能将
新的
运算符与此一起使用。使用
new
意味着您的代码已链接到
new
使用的类,因此,当包含
new
表达式的代码仍处于活动状态时,该类无法被垃圾收集。此时必须使用反射,例如在
类上调用
newInstance()
。当然,动态加载的代码本身可以使用
new
在其自己的范围内实例化类。