Ответ 1
Обновление Q4 2017: прокомментировал ниже vda8888, в Java 9, System java.lang.ClassLoader
уже не java.net.URLClassLoader
.
См. "Руководство по перенастройке Java 9: Семь наиболее распространенных проблем
Стратегия загрузки класса, которую я только что описал, реализована в новом типе, а в Java 9 - загрузчик классов приложений. Это означает, что это уже не
URLClassLoader
, поэтому случайные последовательности(URLClassLoader) getClass().getClassLoader()
или(URLClassLoader) ClassLoader.getSystemClassLoader()
больше не будут выполняться.
java.lang.ModuleLayer будет альтернативным подходом, используемым для того, чтобы влиять на путь модуля (а не путь к классам). См. Например: Модули Java 9 - Основы JPMS.
Для Java 8 или ниже:
Некоторые общие комментарии:
вы не можете (в переносном режиме, который гарантированно работает, см. ниже) изменить путь к системе. Вместо этого вам нужно определить новый ClassLoader.
ClassLoaders работают иерархически... поэтому любой класс, который делает статическую ссылку на класс X, должен быть загружен в тот же ClassLoader, что и X, или в дочерний ClassLoader. Вы не можете использовать какой-либо пользовательский класс ClassLoader, чтобы код, загруженный системой ClassLoader, правильно, если бы он этого не делал раньше. Поэтому вам нужно организовать, чтобы ваш основной код приложения выполнялся в пользовательском ClassLoader в дополнение к дополнительному коду, который вы найдете.
(При этом cracked-all упоминает в комментариях этот пример расширение URLClassLoader
)
И вы можете не писать собственный ClassLoader, а просто использовать URLClassLoader. Создайте URLClassLoader с 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);
Если вы предполагаете, что системный загрузчик JVMs является загрузчиком 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");