Обновление Q4 2017: как прокомментировал ниже vda8888 , в Java 9 система java.lang.ClassLoader
больше не java.net.URLClassLoader
.
См. " Руководство по миграции на Java 9: семь самых распространенных проблем "
Стратегия загрузки классов, которую я только что описал, реализована в новом типе, а в Java 9 загрузчик классов приложений относится к этому типу.
Это означает, что это больше не URLClassLoader
, поэтому случайные последовательности (URLClassLoader) getClass().getClassLoader()
или (URLClassLoader) ClassLoader.getSystemClassLoader()
больше не будут выполняться.
java.lang.ModuleLayer будет альтернативным подходом, используемым для воздействия на modulepath (вместо classpath). См., Например, " Модули Java 9 - основы JPMS ".
Для Java 8 или ниже:
Некоторые общие комментарии:
вы не можете (в переносимом режиме, который гарантированно работает, см. Ниже) изменить системный путь к классу. Вместо этого вам нужно определить новый ClassLoader.
ClassLoaders работают иерархически ... поэтому любой класс, который делает статическую ссылку на класс X, должен быть загружен в тот же ClassLoader, что и X, или в дочерний ClassLoader. Вы НЕ можете использовать любой пользовательский ClassLoader для правильной загрузки кода по системной ссылке ClassLoader, если бы этого не было раньше. Поэтому вам нужно организовать запуск кода основного приложения в пользовательском ClassLoader в дополнение к дополнительному коду, который вы обнаружите.
(При этом cracked-all упоминает в комментариях этот пример расширения URLClassLoader
)
И вы можете не писать свой собственный ClassLoader, а просто использовать вместо него URLClassLoader. Создайте URLClassLoader с URL, которые не в URL родительских загрузчиков классов.
URL[] url={new URL("file://foo")};
URLClassLoader loader = new URLClassLoader(url);
A Более полное решение будет:
ClassLoader currentThreadClassLoader
= Thread.currentThread().getContextClassLoader();
// Add the conf dir to the classpath
// Chain the current thread classloader
URLClassLoader urlClassLoader
= new URLClassLoader(new URL[]{new File("mtFile").toURL()},
currentThreadClassLoader);
// Replace the thread classloader - assumes
// you have permissions to do so
Thread.currentThread().setContextClassLoader(urlClassLoader);
Если вы предполагаете, что системный загрузчик классов JVM является URLClassLoader (что может не соответствовать действительности для всех JVM), вы также можете использовать отражение, чтобы фактически изменить системный путь к классам ... (но это взлом;)):
public void addURL(URL url) throws Exception {
URLClassLoader classLoader
= (URLClassLoader) ClassLoader.getSystemClassLoader();
Class clazz= URLClassLoader.class;
// Use reflection
Method method= clazz.getDeclaredMethod("addURL", new Class[] { URL.class });
method.setAccessible(true);
method.invoke(classLoader, new Object[] { url });
}
addURL(new File("conf").toURL());
// This should work now!
Thread.currentThread().getContextClassLoader().getResourceAsStream("context.xml");