Вопрос-ответ

How to load a jar file at runtime [duplicate]

Как загрузить jar-файл во время выполнения

Меня попросили создать систему Java, которая будет иметь возможность загружать новый код (расширения) во время выполнения. Как мне повторно загрузить файл jar во время выполнения моего кода? или как мне загрузить новый jar?

Очевидно, поскольку важно постоянное время безотказной работы, я хотел бы добавить возможность перезагрузки существующих классов во время выполнения (если это не слишком усложнит задачу).

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

Переведено автоматически
Ответ 1

Перезагрузка существующих классов с существующими данными, скорее всего, приведет к сбоям.

Вы можете относительно легко загружать новый код в новые загрузчики классов:

ClassLoader loader = URLClassLoader.newInstance(
new URL[] { yourURL },
getClass().getClassLoader()
);
Class<?> clazz = Class.forName("mypackage.MyClass", true, loader);
Class<? extends Runnable> runClass = clazz.asSubclass(Runnable.class);
// Avoid Class.newInstance, for it is evil.
Constructor<? extends Runnable> ctor = runClass.getConstructor();
Runnable doRun = ctor.newInstance();
doRun.run();

Больше не используемые загрузчики классов можно использовать для сбора мусора (если только нет утечки памяти, как это часто бывает при использовании ThreadLocal, драйверов JDBC, java.beans и т.д.).

Если вы хотите сохранить данные объекта, то я предлагаю механизм сохранения, такой как сериализация, или что-то еще, к чему вы привыкли.

Конечно, системы отладки могут делать более причудливые вещи, но они более хакерские и менее надежные.

В загрузчик классов можно добавлять новые классы. Например, с помощью URLClassLoader.addURL. Однако, если класс не загружается (скажем, потому, что вы его не добавили), то он никогда не загрузится в этом экземпляре загрузчика класса.

Ответ 2

У меня это работает:

File file  = new File("c:\\myjar.jar");

URL url = file.toURL();
URL[] urls = new URL[]{url};

ClassLoader cl = new URLClassLoader(urls);
Class cls = cl.loadClass("com.mypackage.myclass");
Ответ 3

Меня попросили создать систему java, которая будет иметь возможность загружать новый код во время выполнения


Возможно, вы захотите основать свою систему на OSGi (или, по крайней мере, приложить к этому много усилий), которая была создана именно для этой ситуации.

Возня с загрузчиками классов - действительно сложное дело, в основном из-за того, как работает видимость классов, и вы не хотите позже столкнуться с проблемами, которые трудно отладить. Например, Class.forName(), который широко используется во многих библиотеках, не слишком хорошо работает во фрагментированном пространстве classloader.

Ответ 4

Я немного погуглил и нашел этот код здесь:

File file = getJarFileToLoadFrom();   
String lcStr = getNameOfClassToLoad();
URL jarfile = new URL("jar", "","file:" + file.getAbsolutePath()+"!/");
URLClassLoader cl = URLClassLoader.newInstance(new URL[] {jarfile });
Class loadedClass = cl.loadClass(lcStr);

Кто-нибудь может поделиться мнениями / комментариями / ответами относительно этого подхода?

java jar