类加载器如何在清单类路径中加载类引用? [英] How does a classloader load classes reference in the manifest classpath?

查看:130
本文介绍了类加载器如何在清单类路径中加载类引用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用maven来构建一个带有外部类路径添加的jar,使用 addClasspath

I used maven to built a jar with an external classpath additions using addClasspath.

当我使用 java -jar artifact.jar 运行该jar时,它能够从该主jar加载类以及来自libs目录中的所有jar。

When I run that jar using java -jar artifact.jar it is able to load classes from that main jar and from all jars in the libs directory.

但是如果我问系统属性 java.class.path 它只会列出主罐子。如果我向系统类加载器询问其URL( ClassLoader.getSystemClassLoader()。getURLs()),它也只会返回主jar。如果我问一些库中包含的任何类的类加载器,它将返回系统类加载器。

However if I ask the system property java.class.path it will only list the main jar. If I ask the system class loader for its urls (ClassLoader.getSystemClassLoader().getURLs()) it will also only return the main jar. If I ask any class contained in some library for its class loader it will return the system class loader.

系统类加载器如何加载这些类?

How is the system class loader able to load those classes?

它必须对这些库有一些了解才能从这些库中加载类。有没有办法要求它使用这种扩展类路径?

It has to have some knowledge about those libraries in order to load classes from those. Is there a way to ask it for this kind of "extended" classpath?

推荐答案

简短的回答是实现是部分太阳的内部运作,而不是通过公共手段提供。 getURLs()只返回传入的网址。答案较长,但只适用于大胆。

The short answer is that the implementation is part of Sun's internal workings and not available through public means. getURLs() will only ever return the URLs that are passed in. There is a longer answer but it is only for the daring.

使用调试器逐步调试Oracle JVM 8使我通过与OpenJDK6完全相同的结构,您可以看到它加载类路径的位置此处

Stepping through Oracle JVM 8 with the debugger has led me through pretty much an identical structure as OpenJDK6 and you can see where it loads the class path here.

基本上,类加载器会保留一堆尚未解析到内存中的URL。当被要求加载一个类时,它将从堆栈中弹出URL,将它们作为类文件或jar文件加载,如果它们是jar文件,它将读取清单并将类路径条目推送到堆栈。每次处理文件时,它都会添加loader,它将该文件加载到加载程序映射中(如果没有别的,则确保它不会多次处理同一文件)。

Basically, the class loader keeps a stack of URLs it has not yet parsed into memory. When asked to load a class it will pop URLs off the stack, load them as class files or jar files, and if they are jar files it will read the manifest and push class path entries onto the stack. Each time it processes a file it adds the "loader" which loaded that file to a loader map (if nothing else, to ensure it doesn't process the same file multiple times).

如果你真的有动机去做(不推荐),你可以访问这张地图:

You can access this map if you are really motivated to do (would not recommend it) with:

        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);

在假设置上运行,我有dummy-plugin.jar,它引用external.jar(in dummy-plugin.jar的清单我得到以下内容:

Running that on a dummy setup where I have dummy-plugin.jar which references external.jar (in the manifest of dummy-plugin.jar) I get the following:

1)创建类加载器之后(加载任何类之前):

1) Immediately after creating the class loader (before loading any class):

urlClassLoader.getURLs()=[file:.../dummy-plugin.jar]
getSecretUrlsStack=[file:.../dummy-plugin.jar]
getSecretLmapField={}

2)从中加载一个类之后dummy-plugin.jar:

2) After loading a class from 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加载一个类后:

3) After loading a class from 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的权限创建。

The classes that are loaded are by default granted permission only to access the URLs specified when the URLClassLoader was created.

这篇关于类加载器如何在清单类路径中加载类引用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆