Java 8 分配了太多内存

2022-09-01 13:25:28

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

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

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

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

答案 1

提问方式

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

我不认为任何人都能回答,但是有几个指导方针可能会有所帮助。鉴于您是通过任务管理器测量内存的,因此您对使用的总RSS感兴趣。所以

  • 第 1 步:比较您正在运行的版本之间的 JVM 缺省值。您可以使用两个jdk的命令来获取它们。在输出之上使用文本排序,您将能够使用任何比较工具获得漂亮的差异。更改默认 GC 收集器和线程堆栈大小等操作将对最终 RSS 产生很大影响。java -XX:+UnlockDiagnosticVMOptions -XX:+PrintFlagsFinal -version
  • 第 2 步:测量每个内存池的分配。一般来说,java使用的总内存可以使用heap + metasize + code cache + native + (thread_stack_size * maximum_number_of_threads)
    • 堆内存很容易被成熟的工具(Eclipse Memory AnalyzerVisualVM等)测量(而且可以很容易地比较!!)。如果你在堆区域内存增加 - 你很幸运。在其他可视化vm中,允许您安装插件,该插件将显示可通过jmx访问的所有内存池的值。
    • metasize(在jdk<8中又名permgen)应该或多或少相等,并且可以使用jmap工具找到。无需玩旗帜,您可以获得数字,并在增加或不增加时进行比较。
    • 代码缓存:除了保留的代码缓存之外,您还可以设置初始代码缓存(这将影响RSS的使用量)。
    • 本地人:有点黑羊。如果所有其他内存池都相等(您的内存凸起为 2GB),则内存丢失必须位于本机区域的某个位置。我所知道的唯一工具是jcmd,它在oracle文档中有大量文档。

非技术性 - 虽然调整各种选项以减少内存可能会有所帮助,但获得正确值的机会接近于大海捞针。我真的建议有一个关于RSS如何在java中使用。这些知识将在相当长的几年内派上用场!

请让我知道,每当你需要更具体的参考或更好的解释。和。。。祝你好运;-)


答案 2

我可以确认,与 JRE 1.7.0_80 相比,我正在处理的 Web 应用程序(Jetty、Struts2、JDBC)在启动后立即消耗了大约 300 MB 的 RAM (1.2G)。该应用程序在Centos 6 x64上运行,为了使内存测量尽可能透明,我禁用了交换并将-Xms设置为-Xmx(可用RAM的40%)。我已经使用或获取java进程消耗的总内存。dstat --top-memtop -m

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

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

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