Java 从自定义类加载器中添加或删除特定JAR
我想创建用于在受控环境中执行JSR223脚本的脚本,但失败了 我正在尝试使用当前(父)类加载器删除/添加JAR,我尝试了解决方案 但是使用解决方案并不能找到类Java 从自定义类加载器中添加或删除特定JAR,java,jar,classloader,dynamic-class-loaders,Java,Jar,Classloader,Dynamic Class Loaders,我想创建用于在受控环境中执行JSR223脚本的脚本,但失败了 我正在尝试使用当前(父)类加载器删除/添加JAR,我尝试了解决方案 但是使用解决方案并不能找到类 ClassLoader cl = new DistributionClassLoader(this.getClass().getClassLoader()); Class cls = cl.loadClass("org.springframework.http.HttpStatus"); 例外情况: java.lang.ClassNot
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
编辑
我可以使用加载JAR,但我仍然希望删除除JDK之外的所有/大多数类
你把代表团搞错了。如果父类加载器有这个类,您永远不会检查它 如果我们查看for
ClassLoader.loadClass(字符串,布尔值)
我们会发现:
加载具有指定二进制名称的类。此方法的默认实现按以下顺序搜索类:
findLoadedClass(String)
检查类是否已加载
loadClass
方法。如果父级为null,则使用虚拟机中内置的类装入器
findClass(String)
方法来查找类
loadClass
,但没有对其父类加载器进行任何委托。而是调用
classLoadersByDistribution.get(distribution.get())
,最有可能是null
(很难说,但总是希望WeakHashMap.get()
返回null
)
如果delegate
不为null,则尝试从那里加载类。这意味着加载的类不会使用您的类加载器加载新类,而是使用您委托给的类加载器
毕竟,这听起来像是一场灾难。您希望使用脚本API执行一些代码,并以某种方式控制环境。您是否尝试使用
安全管理器
关于您的评论,您需要自己的
类加载器来创建:这个类加载器用于搜索ScriptEngineFactory实现。这是使用一个。
如果您不使用自己的脚本引擎,这对您来说应该无关紧要
如果您的目标是添加几个JAR以便引擎可以使用它,那么创建一个新的URLClassLoader
,将平台类装入器作为父级。(或扩展类加载器,取决于java版本。)
将此类加载器设置为Thread.setContextClassLoader()
,并创建脚本引擎
如果您正确选择了URLClassLoader
的父级,它将看不到应用程序类装入器可装入的类。您的委托错误。如果父类加载器有这个类,您永远不会检查它
如果我们查看forClassLoader.loadClass(字符串,布尔值)
我们会发现:
加载具有指定二进制名称的类。此方法的默认实现按以下顺序搜索类:
调用findLoadedClass(String)
检查类是否已加载
调用父类加载器上的loadClass
方法。如果父级为null,则使用虚拟机中内置的类装入器
调用findClass(String)
方法来查找类
如果使用上述步骤找到该类,并且resolve标志为true,则该方法将调用结果类对象上的resolveClass(class)方法
建议ClassLoader的子类重写findClass(String),而不是此方法。
您确实重写了loadClass
,但没有对其父类加载器进行任何委托。
而是调用classLoadersByDistribution.get(distribution.get())
,最有可能是null
(很难说,但总是希望WeakHashMap.get()
返回null
)
如果delegate
不为null,则尝试从那里加载类。这意味着加载的类不会使用您的类加载器加载新类,而是使用您委托给的类加载器
毕竟,这听起来像是一场灾难。您希望使用脚本API执行一些代码,并以某种方式控制环境。
您是否尝试使用安全管理器
关于您的评论,您需要自己的类加载器来创建:这个类加载器用于搜索ScriptEngineFactory实现。这是使用一个。
如果您不使用自己的脚本引擎,这对您来说应该无关紧要
如果您的目标是添加几个JAR以便引擎可以使用它,那么创建一个新的URLClassLoader
,将平台类装入器作为父级。(或扩展类加载器,取决于java版本。)
将此类加载器设置为Thread.setContextClassLoader()
,并创建脚本引擎
如果您正确选择了URLClassLoader
的父级,它将看不到应用程序类加载器可加载的类。关于最后一个命令,我需要类加载器,请参见以便提供您自己的脚本引擎?通过您自己的类加载器加载?我想在发送到ScriptEngine之前使用当前类加载器更新(添加/删除JAR)。您不应该在类加载器创建之后修改它。这很危险。(请参阅JVM中关于加载类的内容。)但是我想在现有classloaderAbout的基础上使用一个更安全/可配置的classloader上一个命令,我需要classloader,请参阅,您想提供自己的ScriptEngine吗?通过您自己的类加载器加载?我想更新(添加/删除JAR)usi
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)
Method sysMethod = URLClassLoader.class.getDeclaredMethod("addURL", new Class[]{URL.class});
sysMethod.setAccessible(true);
sysMethod.invoke(sysLoader, new Object[]{url});