java堆分配多少物理内存是怎么决定的?

我有 16G RAM 的机器。我运行带有参数的 java 应用程序-Xms9G -Xmx9G。当我运行top命令时,我看到我的 Java 进程占用了13.8g VIRT,但只有4.6g RES。


  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND

 5019 root      20   0 13.8g 4.7g  18m S  0.7 30.7   3:28.39 java                                     

在运行pmap命令时,我看到只有~3.9g的堆作为RES存在,其余5.7g 在 virtual 中。


Address           Kbytes     RSS   Dirty Mode   Mapping

0000000580000000 9452384 4074228 4074228 rw---    [ anon ]

在使用 监视HPCUR时,我观察到当HPCUR 达到约 3gjvmtop时触发了 GC 。


PID MAIN-CLASS        HPCUR HPMAX NHCUR NHMAX    CPU     GC    VM USERNAME   #T DL

 5019 .1-SNAPSHOT.jar  408m 9216m  192m   n/a  0.25%  0.00% O8U20   webapp  823

我观察到进程的 RES 逐渐增加,RES 中的堆内存(通过 pmap)也逐渐增加。结果 GC 阈值增加。


我对这种行为有几个问题。


是否只使用了 RES 中存在的堆,而不使用 VIRT?

如果我分配了 9G min heap ( -Xms),那么最初为什么只分配了 3.9g RES。这与保持低 -Xms 不一样吗?那么保留 -Xms=-Xmx 有什么意义呢?

在什么基础上决定RES中应该有多少堆?在某处读到它由操作系统管理,但有任何粗略的逻辑吗?

有什么方法可以确保实际使用分配的堆?


MMTTMM
浏览 167回答 2
2回答

函数式编程

VIRT表示虚拟内存 - 这是进程的整个保留地址空间。RSS是常驻集大小——在物理 RAM 中分配的虚拟地址空间部分。对于任何地址范围(不仅是堆)RSS是 的子集VIRT,可能是完整的或空的。似乎您已经探索过pmap- 对于每个虚拟地址范围,它显示了物理分配内存 (RSS) 的确切数量。操作系统在第一次访问时延迟分配物理页面。这就是为什么在相应的页面被读取或写入之前,即使已提交的内存也不是 RSS 的一部分。堆的大部分不在 RSS 中这一事实意味着堆的这一部分从未被触及过。另请参阅此问题。有一个 JVM 选项-XX:+AlwaysPreTouch可以强制接触堆的每一页,从而使其成为 RSS 的一部分。尝试java -Xms9G -Xmx9G -XX:+AlwaysPreTouch。

桃花长相依

是的 HEAP 是 RES(只要它适合主内存)This answer表明这-Xms是对GC的提示,在什么时候需要进行完整的垃圾收集。使用我的本地 JVM 进行测试,我可以确认它不会立即保留内存。您获得的是您的 JVM 不会阻塞大量未使用的内存,但会更快地达到您的下限,因为 GC 运行较少。1 的回答:RES 总是包含所有的 HEAP我的理解是您的选择将实现您的意图。您的应用程序将占用 9GB 内存,然后更频繁地启动垃圾收集。如果您需要更多优化,还有其他选项,例如MinHeapFreeRatio和 取决于所使用的垃圾收集器的选项。您是否打印了 GC 日志并验证是否有问题?如果您看到在达到 9G 之前应用程序启动时运行了很多 GC,我会进一步查看。如果在达到 9G 之前几乎没有运行任何 GC,我会说一切都很好。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java