Возможно ли добавить jar / пакет в путь к классу, а затем удалить его после использования? (во время выполнения)

#java #multithreading #jvm #conflict

#java #многопоточность #jvm #конфликт

Вопрос:

Предыстория: моя основная цель — развернуть поток, задать для него путь к классу, а затем после завершения потока я не хочу, чтобы что-либо сохранялось из потока. Возможно ли сбросить загрузчик классов после выполнения потока, чтобы любые добавленные пакеты URL не сохранялись после?

Я запускал следующий код внутри отдельного потока:

     public static void addURL(URL url) throws Exception {
        URLClassLoader classLoader
        = (URLClassLoader) Thread.currentThread().getContextClassLoader();
        Class clazz= URLClassLoader.class;

        // Use reflection
        Method method= clazz.getDeclaredMethod("addURL", new Class[] { URL.class });
        method.setAccessible(true);
        method.invoke(classLoader, new Object[] { url });
    }

  

затем выполняется forname для добавленного класса:

 try {
    Class.forName("com.mypackage.myclass", false, Thread.currentThread().getContextClassLoader());
} catch (ClassNotFoundException e) {
    e.printStackTrace();
}
  

Однако после завершения потока я ожидаю исключение classnotfoundexception вне потока, если я повторно запускаю forName() выше, но оно не выдает ошибку. Есть ли способ удалить пакет из загрузчика классов контекста родительского потока?

Комментарии:

1. Почему вы исправляете существующий ClassLoader вместо создания дочернего? Невозможно выгрузить класс без выгрузки всего ClassLoader. Нет способа сбросить ClassLoader — вам нужно создать новый, а затем удалить его.

2. Я пытался использовать Thread.setContextClassLoader() с новым classloader, но это всегда приводит к classnotfound, когда я пытаюсь инициализировать что-либо из нового classpath в другом потоке.

3. Это потому, что загрузчик контекстного класса совершенно не имеет отношения к загрузке класса. Когда вы используете customClassLoader.loadClass("com.mypackage.myclass") и класс действительно был загружен через него (т. Е. Не через родительский загрузчик), все его символические ссылки будут разрешены через пользовательский загрузчик классов, независимо от потока, используемого для выполнения кода.