深入理解 JVM ------ 调优案例分析与实战

发布时间 2023-04-15 21:26:09作者: archaique

1、大内存硬件上的程序部署策略

网站失去响应是由垃圾收集停顿所导致的,在该系统软硬件条件下, HotSpot虚拟机是以服务端模式运行,默认使用的是吞吐量优先收集器,回收12GB的Java堆,一次Full GC的停顿时间就高达14秒(太大会导致回收停顿时间过长。再加上直接进入老年代,Full GC 次数多

由于程序设计的原因,访问文档时会把文档从磁盘提取到内存中,导致内存中出现很多由 文档序列化产生的大对象,这些大对象大多在分配时就直接进入了老年代,没有在 Minor GC中被清理掉。这种情况下即使有12GB的堆,内存也很快会被消耗殆尽。

将硬件升级到64位系统、16GB内存希望能提升程序效能,却反而出现了停顿问题,尝试 过将Java堆分配的内存 重新缩小到1.5GB或者2GB,这样的确可以 避免长时间停顿,但是在硬件上的投 资就显得非常浪费。

对于用户交互性强、对停顿时间敏感、内存又较大的 系统,并不是一定要使用Shenandoah、ZGC这些明确以控制延迟为目标的垃圾收集器才能解决问题 (当然不可否认,如果情况允许的话,这是最值得考虑的方案),使用Parallel Scavenge/Old收集器,并 且给Java虚拟机分配较大的堆内存也是有很多运行得很成功的案例的,但前提是必须把应用的Full GC 频率控制得足够低。

控制Full GC频率的关键是老年代的相对稳定,这主要取决于应用中绝大多数对象能否符合“朝生夕灭”的原则,即大多数对象的生存时间不应当太长,尤其是不能有成批量的、长生存时间的大对象产生,这样才能保障老年代空间的稳定。

许多网站和B/S形式的应用里,多数对象的生存周期都应该是请求级或者页面级,会话级和全局级的长生命对象相对较少。只要代码写得合理,实现在超大堆中正常使用没有Full GC应当并不困难,这样的话,使用超大堆内存时,应用响应速度才可能会有所保证。

除此之外,如果读者计划使用 单个Java虚拟机实例来管理大内存,还需要考虑下面可能面临的问题: