Java 8分配了太多内存



我正在运行Eclipse 4.3Java 7 JRE。当我升级到Java 8 JRE时,Eclipse突然消耗了更多的内存。如果我直接在工作空间中启动带有JRE 7的Eclipse,它会根据任务管理器分配600 MB的RAM。当我使用JRE 8时,这个值是750 MB。

更糟糕的是,如果我运行一个大型Java程序,通常使用JRE 7分配大约10gb的RAM,切换到JRE 8会导致它分配12gb的RAM。

有谁知道是什么原因导致这个额外的RAM分配?我已经测试了调整不同的选项,但没有成功:

-XX:ReservedCodeCacheSize=
-XX:MaxMetaspaceSize=
-XX:MetaspaceSize=
...

以提问的方式

为什么Java 8在我的机器上分配了太多内存

我认为没有人能回答这个问题,但是有一些指导方针可能会有所帮助。假设您正在通过任务管理器测量内存,那么您会对使用的RSS总量感兴趣。所以

  • 步骤1:比较您正在运行的不同版本之间的JVM默认值。您可以使用java -XX:+UnlockDiagnosticVMOptions -XX:+PrintFlagsFinal -version命令为这两个jdk获取它们。在输出上使用文本排序,您将能够使用任何比较工具获得不错的差异。诸如更改默认GC收集器和线程堆栈大小之类的事情将对最终RSS产生很大影响。
  • 步骤2:度量每个内存池的分配。一般来说,java使用的总内存可以使用heap + metasize + code cache + native + (thread_stack_size * maximum_number_of_threads)来计算
    • 堆内存易于通过成熟的工具(Eclipse memory Analyzer, VisualVM等)测量(并且可以轻松比较!!)如果你还记得增加堆的面积-你很幸运。在附加的可视化vm允许您安装插件,它将显示通过jmx访问的所有内存池的值。
    • metasize (jdk<8中的permgen)应该是相等的,可以在jmap工具中找到。不需要玩flag,你可以得到数字,只是比较何时增加或不增加。
    • 代码缓存:除了保留的代码缓存,你可以设置初始代码缓存(这将影响RSS的使用)。
    • native:有点害群之马。如果所有其他内存池相等(内存增量为2GB),则内存丢失一定在本机区域的某个地方。我所知道的唯一工具是jcmd,它在oracle文档中有广泛的文档。

非技术-虽然调整各种选项以减少内存可以帮助,但获得正确值的机会接近于大海捞针。我非常推荐有一个关于如何在java中使用RSS的教程。这些知识在今后几年里都很有用!

如果你需要更具体的参考资料或更好的解释,请告诉我。和…祝你好运;-)

我可以确认,在JRE 1.8.0_72下运行的Web应用程序(Jetty、Struts2、JDBC)启动后立即消耗的内存(1.2G)比在JRE 1.7.0_80下运行时多300 mb。应用程序在Centos 6 x64上运行,为了使内存测量尽可能透明,我禁用了swap并将-Xms设置为-Xmx(40%的可用RAM)。我使用dstat --top-memtop -m来获得java进程消耗的总内存。

此外,当Web客户端过于频繁地连接到应用程序时,消耗的总内存会上升,直到系统内存耗尽并杀死java进程。我唯一能看到的是/var/log/messages中的信息:

11月10日21:29:54我的内核:内存不足:杀死进程26610 (java)得分570或牺牲孩子

当我从bash中运行一个无限循环,调用连接到应用程序的4个并行Web客户机(=建立新的TCP连接),请求应用程序状态并断开连接时,应用程序消耗的总内存每分钟增加大约100-200 kb。每个客户端每分钟处理6-10个请求。

最新更新