是否有一种方法可以自动找出实际加载了哪些Java类(尽可能在编译时或在应用程序运行时),并从JAR中排除所有其他类以进行创建较小的JAR?在实践中这真的有意义吗?
我正在谈论应用程序JAR的应用程序类。通常,应用程序中有很多库,而应用程序很少需要这些库的所有功能。因此,我怀疑这将使应用程序小得多。从理论上讲,这可以通过例如Java代理来完成,该Java代理记录应用程序的一次或多次运行(甚至仅通过java -verbose:class)读取哪些类和资源,以及抛出所有其他类的maven插件。从具有依赖项的jar中获取。已经有这样的东西了吗?
澄清:我不是在谈论未使用的依赖项(根本不使用JAR),而是在删除每个包含的JAR的未使用部分。
答案 0 :(得分:1)
好吧,在为您的应用程序创建Uber-JAR时,Maven Shade插件具有选项minimizeJar
:
https://maven.apache.org/plugins/maven-shade-plugin/
但是,正如其他人已经指出的那样,这非常危险,因为它经常无法检测到通过反射或其他动态引用完成的类访问。
答案 1 :(得分:0)
这可能不是自动化的好方法,因为应用程序可以使用反射来初始化对象,或者一个JAR依赖于另一个JAR。
我能想到的唯一方法是逐个删除每个JAR,并检查应用程序是否按预期运行。然后再次使用这种方法,必须测试应用程序的所有模块,因为一个模块可以在没有特定依赖的情况下工作,而其他模块则可以。
更好的解决方案是在开发时要小心。应用程序开发人员在完成代码段之后,在添加依赖项和删除不需要的依赖项时必须小心。
答案 2 :(得分:0)
全球战略。
1)查找运行时加载的所有类。
2)类路径中所有可用类的列表。
3)通过创建仅包含所需类的jar的副本来减少类路径。
我已经完成了第一部分和第二部分,所以我可以为您提供帮助。
1)找出所有已加载的类。您需要100%的代码覆盖率(我不是在谈论测试,而是在生产)。因此,请运行所有可能的方案,以便将加载和记录您的应用程序所需的所有类。
要记录加载的类,请尝试几种方法。 Reflection,–verbose:class flag,您还可以了解Java代理。它允许在运行时修改方法。 This is an example of some java agent code或another java agent example
2)要查找jar中可用的所有类,可以编写一个程序。您需要知道放置应用程序jar的所有位置。循环抛出这些罐子(您可以使用ZipFile
),循环访问ZipFileEntry
条目,并收集所有类。
3)之后,编写重新组装您的应用程序的脚本或程序。例如,现在您可以为每个库创建一个新的jar文件,并仅在其中放置所需的类。
您还可以使用工具(同样,您是程序员,因此请编写程序),该工具检查代码是否与类相关。如果它们用于编译,则您不想删除它们。当我还是学生的时候,我写了代码alanyzer,它为类依赖关系构建了一个面向对象的图。
正如@Gokul Nath KP所指出的,我之前曾这样做。我手动更改gradle和maven依赖项,一一删除,然后进行全面回归测试。我花了一个星期的时间(与数百个开发人员创建的现代企业系统相比,我们的应用程序很小)。
所以,要有创造力,一旦成功,您的项目将被数以百万计的人使用!