我需要在运行时卸载类。我有一个在运行时初始化的自定义类加载器。此类加载器加载较新版本的类。此类也可以在运行时更新。在这种情况下,我想删除旧版本的类加载器,以便可以从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。我该如何卸载课程?