我正在运行Eclipse 4.3
与Java 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-mem
或top -m
来获得java进程消耗的总内存。
此外,当Web客户端过于频繁地连接到应用程序时,消耗的总内存会上升,直到系统内存耗尽并杀死java进程。我唯一能看到的是/var/log/messages中的信息:
11月10日21:29:54我的内核:内存不足:杀死进程26610 (java)得分570或牺牲孩子
当我从bash中运行一个无限循环,调用连接到应用程序的4个并行Web客户机(=建立新的TCP连接),请求应用程序状态并断开连接时,应用程序消耗的总内存每分钟增加大约100-200 kb。每个客户端每分钟处理6-10个请求。