在运行时从Java类路径中删除文件夹
有没有一种从类路径中删除文件夹的方法类似于在运行时添加文件夹()我认为没有一种简单的方法可以做到这一点。您可以按照以下步骤操作:在运行时从Java类路径中删除文件夹,java,Java,有没有一种从类路径中删除文件夹的方法类似于在运行时添加文件夹()我认为没有一种简单的方法可以做到这一点。您可以按照以下步骤操作: 使用:System.getenv(“CLASSPATH”)获取类路径变量。它将返回分号分隔的值 String classPath=System.getenv(“classPath”) 将文件夹路径作为输入,并将其替换为“”,如: String remainigPath=classPath.replace(inputpath,”) 使用拆分方法将剩余路径放入数组中 S
- 使用:
获取类路径变量。它将返回分号分隔的值System.getenv(“CLASSPATH”)
String classPath=System.getenv(“classPath”)
- 将文件夹路径作为输入,并将其替换为“”,如:
String remainigPath=classPath.replace(inputpath,”)代码>
- 使用拆分方法将剩余路径放入数组中
String[]path=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);
}
}
}
编译如下
javac EvilPathDemo.java
javac -d /tmp Foo.java Bar.java
在测试期间,我们将尝试加载类Foo
和Bar
类路径中没有/tmp
java -cp . EvilPathDemo
java.lang.ClassNotFoundException: Foo
java.lang.ClassNotFoundException: Bar
java -cp . EvilPathDemo add
java.lang.ClassNotFoundException: Foo
evil path '/tmp' will be added
I'm bar...
class loaded: Bar
java -cp .:/tmp EvilPathDemo
evil path '/tmp' in the classpath
I'm foo...
class loaded: Foo
I'm bar...
class loaded: Bar
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
向类路径添加/tmp
java -cp . EvilPathDemo
java.lang.ClassNotFoundException: Foo
java.lang.ClassNotFoundException: Bar
java -cp . EvilPathDemo add
java.lang.ClassNotFoundException: Foo
evil path '/tmp' will be added
I'm bar...
class loaded: Bar
java -cp .:/tmp EvilPathDemo
evil path '/tmp' in the classpath
I'm foo...
class loaded: Foo
I'm bar...
class loaded: Bar
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
在类路径中使用/tmp
java -cp . EvilPathDemo
java.lang.ClassNotFoundException: Foo
java.lang.ClassNotFoundException: Bar
java -cp . EvilPathDemo add
java.lang.ClassNotFoundException: Foo
evil path '/tmp' will be added
I'm bar...
class loaded: Bar
java -cp .:/tmp EvilPathDemo
evil path '/tmp' in the classpath
I'm foo...
class loaded: Foo
I'm bar...
class loaded: Bar
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
从类路径中删除/tmp
java -cp . EvilPathDemo
java.lang.ClassNotFoundException: Foo
java.lang.ClassNotFoundException: Bar
java -cp . EvilPathDemo add
java.lang.ClassNotFoundException: Foo
evil path '/tmp' will be added
I'm bar...
class loaded: Bar
java -cp .:/tmp EvilPathDemo
evil path '/tmp' in the classpath
I'm foo...
class loaded: Foo
I'm bar...
class loaded: Bar
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”)
移除路径(路径);//无效
tryToLoad(“巴”)李> - 移除路径(路径)
tryToLoad(“Foo”)
添加路径(路径);//没有效果
tryToLoad(“巴”)李> - tryToLoad(“Foo”)
移除路径(路径);//没有效果
tryToLoad(“巴”)李>
我没有花时间去找出原因。因为我看不出它有什么实际用途。如果您确实需要/希望使用类路径,请查看类加载器是如何工作的。上面的
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:///"));
}
public static void removeLastClasspathEntry()引发异常{
URLClassLoader URLClassLoader=(URLClassLoader)ClassLoader.getSystemClassLoader();
类urlClass=URLClassLoader.Class;
字段ucpField=urlClass.getDeclaredField(“ucp”);
ucpField.setAccessible(true);
URLClassPath ucp=(URLClassPath)ucpField.get(urlClassLoader);
Field LoaderField=URLClassPath.class.getDeclaredField(“加载器”);
loadersField.setAccessible(true);
List jarEntries=(List)loadersField.get(ucp);
jarEntries.remove(jarEntries.size()-1);
Field pathField=URLClassPath.class.getDeclaredField(“路径”);
setAccessible(true);
List pathList=(List)pathField.get(ucp);
URL jarUrl=(URL)pathList.get(pathList.size()-1);
字符串jarName=jarUrl.toString();
移除(pathList.size()-1);
字段lmapField=URLClassPath.class.getDeclaredField(“lmap”);
lmapField.setAccessible(true);
Map lmapMap=(Map)lmapField.get(ucp);
remove(jarName.replaceFirst(“文件:/”,“文件:/”));
}
类加载器可以嵌套,因此与其修改系统类加载器(类加载器树的根),不如简单地创建一个嵌套类加载器并使用它来加载类
系统类加载器本身是不可变的(有充分的理由),但您可以在嵌套类加载器中执行任何操作,包括销毁它们以卸载类和资源。这通常在osgi和应用服务器中用于加载/卸载插件、应用程序等
对于嵌套类装入器,您可以完全自定义如何装入类。
URLClassloader
可能是一个很好的起点 我也遇到了同样的问题,因此我通过创建一个库来解决这个问题,该库可以在使用URLClassPath
的每个ClassLoader
上运行(因此,目前,URLClassLoader
)
该库提供了以下方法:
- 在前面添加新条目
- 附加新条目
- 删除现有条目
这是(感谢您的贡献),这是您尝试过什么吗?成为一名优秀的开发人员的一部分是要有为自己进行实验和解决问题的愿望。问这个问题没什么错,但如果你一开始就说“这是我到目前为止尝试过但没有成功的东西”,那么这个问题会好得多……我想知道这个需求是否有任何现实场景。我自己没有尝试过任何东西,更多的只是四处寻找可能的解决方案。至于现实生活中的情景。。我不能给你一个生产场景,因为这只能在我们的测试环境中使用。@mks我能想到的唯一一个场景是在单元测试中,在单元测试中,你正在测试错误条件的处理——特别是找不到一个文件。请注意:代码的灵感来自于和在这里找到的代码片段,还有一些应该修改的地方(事实上,稍微)提高可靠性。我喜欢这个答案所涉及的纯粹的实验性努力!我认为只有当你想移除的罐子恰好是列表中的最后一个罐子时,这种方法才有效。不过,再加上一点内省,我认为这种方法是可行的