如何使用jdeps计算所需的java模块列表?
我基本上正在使用一个具有复杂结构的 tomcat web 应用程序,在多个位置有许多 jar 和类,我想使用 jlink
及其 --add-modules< 生成一个 JRE /code> 选项,以减少我使用的二进制文件的重量和攻击面。
澄清一下,如果我使用 jlink --add-modules ALL-MODULE-PATH 包含所有模块,则一切都会顺利运行。
我已经进行了几次尝试:
1) 在整个目录上运行 jdeps
我需要分析的目标是一个经典的 tomcat 结构,其中在多个位置包含 jar 和类。
> tree -L 1 /usr/local/tomcat/
├── LICENSE
├── NOTICE
├── RELEASE-NOTES
├── bin
├── conf
├── db.sh
├── favicon.ico
├── lib
├── logs
├── run
├── save.sh
├── start.sh
├── stop.sh
├── temp
├── webapps
└── work
> find . -name "*.jar" -o -name "*.class" | wc -l
938
我一直在尝试以多种方式使用 jdeps,但是 文档 不是很有帮助。下面是返回类似于我所期望的内容的唯一命令:
> jdeps --recursive --print-module-deps --ignore-missing-deps /usr/local/tomcat/
java.base,java.compiler,java.desktop,java.management,java.naming,java.scripting,java.sql
这种工作按预期进行,但似乎只考虑了类。如果没有 --print-module-deps
我会得到一大堆像这样的未知依赖项
com.my.app -> org.eclipse.jgit.diff not found
即使依赖项已正确安装在 /usr/local/tomcat/webapps/ROOT/WEB-INF /lib/org.eclipse.jgit-5.10.0.202012080955-r.jar
。
一个明显的结果是,有很多未列出的所需模块,并且当使用自定义 JRE 执行应用程序时,由于缺少 java 模块,我会收到错误。
2)在我测试过的目录的每个jar/类文件上运行jdeps,
在每个jar上运行jdeps以添加缺少的模块,尽管使用jdeps的更直接/有效的方法会更好。
查找 . -名称“*.jar”-o -名称“*.class”| xargs jdeps --print-module-deps --ignore-missing-deps 似乎可以解决这个基本用例,但是当应用于更大的 tomcat 项目时,仍然存在运行时异常,所以我认为
ignore-missing-deps
使其毫无意义。
3) 在目录上运行 jdeps,将所有 jar 文件提供给 jdeps 的类路径选项
不确定 jdeps
是否在完整的 tomcat 目录上运行,我尝试提供将所有 jar 文件添加到 jdeps 的 -cp
类路径选项中,并且看起来它消除了一些“未找到”条目(262 => 43)。添加类没有什么区别。
我仍然需要将 --ignore-missing-deps
与 --print-module-deps
和 a tail -1 结合使用来忽略“拆分包”的少量内容警告
# run jdeps on directory (might need `apk -U add findutils` on alpine)
jdeps --multi-release 17 --recursive -cp "$(find . -name "*.jar" -printf "%h/*\n" | sort -u | paste -sd ":")" --ignore-missing-deps --print-module-deps ./ | tail -1
使用此输出,我可以将原来包含 68 个 java 模块的完整列表减少到只有 17 个,从而获得大约 22MB 的空间。 不确定攻击面,但我已经看到了更好的减重效果!
这仍然不完美,例如我发现该应用使用 jar://
文件系统提供程序。 java类中没有特定的import
,因此jdeps无法知道应用程序需要jdk.zipfs
模块来挂载jar...
结论
对我的没有信心二进制;
为什么 jdeps 仍然给我 not find
错误和 split package
警告,我该如何解决这个问题?
I'm basically working with a tomcat webapp that has a complex structure, with many jars and classes at several locations and I want to generate a JRE with jlink
and its --add-modules
option in order to reduce the weight and attack surface of the binaries I use.
To clarify, if I include all modules with jlink --add-modules ALL-MODULE-PATH
everything runs smoothly.
I've given this a few attempts:
1) run jdeps
on whole dir
The target I need to analyse is a classic tomcat structure, which contains jars and classes at several locations.
> tree -L 1 /usr/local/tomcat/
├── LICENSE
├── NOTICE
├── RELEASE-NOTES
├── bin
├── conf
├── db.sh
├── favicon.ico
├── lib
├── logs
├── run
├── save.sh
├── start.sh
├── stop.sh
├── temp
├── webapps
└── work
> find . -name "*.jar" -o -name "*.class" | wc -l
938
I've been trying to use jdeps in several ways but the docs are not super helpfull. Below is the only command that returned something looking like what I'd expect:
> jdeps --recursive --print-module-deps --ignore-missing-deps /usr/local/tomcat/
java.base,java.compiler,java.desktop,java.management,java.naming,java.scripting,java.sql
That kind of works as expected, but it seems to only take the classes into account. Without --print-module-deps
I get a whole bunch of unknown dependencies like this
com.my.app -> org.eclipse.jgit.diff not found
Even though the dependecy is properly installed at /usr/local/tomcat/webapps/ROOT/WEB-INF/lib/org.eclipse.jgit-5.10.0.202012080955-r.jar
.
As an obvious consequence, there are a lot of unlisted needed modules, and when executing the app with the custom JRE, I get errors because of the missing java modules.
2) Run jdeps on each jar/class file of the directory
I've tested runnning jdeps on every single jar to add the missing modules, even though a more direct / efficient approach with jdeps
would be better.
The find . -name "*.jar" -o -name "*.class" | xargs jdeps --print-module-deps --ignore-missing-deps
seems to do the trick on this basic usecase, but when applied to the bigger tomcat project, there still are runtime exceptions so I think the ignore-missing-deps
makes it pointless.
3) Run jdeps on directory, providing all jar files to the classpath option of jdeps
Not being sure if jdeps
is made to run on a full tomcat directory like that, I tried providing all jars to the -cp
classpath option of jdeps, and it looks like it gets rid of some of the "not found" entries (262 => 43). Adding the classes makes no difference.
I still need to use --ignore-missing-deps
in conjuction with --print-module-deps
an a tail -1 to ignore the handfull of "split package" warnings
# run jdeps on directory (might need `apk -U add findutils` on alpine)
jdeps --multi-release 17 --recursive -cp "$(find . -name "*.jar" -printf "%h/*\n" | sort -u | paste -sd ":")" --ignore-missing-deps --print-module-deps ./ | tail -1
Using this output, I can go from the original full list of 68 java modules to only 17, gaining approximately 22MB. Not sure about the attack surface, but I've seen better results on weigh reduction!
This is still unperfect, for example I figured out that the app uses the jar://
FileSystemProvider. There is no specific import
in the java class, so jdeps can't know that the app need the jdk.zipfs
module to mount jars...
Conclusion
Not confident about my binary;
Why does jdeps still gives me not found
errors and split package
warnings, how can I fix that?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论