【问题标题】:Create Classloader with only classes inside specific folder仅使用特定文件夹中的类创建类加载器
【发布时间】:2019-11-13 19:57:31
【问题描述】:

我想使用specific ClassLoaderScriptEngineManager 中加载特定的罐子

此构造函数使用服务提供者机制加载对给定 ClassLoader 可见的 ScriptEngineFactory 的实现。

我尝试创建Classloader时的问题

File file = new File("c:\\myclasses\\");

try {
// Convert File to a URL
URL url = file.toURI().toURL();          // file:/c:/myclasses/
URL[] urls = new URL[]{url};

// Create a new class loader with the directory
ClassLoader cl = new URLClassLoader(urls)

而且我还要上一些不在课堂上的课,例如 Spring

 Class cls1 = cl.loadClass("org.springframework.http.HttpStatus");

如何创建一个只包含特定文件夹类的干净类加载器?

编辑

如果不可能,我可以在 groovy 脚本中使用与 Rhino 的 ClassShutter 等效的东西吗?

private static void setJavaClassesVisibleInvisibleSandbox(Context cx)
 {
  cx.setClassShutter(new ClassShutter()
   {
      public boolean visibleToScripts(String className)
      {
          // No Java classes allowed inside scripts

编辑

当尝试@Vinz243 CustomClassLoader 解决方案无法从特定文件夹加载类文件或jar 文件的类,甚至尝试rt.jar

java.lang.SecurityException: Prohibited package name: java.lang
    at java.lang.ClassLoader.preDefineClass(ClassLoader.java:662)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:761)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:467)
    at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:368)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:362)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:361)
    at com.CustomClassLoader.loadClass(CustomClassLoader.java:15)

【问题讨论】:

    标签: java classloader urlclassloader


    【解决方案1】:

    在 javadoc 中指定:

    public URLClassLoader(URL[] urls)

    为指定的 URL 构造一个新的 URLClassLoader使用默认的委托父 ClassLoader。 在父类加载器中首次搜索后,将按照为类和资源指定的顺序搜索 URL。假设任何以“/”结尾的 URL 都指向一个目录。否则,假定 URL 引用一个 JAR 文件,该文件将根据需要下载和打开。

    所以你可以尝试扩展ClassLoader,因为负责加载父类的机制在java.lang.ClassLoader#loadClass(java.lang.String, boolean)内部

        try {
            if (parent != null) {
                c = parent.loadClass(name, false);
            } else {
                c = findBootstrapClassOrNull(name);
            }
        } catch (ClassNotFoundException e) {
            // ClassNotFoundException thrown if class not found
            // from the non-null parent class loader
        }
    

    编辑

    未测试,但类似的东西应该可以完成工作:

    class CustomClassLoader extends URLClassLoader {
    
        public CustomClassLoader (URL[] urls) throws NoSuchMethodException {
            super(urls);
        }
    
        @Override
        protected Class<?> loadClass (String name, boolean resolve) throws ClassNotFoundException {
            synchronized (getClassLoadingLock(name)) {
                Class<?> aClass = findClass(name);
                if (resolve) {
                    resolveClass(aClass);
                }
                return aClass;
            }
        }
    }
    

    【讨论】:

    • 无法访问ClassLoader private final ClassLoader parent
    • 我的意思是扩展 ClassLoader/URLClassLoader 而不是修改 URLClassLoader
    • 我尝试扩展,无法使用parent ClassLoader.parent字段不可见
    • 为什么需要访问父节点?你的实现不应该使用它
    • 我尝试了你的建议扩展ClassLoader并使用if (parent != null) {,你能解释一下你的答案吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多