在运行时卸载类

时间:2015-07-16 18:53:15

标签: java spring jvm osgi loading

我需要在运行时卸载类。我有一个在运行时初始化的自定义类加载器。此类加载器加载较新版本的类。此类也可以在运行时更新。在这种情况下,我想删除旧版本的类加载器,以便可以从GC中删除旧类和旧类加载器。我要交换的课程是春季服务。这个改变是有效的,但不是从堆中删除旧版本的类。

我从自定义类加载器中删除了旧类,从systemclassloader中删除了旧的类加载器,并将自定义类加载器中的父类设置为每次反射为null。

@SuppressWarnings("unchecked")
private static void findAndDeleteClass(final Class<?> clazz, ClassLoader classClassLoader,
        final Field classLoaderFields) throws IllegalArgumentException, IllegalAccessException {
    if (classClassLoader == null) {
        return;
    }
    final List<VectorElement> swapElements = new ArrayList<VectorElement>();
    final Vector<Class<?>> classLoaderClasses = (Vector<Class<?>>) classLoaderFields.get(classClassLoader);
    for (int index = 0; index < classLoaderClasses.size(); index++) {
        if (clazz.getName().equals(classLoaderClasses.get(index).getName())) {
            final VectorElement vectorElement = new VectorElement();
            vectorElement.setPosition(index);
            vectorElement.setClazz(clazz);
            swapElements.add(vectorElement);
        }
    }
    for (VectorElement swapedElement : swapElements) {
        classLoaderClasses.removeElementAt(swapedElement.getPosition());
    }
}

@SuppressWarnings("unchecked")
private static void findAndDeleteClassLoader(ClassLoader classClassLoader, ClassLoader systemClassLoader,
        Field classLoaderFields) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
    if (systemClassLoader == null) {
        return;
    }
    final List<VectorElement> swapElements = new ArrayList<VectorElement>();
    final Vector<Class<?>> classLoaderClasses = (Vector<Class<?>>) classLoaderFields.get(systemClassLoader);
    for (int index = 0; index < classLoaderClasses.size(); index++) {
        if (classClassLoader.getClass().getName().equals(classLoaderClasses.get(index).getName())) {
            final VectorElement vectorElement = new VectorElement();
            vectorElement.setPosition(index);
            vectorElement.setClazz(classClassLoader.getClass());
            swapElements.add(vectorElement);
        }
    }
    for (VectorElement swapedElement : swapElements) {
        classLoaderClasses.removeElementAt(swapedElement.getPosition());
    }
    if(classClassLoader.getParent().equals(systemClassLoader)){
        final Class<ClassLoader> classLoaderClass = ClassLoader.class;
        final Field parentField = classLoaderClass.getDeclaredField("parent");
        parentField.setAccessible(true);
        final Object parent = parentField.get(classClassLoader);
        parentField.set(classClassLoader, null);
    }
    findAndDeleteClassLoader(classClassLoader, systemClassLoader.getParent(), classLoaderFields);
}

如果我使用 jvisualvm 查看VM,旧类没有实例和大小0,但仍然存在。旧的类加载器是实例化的。

我知道OSGi可以停止捆绑并卸载它们。最好的情况是我得到一个卸载像OSGi这样的类的机制。根据反射,不可能从类中获取类加载器字段以将类加载器设置为null。我该如何卸载课程?

0 个答案:

没有答案