有没有办法从类路径中删除文件夹,类似于在运行时添加文件夹(可以在运行时将目录添加到类路径吗?)
请在下面找到一个片段作为技术示例来演示添加/删除路径.
在任何目录中创建以下源文件
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( "富");
removePath(evilPath); //没有影响
tryToLoad("Bar");
removePath(evilPath);
tryToLoad( "富");
让addpath(evilPath); //没有效果
tryToLoad("Bar");
tryToLoad( "富");
removePath(evilPath); //没有效果
tryToLoad("Bar");
我没有花时间找出原因.因为我没有看到任何实际用途.如果你真的需要/希望使用类路径,看看类加载器是如何工作的.