Как изменить путь к классам в Java?


Как изменить путь к классам процесса Java из процесса Java?


прежде чем вы спросите меня: "почему вы хотите это сделать?- Я сейчас все объясню.

когда у вас работает Clojure REPL, обычно требуется больше банок в вашем CLASSPATH для загрузки Clojure исходный файл, и я хотел бы сделать это без перезапуска самого Clojure (что на самом деле не является опцией при использовании его на Slime on Emacs).

Это причина, но я не хочу, чтобы этот вопрос был помечен как какой-то странный язык, какой-то странный редактор и игнорировался большинством разработчиков Java, которые могут иметь ответ.

6 59

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.

String s="java  -classpath abcd/ "+pgmname+" "+filename;   
Process pro2 = Runtime.getRuntime().exec(s); 
BufferedReader in = new BufferedReader(new InputStreamReader(pro2.getInputStream()));

является примером изменения пути к классам в java-программе