简体   繁体   English

Weblogic - 为什么 Java ClassLoader 不从空清单 jar 中提到的 jars 加载类

[英]Weblogic - Why Java ClassLoader does not load classes from jars mentioned in empty manifest jar

I have recently come across of a scenario where we would have a empty manifest jar (ie jar with just META-INF/MANIFEST.MF having Class-Path attribute) referring to other jar file somewhere on file system.我最近遇到一个场景,我们将有一个空清单 jar(即 jar,只有 META-INF/MANIFEST.MF 具有类路径属性)引用文件系统上某处的其他 jar 文件。 I believe this manifest jar has been created to act like a soft link to a specific version jar so that consumer need not deal with minor version changes of implementing jar.我相信此清单 jar 已创建为充当特定版本 jar 的软链接,以便消费者无需处理实施 jar 的次要版本更改。

manifest.jar:-
----META-INF/
--------MANIFEST.MF

Actual version specific implementation jar (test-1.1.jar):-
----META-INF/
--------MANIFEST.MF
----test/
--------Test1.class

Including manifest.jar in classpath in application does not load actual implementing jar and hence I see ClassNotFoundException.在应用程序的类路径中包含 manifest.jar 不会加载实际实现 jar,因此我看到了 ClassNotFoundException。 Any idea why it does not load and how can I get this jar loaded as expected?知道为什么它不加载以及如何按预期加载此 jar 吗?

Update :更新
I tried this with a sample executable jar and it (sun.misc.Launcher$AppClassLoader) seems to load the class as expected.我使用示例可执行文件 jar 进行了尝试,它 (sun.misc.Launcher$AppClassLoader) 似乎按预期加载了 class。 Referring just manifest.jar in Class-Path in-turn includes the actual implementing jar.在类路径中仅引用 manifest.jar 反过来包括实际实现 jar。
Also, I found that we do have a legacy custom class loader for the project, not sure if that causing this weird behavior.此外,我发现我们的项目确实有一个遗留的自定义 class 加载程序,不确定是否会导致这种奇怪的行为。

By default, shouldn't it take care of the referencing of other jars from manifest.jar?默认情况下,它不应该处理来自 manifest.jar 的其他 jars 的引用吗?
Is there a way to check whether this custom class loader is actually referencing jars mentioned in Class-Path?有没有办法检查这个自定义 class 加载器是否实际上引用了类路径中提到的 jars?

When using java -jar somejar.jar , then the classpath is set up as follows:使用java -jar somejar.jar时,类路径设置如下:

  • Environment variable CLASSPATH is entirely ignored .环境变量 CLASSPATH 被完全忽略
  • The -cp / -classpath switch is entirely ignored . -cp / -classpath开关被完全忽略
  • The Class-Path entry in the manifest of the jar you specified explicitly , ie somejar.jar is read, split on spaces, any relative paths are resolved relative to the directory the jar is in, and that is used as classpath.您明确指定的 jar 的清单中的Class-Path条目,即somejar.jar被读取,按空格拆分,任何相对路径都相对于 jar 所在的目录解析,并用作类路径。
  • The Class-Path entry in any other jar file, including jar files listed in the Class-Path entry of somejar.jar is entirely ignored .任何其他 jar 文件中的 Class- Class-Path条目,包括 somejar.jar 的 Class-Path 条目中列出的somejar.jar文件被完全忽略
  • The Main-Class entry in the manifest of somejar.jar is read, the string found there is loaded as class, and its main method is invoked.读取somejar.jar清单中的Main-Class条目,将在那里找到的字符串加载为 class,并调用其 main 方法。 Any Main-Class entries in any jars you mentioned in the Class-Path entry is entirely ignored .您在Class-Path条目中提到的任何 jars 中的任何Main-Class条目都被完全忽略

In other words, this proxy concept cannot really work.换句话说,这个代理概念并不能真正起作用。 The jar you put in java -jar thejar.jar must have the Main-Class attribute and must list all the required jars to run that application in its Class-Path attribute.您放入java -jar thejar.jar中的 jar必须具有Main-Class属性,并且必须在其Class-Path属性中列出运行该应用程序所需的所有jars。

If you use this instead: java -cp somejar.jar:lib/dep1.jar:lib/dep2.jar:etc com.foo.Main , then the manifest is entirely ignored , and thus whatever you set up in any manifest's Class-Path or Main-Class attribute is irrelevant here.如果您改用它: java -cp somejar.jar:lib/dep1.jar:lib/dep2.jar:etc com.foo.Main Class-Path那么清单将被完全忽略,因此您在清单中设置的任何类Class-PathMain-Class属性在这里无关紧要。

I think what you are observing may be explained by the JAR file spec section on the Class-Path attribute .我认为您所观察到的可能是由 JAR file spec section on the Class-Path attribute解释的。

Specifically:具体来说:

"Currently, the URLs must be relative to the code base of the JAR file for security reasons. Thus, remote optional packages will originate from the same code base as the application." “目前,出于安全原因,URL 必须与 JAR 文件的代码库相关。因此,远程可选包将源自与应用程序相同的代码库。”

"Each relative URL is resolved against the code base that the containing application or library was loaded from. If the resulting URL is invalid or refers to a resource that cannot be found then it is ignored." “每个相关的 URL 都是针对从中加载包含应用程序或库的代码库解析的。如果生成的 URL 无效或引用无法找到的资源,则将其忽略。”

So, if the Class-Path attribute in the MANIFEST.MF file for manifest.jar uses absolute URLs, or URLs starting with "/", or if they do not resolve relative to the location of manifest.jar itself, the corresponding JARs, etc won't be added to the internal classpath.因此,如果manifest.jarMANIFEST.MF文件中的Class-Path属性使用绝对 URL,或以“/”开头的 URL,或者如果它们不相对于manifest.jar本身的位置进行解析,则相应的 JARs,等不会被添加到内部类路径。 They are silently ignored.他们被默默地忽略了。

This would happen if you just copied the manifest.jar into your project...如果您只是将manifest.jar复制到您的项目中,就会发生这种情况......

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM