java堆设置太大不gc_为什么 Java 堆不能设置过小或过大

堆过小

如果分配的堆过于小,新生代和老年代的空间过小,会更快的让其空间充满,导致更快的 GC,最后可能程序的大部分时间可能都消耗在 GC 上。无论是 Minor GC 还是 Full GC。

堆过大

如果分配的过于大,我们又需要考虑到 GC 停顿消耗的时间取决于堆的大小,即,如果增大堆的空间,新生代和老年代的空间过大,当发生 GC 的时候, JVM 要扫描新生代或者整个堆。

而在四种垃圾回收算法中,由于内存碎片的整理机制,需要应用线程时空停顿,此时堆又过大,导致 JVM 整理的时间变长,与之停顿的持续时间也会变长。

这种情况下,虽然停顿的频率会变得更少,但是它们持续的时间会让程序的整体性能变慢。

还有一个风险是,操作系统使用虚拟内存机制管理机器的物理内存。一台机器可能有 8G 的物理内存,不过操作系统可能让你感觉有更多的可用内存。

虚拟内存的数量取决于操作系统的设置,譬如操作系统可能让你感觉它的内存达到了 16G 。操作系统通过名为“交换”(swapping)(或者称之为分页,虽然两者技术存在差异)。

你可以载入需要 16G 内存的应用程序,操作系统在需要时会将程序运行时不活跃的数据由内存复制到磁盘。再次需要这部分内存的内容时,操作系统再将它们由磁盘重新载入到内存(为了腾出空间,通常它会先将另一部分内存的内容复制到磁盘)。

系统中运行着大量不同的应用程序时,这个流程工作的很顺畅,因为大多数的应用程序不会同时处于活跃状态。但是,对于 Java 应用,它工作得并不那么好。

如果一个 Java 应用使用了这个系统上大约 12G 的堆,操作系统可能在 RAM 上分配了 8G 的堆空间,另外 4G 的空间存在于磁盘。这样操作系统需要将相当一部分的数据由磁盘交换到内存,如果发生了 Full GC 时,因为这时候 JVM 必须访问整个堆的内容,如果系统发生内存交换,停顿时间会更长。

这时就算用 Concurrent(G1) 收集器也不管用, Concurrent 收集器虽然使用了多线程收集,但是这时候,JVM 本身需要等待系统从磁盘复制数据到内存中(有可能堆数据部分存在内存,部分存在磁盘中)。

来自于《Java 性能权威指南》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值