Есть ли способ, чтобы удалить папку из аналогичных классов добавления папки во время выполнения (Can a directory be added to the class path at runtime?)Удалить папку из Java во время выполнения классов
ответ
Я не думаю, что есть прямой способ сделать это. Вы можете следующим образом:
Получить переменные пути класса, используя:
System.getenv("CLASSPATH")
. Он будет возвращать значения, разделенные двоеточием.String classPath = System.getenv("CLASSPATH")
Возьмите путь к папке в качестве входных данных и заменить его "" как:
String remainigPath = classPath.replace(inputpath,"");
Положите оставшиеся пути в массиве, используя метод расщепления.
String[] paths = remainigPath .split(";");
Для добавления пути к классам, У вас уже есть код.
Ниже приведен фрагмент в качестве технического примера для демонстрации добавления/удаления пути.
создать следующие исходные файлы в любом каталоге
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Stack;
import sun.misc.URLClassPath;
public class EvilPathDemo {
public static void addPath(String path) throws Exception {
URL u = new File(path).toURI().toURL();
URLClassLoader urlClassLoader = (URLClassLoader)
ClassLoader.getSystemClassLoader();
Class<?> urlClass = URLClassLoader.class;
Method method = urlClass.getDeclaredMethod("addURL",
new Class[]{URL.class}
);
method.setAccessible(true);
method.invoke(urlClassLoader, new Object[]{u});
}
public static void removePath(String path) throws Exception {
URL url = new File(path).toURI().toURL();
URLClassLoader urlClassLoader = (URLClassLoader)
ClassLoader.getSystemClassLoader();
Class<?> urlClass = URLClassLoader.class;
Field ucpField = urlClass.getDeclaredField("ucp");
ucpField.setAccessible(true);
URLClassPath ucp = (URLClassPath) ucpField.get(urlClassLoader);
Class<?> ucpClass = URLClassPath.class;
Field urlsField = ucpClass.getDeclaredField("urls");
urlsField.setAccessible(true);
Stack urls = (Stack) urlsField.get(ucp);
urls.remove(url);
}
public static void main(String[] args) throws Exception {
String parm = args.length == 1 ? args[0] : "";
String evilPath = "/tmp";
String classpath = System.getProperty("java.class.path");
boolean isEvilPathSet = false;
for (String path : classpath.split(File.pathSeparator)) {
if (path.equalsIgnoreCase(evilPath)) {
System.out.printf("evil path '%s' in classpath%n", evilPath);
isEvilPathSet = true;
break;
}
}
if (isEvilPathSet && parm.equalsIgnoreCase("REMOVE")) {
System.out.printf("evil path '%s' will be removed%n", evilPath);
removePath(evilPath);
}
tryToLoad("Foo");
if (parm.equalsIgnoreCase("ADD")) {
System.out.printf("evil path '%s' will be added%n", evilPath);
addPath(evilPath);
}
tryToLoad("Bar");
}
private static void tryToLoad(String className) {
try {
Class<?> foo = Class.forName(className);
System.out.printf("class loaded: %s%n", foo.getName());
} catch (ClassNotFoundException ex) {
System.out.println(ex);
}
}
}
.
public class Foo {
static {
System.out.println("I'm foo...");
}
}
.
public class Bar {
static {
System.out.println("I'm bar...");
}
}
компилировать их как следовать
javac EvilPathDemo.java
javac -d /tmp Foo.java Bar.java
Во время теста мы будем стараться, чтобы загрузить классы Foo
и Bar
.
без/TMP в пути к классам
java -cp . EvilPathDemo
java.lang.ClassNotFoundException: Foo
java.lang.ClassNotFoundException: Bar
добавление/TMP к классам
java -cp . EvilPathDemo add
java.lang.ClassNotFoundException: Foo
evil path '/tmp' will be added
I'm bar...
class loaded: Bar
с/TMP в пути к классам
java -cp .:/tmp EvilPathDemo
evil path '/tmp' in the classpath
I'm foo...
class loaded: Foo
I'm bar...
class loaded: Bar
удалить/TMP из
классамjava -cp .:/tmp EvilPathDemo remove
evil path '/tmp' in the classpath
evil path '/tmp' will be removed
java.lang.ClassNotFoundException: Foo
java.lang.ClassNotFoundException: Bar
Во время тестирования я обнаружил, что следующие случаи не работают.
- addPath (evilPath);
tryToLoad ("Foo");
removePath (evilPath); // не влияет
tryToLoad ("Bar"); - removePath (evilPath);
tryToLoad ("Foo");
addPath (evilPath); // не имел эффекта
tryToLoad ("Bar"); - tryToLoad ("Foo");
removePath (evilPath); // не имел эффекта
tryToLoad ("Bar");
Я не потратил времени, чтобы узнать, почему. Потому что я не вижу в этом никакого практического использования. Если вам действительно нужно/хотите играть с classpaths, посмотрите, как работают загрузчики классов.
Полюбите явное экспериментальное усилие, вовлеченное в этот ответ! – Stewart
Метод removePath
сверху не работал для меня и моего контейнера Weld, стек url всегда был emtpy. Следующие некрасиво самодовольны методы сработали:
public static void removeLastClasspathEntry() throws Exception {
URLClassLoader urlClassLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
Class<?> urlClass = URLClassLoader.class;
Field ucpField = urlClass.getDeclaredField("ucp");
ucpField.setAccessible(true);
URLClassPath ucp = (URLClassPath) ucpField.get(urlClassLoader);
Field loadersField = URLClassPath.class.getDeclaredField("loaders");
loadersField.setAccessible(true);
List jarEntries = (List) loadersField.get(ucp);
jarEntries.remove(jarEntries.size() - 1);
Field pathField = URLClassPath.class.getDeclaredField("path");
pathField.setAccessible(true);
List pathList = (List) pathField.get(ucp);
URL jarUrl = (URL) pathList.get(pathList.size() - 1);
String jarName = jarUrl.toString();
pathList.remove(pathList.size() - 1);
Field lmapField = URLClassPath.class.getDeclaredField("lmap");
lmapField.setAccessible(true);
Map lmapMap = (Map) lmapField.get(ucp);
lmapMap.remove(jarName.replaceFirst("file:/", "file:///"));
}
класса погрузчики могут быть вложенными, так вместо того, чтобы модифицировать системный класс загрузчик, который является корнем дерева загрузчиков классов, то лучше просто создать вложенную загрузчик классов и использование что для загрузки классов.
Системный загрузчик классов неизменен (по уважительным причинам), но вы можете делать все, что хотите, в загрузчиках вложенных классов, включая уничтожение их для разгрузки классов и ресурсов. Это обычно используют, например, osgi и серверы приложений для загрузки/выгрузки, например. плагины, приложения и т. д.
Для вложенных загрузчиков классов вы можете полностью настроить загрузку классов. URLClassloader
, вероятно, является хорошей отправной точкой для того, что вы хотите.
У меня была такая же проблема, поэтому я занялся ею, создав библиотеку, которая работает на каждом ClassLoader
, который использует URLClassPath
(так, в настоящее время, URLClassLoader
).
В библиотеке есть методы:
- Добавление новых записей перед
- Добавляя новые записи
- удаления существующих записей
Пожалуйста, обратите внимание, что, поскольку эта библиотека обращается к внутренней и патентованной API, в будущих версиях JDK не гарантируется работа. В настоящее время он работает для Java 7 и Java 8 (Oracle и OpenJDK).
Вот the GitHub page (вклад ценится), а вот the Maven Central artifact
Просто примечание: код вдохновлен фрагментами, найденными здесь [JohannSchwarz] (http://stackoverflow.com/users/1979735/johannschwarz) и [SubOptimal] (http://stackoverflow.com/users/2333222/ субоптимальный), с небольшими изменениями, которые должны (на самом деле, незначительно) повысить надежность. –
- 1. Java загрузка пользовательских классов во время выполнения
- 2. Перезагрузка используемых классов во время выполнения Java
- 3. Создание классов JAVA из wsdl во время выполнения
- 4. Загрузка Котлин созданных классов во время выполнения из Java
- 5. Компиляция и использование классов Groovy из Java во время выполнения?
- 6. Определение классов во время выполнения
- 7. Обновлять папку динамически во время выполнения
- 8. удалить кнопку из приложения во время выполнения
- 9. ModelMapper: отображение абстрактных классов во время выполнения
- 10. Добавить папку, содержащую источники java, в classpath во время выполнения
- 11. Удалить элемент во время выполнения
- 12. класса во время выполнения
- 13. Создание экземпляров классов во время выполнения
- 14. Загрузка классов из приложения из файловой системы во время выполнения
- 15. Расширение/изменение классов NHibernate во время выполнения
- 16. Как интегрировать элементы GUI из разных классов во время выполнения?
- 17. Расширение или добавление новых классов во время выполнения в Java
- 18. Java: Передача классов как параметров во время выполнения
- 19. Импорт классов Java во время выполнения и компиляция
- 20. Изменить наследование классов во время выполнения
- 21. Создание классов C# во время выполнения
- 22. Компиляция портативной библиотеки классов во время выполнения
- 23. Определение иерархии классов объекта во время выполнения
- 24. Генерация классов во время выполнения/время компиляции с Дартом
- 25. Java интерпретируется во время выполнения?
- 26. Обнаружение нового класса Java во время выполнения
- 27. Удалить MC загружается во время выполнения
- 28. Удалить все объекты Realm во время выполнения
- 29. jQuery удалить validationEngine во время выполнения
- 30. Как удалить строку TableLayout во время выполнения
Пытались ли вы что-нибудь? Часть того, чтобы быть хорошим разработчиком, имеет желание экспериментировать и рисовать вещи для себя. Нет ничего плохого в вопросе, но это было бы намного лучше, если бы вы начали с «Вот что я пытался до сих пор, но это не сработало» ... –
Хотелось бы узнать, есть ли любой сценарий реальной жизни для этого требования. – mks
Я сам ничего не пробовал, а просто рылся в поисках возможных решений.Что касается реальных сценариев жизни. Я не могу дать вам сценарий производства, поскольку это будет использоваться только в наших тестовых средах. – jpints14