Как изменить путь к классам в Java?
Как изменить путь к классам процесса Java из процесса Java?
прежде чем вы спросите меня: "почему вы хотите это сделать?- Я сейчас все объясню.
когда у вас работает Clojure REPL, обычно требуется больше банок в вашем CLASSPATH для загрузки Clojure исходный файл, и я хотел бы сделать это без перезапуска самого Clojure (что на самом деле не является опцией при использовании его на Slime on Emacs).
Это причина, но я не хочу, чтобы этот вопрос был помечен как какой-то странный язык, какой-то странный редактор и игнорировался большинством разработчиков Java, которые могут иметь ответ.
6 ответов:
обновление Q4 2017: as прокомментировал ниже vda8888, в Java 9, система
java.lang.ClassLoaderуже нетjava.net.URLClassLoader.в разделе " Java 9 Руководство По Миграции: Семь Наиболее Распространенных Проблем"
стратегия загрузки класса, которую я только что описал, реализована в новом типе, и в Java 9 загрузчик классов приложений имеет этот тип.
Это означает, что это неURLClassLoaderбольше, так что иногда(URLClassLoader) getClass().getClassLoader()или(URLClassLoader) ClassLoader.getSystemClassLoader()последовательности больше не будет выполняться.java.ленг.ModuleLayer был бы альтернативный подход, используемый для того, чтобы повлиять на modulepath (вместо classpath). См., например,"Java 9 modules-JPMS basics".
для Java 8 или ниже:
некоторые общие замечания:
вы не можете (в портативном способе, который гарантированно работа, см. ниже) измените системный путь к классам. Вместо этого необходимо определить новый загрузчик классов.
загрузчики классов работают в иерархическом порядке... поэтому любой класс, который делает статическую ссылку на класс X, должен быть загружен в тот же загрузчик классов, что и X, или в дочерний загрузчик классов. Вы не можете использовать какой-либо пользовательский загрузчик классов для правильной загрузки кода по ссылке system ClassLoader, если это не было сделано раньше. Поэтому вам нужно организовать запуск вашего основного кода приложения в пользовательский загрузчик классов в дополнение к дополнительному коду, который вы найдете.
(Это, как говорится, трещины-все упоминает в комментариях этот пример расширенияURLClassLoader)и вы можете рассмотреть возможность не писать свой собственный загрузчик классов, а просто использовать 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);если вы предполагаете, что системный загрузчик классов JVMs является URLClassLoader (что может быть неверно для всех JVMs), вы также можете использовать отражение, чтобы фактически изменить системный путь к классам... (но это хак;)):
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");
Я не верю, что вы можете - правильная вещь, чтобы сделать (я считаю), это создать новый загрузчик классов с новым путем. Кроме того, вы можете написать свой собственный загрузчик классов, который позволяет динамически изменять путь к классам (для этого загрузчика).
нет необходимости писать свой собственный загрузчик класса! Есть clojure.ленг.DynamicClassLoader.
http://blog.japila.pl/2011/01/dynamically-redefining-classpath-in-clojure-repl/
вы можете изучить использование java.net. URLClassLoader. это позволяет программно загружать классы, которые изначально не были в вашем пути к классам, хотя я не уверен, что это именно то, что вам нужно.
это возможно, как видно из двух ссылок ниже, метод VonC дает, кажется, лучший, но проверить некоторые из этих сообщений и google для "Java Dynamic Classpath" или "Java Dynamic Class Loading" и узнать некоторую информацию оттуда.
Я бы опубликовал более подробно, но VonC в значительной степени выполнил эту работу.
с динамическая загрузка файлов классов и Jar.
также проверьте это sun forum post.