简体   繁体   English

找出实际加载的Java类并减少jar

[英]Find out which Java classes are actually loaded and reduce jar

Is there a way to automatically find out which Java classes are actually loaded (either during compile time, as far as that's possible, or during the runtime of an application), and to throw out all other classes from a JAR to create a smaller JAR? 有没有办法自动找出实际加载的Java类(在编译期间,在可能的情况下,或在应用程序的运行时),并从JAR中抛出所有其他类以创建更小的JAR ? Does that actually make sense in practice? 这在实践中真的有意义吗?

I am talking about the application classes for an application JAR. 我在谈论应用程序JAR的应用程序类。 Usually there are lots of libraries in an application, and an application rarely needs all features of those libraries. 通常,应用程序中有许多库,而应用程序很少需要这些库的所有功能。 So I suspect that would make a considerably smaller application. 所以我怀疑这会使一个相当小的应用程序。 In theory that might be done for example via an Java agent that logs which classes and resources are read by one or several runs of an application (or even just by java -verbose:class), and a maven plugin that throws out all other classes from a jar-with-dependencies. 从理论上讲,可以通过Java代理来完成,该代理记录一个或多个应用程序运行(或者甚至只是java -verbose:class)读取哪些类和资源,以及抛出所有其他类的maven插件来自jar-with-dependencies。 Is there already something like that? 有这样的东西吗?

Clarification: I am not talking about unused dependencies (JARs that are not used at all), but about removing unused parts of each included JAR. 澄清:我不是在谈论未使用的依赖项(根本没有使用的JAR),而是关于删除每个包含的JAR的未使用部分。

Well, the Maven Shade Plugin has an option minimizeJar when creating an Uber-JAR for your application: 好吧,在为您的应用程序创建Uber-JAR时,Maven Shade插件有一个选项minimizeJar

https://maven.apache.org/plugins/maven-shade-plugin/ https://maven.apache.org/plugins/maven-shade-plugin/

But, as others already pointed out, this is quite dangerous, as it regularly fails to detect class accesses which are done via Reflection or other dynamic references. 但是,正如其他人已经指出的那样,这是非常危险的,因为它经常无法检测通过Reflection或其他动态引用完成的类访问。

It may not be a good approach automate, as application can use reflection to initialise objects or one JAR is dependent on another JAR. 它可能不是一种自动化的好方法,因为应用程序可以使用反射来初始化对象,或者一个JAR依赖于另一个JAR。

Only way that I can think of is to remove each JARs one by one and check if application runs as expected. 我能想到的唯一方法是逐个删除每个JAR并检查应用程序是否按预期运行。 Then again in this approach all modules of the application has to be tested, since one module can work without particular dependency and other may not. 然后,在这种方法中,必须测试应用程序的所有模块,因为一个模块可以在没有特定依赖性的情况下工作而其他模块可以不工作

Better solution is to take care while developing. 更好的解决方案是在开发过程中注意。 The application developer must be careful in adding a dependency and removing unwanted dependency after his/her piece of code is done. 应用程序开发人员必须小心添加依赖项并在完成他/她的代码之后删除不需要的依赖项。

Global strategy. 全球战略。

1) Find all the classes that are loaded during runtime. 1)查找运行时加载的所有类。

2) List of all the classes available in the classpath. 2)类路径中可用的所有类的列表。

3) Reduce your class path by creating copies of jars containing only classes you need. 3)通过创建仅包含所需类的jar的副本来减少类路径。

I have done 1 and 2 part so I can help you. 我做了1和2部分,所以我可以帮助你。


1) Find out all the classes that are loaded. 1)找出所有加载的类。 You need 100 % code coverage (I am not talking about tests, but production). 您需要100%的代码覆盖率(我不是在谈论测试,而是生产)。 So run all possible scenarios, so all the classes your app needs will be loaded and logged. 因此,请运行所有可能的方案,以便加载和记录您的应用程序所需的所有类。

To log loaded classes try several approaches. 要记录加载的类,请尝试几种方法。 Reflection , –verbose:class flag , also you can learn about java agent. 反思-verbose:class flag ,也可以了解java代理。 It allows to modify methods during runtime. 它允许在运行时修改方法。 This is an example of some java agent code or another java agent example 这是一些java代理程序代码另一个java代理程序示例的示例

2) To find all the classes available in jar, you can write a program. 2)要查找jar中可用的所有类,可以编写程序。 You need to know all places where application jars are placed. 您需要知道放置应用程序罐的所有位置。 Loop throw these jars (You can use ZipFile ), loop through ZipFileEntry entries, and collect all classes. 循环抛出这些jar(你可以使用ZipFile ),循环遍历ZipFileEntry条目,并收集所有类。

3) After that write a script or program that reassembles your application. 3)之后编写一个重新组装应用程序的脚本或程序。 For example, now you can create a new jar file for each library and put there only needed classes. 例如,现在您可以为每个库创建一个新的jar文件,并只放置所需的类。

Also you may use a tool (again, you are a programmer, so write a program), which checks code for classes dependence. 你也可以使用一个工具(再次,你是一个程序员,所以写一个程序),它检查代码的类依赖性。 You do not want to remove classes if they are used for compilation. 如果用于编译,则不希望删除类。 When I was a student, I wrote code alanyzer, which builds an oriented graph for classes dependencies. 当我还是一名学生时,我编写了代码alanyzer,它为类依赖项构建了一个面向图。

As @Gokul Nath KP notes, I did this before. 正如@Gokul Nath KP所说,我之前做过这件事。 I manually change gradle and maven dependencies, removing one by one, and then full regression test. 我手动更改gradle和maven依赖项,逐个删除,然后完全回归测试。 It took me a week (our application was small comparing to modern world enterprise systems created by hundreds of developers). 我用了一个星期(与数百名开发人员创建的现代企业系统相比,我们的应用程序很小)。

So, be creative, and in case of success, your project will be used by millions! 因此,要有创意,如果成功,您的项目将被数百万人使用!

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

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