【发布时间】:2019-11-19 17:20:36
【问题描述】:
我想创建dynamically a classloader 用于在受控环境中执行 JSR223 脚本但失败了,
我正在尝试使用当前(父)ClassLoader 删除/添加 jar,我尝试了解决方案 Dynamically removing jars from classpath
public class DistributionClassLoader extends ClassLoader { public DistributionClassLoader(ClassLoader parent) { super(parent); } private Map<String, ClassLoader> classLoadersByDistribution = Collections.synchronizedMap(new WeakHashMap<>()); private final AtomicReference<String> distribution = new AtomicReference<>(); @Override protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { final ClassLoader delegate = classLoadersByDistribution.get(distribution.get()); if (delegate != null) return Class.forName(name, true, delegate); throw new ClassNotFoundException(name); } public void addDistribution(String key, ClassLoader distributionClassLoader){ classLoadersByDistribution.put(key,distributionClassLoader); } public void makeDistributionActive(String key){distribution.set(key);} public void removeDistribution(String key){ final ClassLoader toRemove = classLoadersByDistribution.remove(key); } }
但它不包括我所有的罐子,在测试这项工作
ClassLoader cl = this.getClass().getClassLoader();
Class cls = cl.loadClass("org.springframework.http.HttpStatus");
但是使用解决方案找不到类
ClassLoader cl = new DistributionClassLoader(this.getClass().getClassLoader());
Class cls = cl.loadClass("org.springframework.http.HttpStatus");
例外:
java.lang.ClassNotFoundException: org.springframework.http.HttpStatus
at com.DistributionClassLoader.loadClass(DistributionClassLoader.java:24)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
如何选择特定 jar 以在 ClassLoader 中添加或删除?
编辑
我可以使用 @czdepski answer 加载 jar,但我仍然想删除除 JDK 之外的所有/大多数类
Method sysMethod = URLClassLoader.class.getDeclaredMethod("addURL", new Class[]{URL.class}); sysMethod.setAccessible(true); sysMethod.invoke(sysLoader, new Object[]{url});
【问题讨论】:
-
你能解释一下为什么你想从类加载器中删除东西吗?因为这不是完全可能的,所以你不能强制卸载类。类可能会使用类加载器进行垃圾收集。请提供一些您需要类似内容的示例。
-
@gotofinal 见bz.apache.org/bugzilla/show_bug.cgi?id=63538
-
我不明白这与从类加载器中删除 jars 有什么关系,当执行一个 groovy 脚本时,只需要使用不使用该库的不同类加载器来加载它。所以这样的库不应该是父类加载器的一部分。因为从父类加载器中删除它们无论如何都不会改变任何东西。
-
@gotofinal 如何在现有类加载器的基础上创建类加载器?
-
检查我在答案中写的内容是否与您需要的类似。
标签: java jar classloader dynamic-class-loaders