Java JAR内存使用VS类文件内存使用情况

Ada*_*dam 8 java profiling

我最近将我的大型Java应用程序更改为在JAR中提供,而不是单个类文件.我有405个JARS,它拥有5000个类文件.我的问题是,当我将程序作为JAR运行时(类路径是一个通配符来获取所有JAR),Java将不断使用越来越多的内存.我已经看到内存大于2GB,看起来Java并没有采用世界末日的垃圾收集方式来降低内存.如果我对爆炸的JAR(只有类文件)运行完全相同的程序,Java的内存使用率会保持低得多(<256MB)并保持不变.这种情况发生在Windows 7(x64)和Windows Server(x64)上的Oracle Java 8中.为什么将我的应用程序打包为JAR会更改内存配置文件?此外,我已经运行了很长一段时间的程序作为JARs,内存最大限制为128MB,没有任何问题,所以我没有内存泄漏.

使用类路径中的JAR文件 使用类路径中的JAR文件

使用classpath中的类文件 使用classpath中的类文件

编辑:我接受了@K Erlandsson的回答,因为我认为这是最好的解释,这只是一个丑陋的Java怪癖.感谢每一位(特别是@K Erlandsson)的帮助.

K E*_*son 3

首先要注意的是,堆上总共使用了多少内存始终不是很有趣,因为大部分已使用的内存可能是垃圾,并将被下一次 GC 清除。

您需要关心的是活动对象使用了多少堆。您在评论中写道:

我不知道这是否重要,但如果我使用 jvisualvm.exe 强制 GC(标记扫描),堆内存使用量将下降,清除几乎所有堆内存。

这很重要。很多。这意味着当您使用 jar 时看到更高的堆使用率时,您会看到更多的垃圾,而不是活动对象消耗的更多内存。当您执行 GC 时,垃圾就会被清除,一切都很好。

从 jar 文件加载类比从类文件加载类会暂时消耗更多内存。需要打开、查找和读取 jar 文件。这比简单地打开特定的文件需要更多的操作和更多的临时数据。.class

由于大部分堆使用量都由 GC 清除,因此您不需要非常关心这种额外的内存消耗。

你还写:

Java 将不断使用越来越多的内存。我已经看到内存超过 2GB,而且 Java 似乎没有进行停止世界的垃圾收集来保持较低的内存。

这是典型的行为。GC仅在JVM认为有必要时运行。JVM 将根据内存行为对此进行调整。

编辑:现在我们看到您的 jConsole 图像,我们看到提交的堆内存存在差异(250 mb 与 680 mb)。提交堆是堆的实际大小。这会有所不同(取决于您设置的内容)-Xmx),具体取决于 JVM 认为将为您的应用程序带来最佳性能的内容。然而,它大部分会增加,几乎不会减少。

对于 jar 情况,JVM 已为您的应用程序分配了更大的堆。可能是由于初始类加载期间需要更多内存。然后 JVM 认为更大的堆会更快。

当您拥有更大的堆、更多提交的内存时,在运行 GC 之前可以使用更多的内存。这就是为什么您会看到两种情况下内存使用情况存在差异的原因。

底线:您看到的所有额外使用都是垃圾,而不是活动对象,因此您不需要担心此行为,除非您遇到实际问题,因为内存将在下一次 GC 时回收。