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

Я хочу загрузить определенные файлы jar в ScriptEngineManager с помощью конкретный загрузчик классов

Этот конструктор загружает реализации 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)

person user7294900    schedule 03.07.2019    source источник


Ответы (1)


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

public URLClassLoader(URL[] urls)

Создает новый URLClassLoader для указанных URL-адресов, используя родительский элемент делегирования по умолчанию 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;
        }
    }
}
person Vinz243    schedule 03.07.2019
comment
ClassLoader недоступен private final ClassLoader parent - person user7294900; 03.07.2019
comment
Я имею в виду расширение ClassLoader/URLClassLoader, а не изменение класса URLClassLoader - person Vinz243; 03.07.2019
comment
Я попытался расширить, и parent не может быть использован Поле ClassLoader.parent не видно - person user7294900; 03.07.2019
comment
Зачем вам нужен доступ к родителю? Ваша реализация не должна его использовать - person Vinz243; 03.07.2019
comment
Я попробовал ваше предложение расширить ClassLoader и использовать if (parent != null) {, можете ли вы объяснить свой ответ? - person user7294900; 03.07.2019
comment
Я бы предпочел расширить URLClassloader, см. редактирование сообщения - person Vinz243; 03.07.2019
comment
Я попробовал ваше решение, но теперь оно не распознает классы внутри определенной папки или классы внутри банок. исключение: java.lang.ClassNotFoundException: net.minidev.asm.FieldFilter at java.net.URLClassLoader.findClass(URLClassLoader.java:381) at com.CustomClassLoader.loadClass(CustomClassLoader.java:15) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) - person user7294900; 03.07.2019
comment
Давайте продолжим обсуждение в чате. - person Vinz243; 03.07.2019