简短的回答是,该实施是 Sun 内部工作的一部分,无法通过公共方式获得。 getURLs() 只会返回传入的 URL。有更长的答案,但它只适用于大胆的人。
使用调试器单步执行 Oracle JVM 8 使我了解了与 OpenJDK6 几乎相同的结构,您可以看到它加载类路径 here 的位置。
基本上,类加载器会保留一堆尚未解析到内存中的 URL。当被要求加载一个类时,它将从堆栈中弹出 URL,将它们作为类文件或 jar 文件加载,如果它们是 jar 文件,它将读取清单并将类路径条目推送到堆栈上。每次它处理一个文件时,它都会将加载该文件的“加载器”添加到加载器映射中(如果没有别的,以确保它不会多次处理同一个文件)。
如果您真的有动力(不推荐)这样做,您可以访问此地图:
Field secretField = URLClassLoader.class.getDeclaredField("ucp");
secretField.setAccessible(true);
Object ucp = secretField.get(loader);
secretField = ucp.getClass().getDeclaredField("lmap");
secretField.setAccessible(true);
return secretField.get(ucp);
在我有引用 external.jar 的 dummy-plugin.jar 的虚拟设置上运行它(在 dummy-plugin.jar 的清单中),我得到以下信息:
1) 在创建类加载器之后(在加载任何类之前):
urlClassLoader.getURLs()=[file:.../dummy-plugin.jar]
getSecretUrlsStack=[file:.../dummy-plugin.jar]
getSecretLmapField={}
2) 从 dummy-plugin.jar 加载类后:
urlClassLoader.getURLs()=[file:.../dummy-plugin.jar]
getSecretUrlsStack=[file:.../external.jar]
getSecretLmapField={file:.../dummy-plugin.jar=sun.misc.URLClassPath$JarLoader@736e9adb}
3) 从 external.jar 加载类后:
urlClassLoader.getURLs()=[file:.../dummy-plugin.jar]
getSecretUrlsStack=[]
getSecretLmapField={file:.../dummy-plugin.jar=sun.misc.URLClassPath$JarLoader@736e9adb, file:.../external.jar=sun.misc.URLClassPath$JarLoader@2d8e6db6}
奇怪的是,这似乎在JDK for URLClassLoader面前飞了起来:
默认情况下,加载的类仅授予
访问创建 URLClassLoader 时指定的 URL。