【发布时间】:2015-06-26 17:54:18
【问题描述】:
我最近将我的大型 Java 应用程序更改为以 JAR 而不是单个类文件的形式交付。我有 405 个 JARS,其中包含 5000 个类文件。我的问题是,当我将程序作为 JAR(类路径是获取所有 JAR 的通配符)运行时,Java 将不断使用越来越多的内存。我已经看到内存超过 2GB 并且似乎 Java 没有进行世界范围内的垃圾收集来保持较低的内存。如果我对分解的 JAR(仅类文件)运行完全相同的程序,Java 的内存使用率会保持低得多(
在类路径中有 JAR 文件
类路径中的类文件
编辑:我接受了@K Erlandsson 的回答,因为我认为这是最好的解释,而这只是 Java 的一个丑陋怪癖。感谢每一个人(尤其是@K Erlandsson)的帮助。
【问题讨论】:
-
这是堆使用量还是总体占用空间?它是否在 Web 容器中运行?它有自定义类加载机制吗?
-
我认为我正在查看堆/整体。我通过 jconsole 查看了内存使用情况,它不断增长堆。我也可以通过 Windows 任务管理器查看它,并且内存(私人工作集)不断增长。我没有使用自定义类加载机制。这是一个独立的 java 进程(没有 tomcat 等),从命令行运行。
-
如果堆在增长,我可能会在它膨胀时对其进行快照(例如
visualvm)并分析它。 -
很难从远处进行诊断,但是如果内存足够(并且
-Xmx足够高),full GC 的发生频率就会大大降低。很可能多次打开所有这些 JAR 文件会留下大量垃圾,而无需清理应用程序就会不断增长。最终会发生完整的 GC 并收集所有垃圾。如果是这种情况,这是一个很好的例子,用-Xmx保持低最大堆是一件好事。 -
这是个问题吗? JVM 将在需要时进行垃圾收集,这就是为什么当您将堆限制为 128MB 时它可以正常工作的原因。但是如果你有一个大堆,而且它还没有全部用完,那么 JVM 没有停止它正在做的事情来做一个大的垃圾收集这一事实肯定是一件好事,而不是一件坏事,对吧?