简短的回答是,实现部分属于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的虚拟设置中运行,我获得以下结果:
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) 从外部.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}
奇怪的是,这似乎与URLClassLoader的JDK相矛盾:
默认情况下,加载的类只被授予访问创建URLClassLoader时指定的URL的权限。