Java 从自定义类加载器中添加或删除特定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

我想创建用于在受控环境中执行JSR223脚本的脚本,但失败了

我正在尝试使用当前(父)类加载器删除/添加JAR,我尝试了解决方案

但是使用解决方案并不能找到类

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)
    方法来查找类

  • 如果使用上述步骤找到该类,并且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
    的父级,它将看不到应用程序类装入器可装入的类。

    您的委托错误。如果父类加载器有这个类,您永远不会检查它

    如果我们查看for
    ClassLoader.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});