Создать Classloader только с классами внутри определенной папки - PullRequest
3 голосов
/ 03 июля 2019

Я хочу загрузить определенные jar-файлы в ScriptEngineManager, используя определенный 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");

Как мне создать чистый загрузчик классов только с определенными классами папок?

EDIT

Если это невозможно, можноЯ использую в Groovy скрипт что-то эквивалентное Rhino's ClassShutter

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

EDIT

При попытке @ 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)

1 Ответ

3 голосов
/ 03 июля 2019

Как указано в javadoc:

public URLClassLoader(URL[] urls)

Создает новый URLClassLoader для указанных URL-адресов , используя родительское делегирование по умолчанию ClassLoade r. 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
    }

EDIT

Не проверено, но что-то подобное должно делать работу:

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;
        }
    }
}
...