Java 8分配了太多内存

时间:2015-09-08 15:08:54

标签: java eclipse memory-management java-8

我正在使用java.lang.ClassCastException: java.util.Date cannot be cast to java.sql.Timestamp 运行Eclipse 4.3。当我升级到Java 7 JRE时,Eclipse会突然消耗更多内存。如果我将带有Java 8 JRE的Eclipse直接启动到我的工作区,它会根据任务管理器分配600 MB的RAM。当我使用JRE 7时,此值为750 MB。

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

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

JRE 8

2 个答案:

答案 0 :(得分:10)

问问题的方式

  

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

我认为任何人都无法回答,但有几条指南可能有所帮助。鉴于您通过任务管理器测量内存,您对使用的RSS总量感兴趣。所以

  • 第1步: 比较正在运行的版本之间的JVM默认值。您可以使用java -XX:+UnlockDiagnosticVMOptions -XX:+PrintFlagsFinal -version命令为两个jdks获取它们。在输出之上使用文本排序,您将能够使用任何比较工具获得不错的差异。更改默认GC收集器和线程堆栈大小之类的事情将影响最终的RSS。
  • 第2步: 测量每个内存池的分配。通常,java使用的总内存可以使用heap + metasize + code cache + native + (thread_stack_size * maximum_number_of_threads)计算
    • 通过成熟工具(Eclipse Memory AnalyzerVisualVM等),可以轻松测量堆内存(并且可以轻松比较!!)。如果你记忆 堆积面积增加 - 你很幸运。在附加的visual vm中,允许您安装插件,该插件将显示可通过jmx访问的所有内存池的值。
    • metasize(在jdk< 8中称为permgen)应该更多/更少相等,并且可以使用jmap工具找到。不需要玩旗帜,你可以得到号码,只要比较增加或不比较。
    • Code cache:除了保留代码缓存,您还可以设置初始代码缓存(这将影响使用RSS的数量)。
    • 土生土长的:它有点像黑羊。如果所有其他内存池相等(内存大小为2GB),则内存丢失必须位于本机区域的某处。我唯一知道的工具是jcmd,它在oracle文档中有大量文档。

非技术性 - 虽然为了减少记忆而调整各种选项可能有所帮助,但获得正确值的机会接近于在大海捞针中找到针。我真的建议了解如何在java中使用RSS。这些知识将在未来几年内得到应用!

如果您想了解更具体的参考资料或更好的解释,请随时告诉我们。并祝你好运! - )

答案 1 :(得分:1)

我可以确认我正在使用的Web应用程序(Jetty,Struts2,JDBC)在JRE 1.8.0_72中运行后,在启动后立即消耗大约300 MB的RAM(1.2G),而不是JRE 1.7.0_80。该应用程序在Centos 6 x64上运行,并使内存测量尽可能透明,我已禁用交换和设置-Xms等于-Xmx(可用RAM的40%)。我使用dstat --top-memtop -m来获取java进程消耗的总内存。

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

  

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

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