我的问题是:当构建一个最小的JRE时,如何确保不缺少所需的模块?
为了说明这个问题,这里有一个示例,其中我希望为我的项目构建一个最小的JRE。让我们假设在这个例子中,logback是我唯一的依赖项。
我运行以下命令来查看所需的模块:
$ jar --file=logback-core-1.2.3.jar --describe-module
No module descriptor found. Derived automatic module.
logback.core@1.2.3 automatic
requires java.base mandated
contains ch.qos.logback.core
contains ch.qos.logback.core.boolex
etc. (there are more "contains ch.qos.logback.XXX" lines)看起来我只需要java.base模块,并相应地构建我的最小JRE:
jlink --output jre-min --add-modules java.base然而,在使用最小JRE运行项目时,我遇到了使用logback的电子邮件记录器(TLS上格式错误的电子邮件)的问题。经过反复试验,我发现jdk.crypto.cryptoki模块也是必需的:
jlink --output jre-min --add-modules java.base,jdk.crypto.cryptoki现在我的项目运作良好。我怎么能避免试错的步骤呢?
发布于 2022-01-16 19:31:36
您在那里使用的JAR没有“模块描述符”(参见第一行输出),因此无法告诉您它依赖于什么模块,因此您必须自己找出。这方面的规范工具是jdeps,但它可能还不够。
静态依赖
我编写了jdeps教程,它帮助您开始工作,但有趣的是本节。要旨是这样的命令:
jdeps --class-path 'jars/*' -summary -recursive logback-core-1.2.3.jar其中jars包含所有的Logback依赖项。(如果您手头没有这些模块,您可以不使用--class-path和-recursive,但是您不知道哪些模块是依赖项。)此外,输出还将列出对JDK模块的依赖关系。
动态依赖
jdeps通过分析字节代码来工作,这意味着它只会找到静态链接的依赖项。因此,如果JAR使用反射、服务加载器或其他机制来避免显式地提到它想要使用的类,jdeps将不会注意到它们。
要找到这些情况,您可以使用java命令行选项-XX:DumpLoadedClassList=classes.lst运行一个应用程序,它将生成一个文件classes.lst,其中列出了所有加载的类。
最小运行时
请注意,基本模块java.base使用了许多由其他模块提供的服务,例如由jdk.localedata提供的地区数据。这意味着一个最小的运行时(即不包括服务提供者模块)可能会忽略应用程序所需要的东西(在本例中,可能是地区)。
您可以使用java --describe-module java.base列出服务(请参阅输出中的uses ...列表),然后通过jlink的--suggest-providers选项查找潜在的提供者。
您可以使用jlink的--bind-services选项包括所有可能的提供者,但这立即放弃了“最小”运行时的概念,因为它将包含许多模块。如果您要使用“最小”,那么可能最好一个一个地包含它们。
不管你做什么,都要确保在定制的运行时彻底测试你的应用程序。
https://stackoverflow.com/questions/70664036
复制相似问题