为什么手动gc没有用?

124 阅读2分钟

背景

在项目发布运行一段时间后,偶然间查看日志,发现时有发生OOM的记录,top命令一看,物理内存所剩无几,并且在长时间无任务执行的情况,内存一直没有得到释放。思来想去,试下手动gc?但是结果毫无波澜~

为什么手动gc没有用?

System.gc()

以下是经过一番查阅后得到的结果:

手动调用 System.gc() 方法并不一定会立即执行垃圾回收。这是因为 Java 中的垃圾回收是由 JVM(Java虚拟机)自动管理的,它会根据一些策略来判断何时执行垃圾回收操作。

调用 System.gc() 方法只是向 JVM 提出建议,希望执行垃圾回收操作。但是,JVM可以选择忽略这个建议,因为它可能认为当前时机不适合执行垃圾回收,或者系统资源不足等其他原因。

此外,垃圾回收是一个耗时的操作,可能会导致应用程序的性能下降。因此,JVM会根据需要自动决定何时执行垃圾回收,以平衡性能和内存管理的需求。

如果你希望确保垃圾回收被执行,可以尝试以下几种方法:

  1. 在调用 System.gc() 方法后,加入一些等待时间,以便给JVM执行垃圾回收的机会。

  2. 增加JVM的堆内存大小,这样可以减少垃圾回收的频率,提高垃圾回收的效率。

  3. 优化代码,减少内存泄漏和不必要的对象创建,以降低垃圾回收的压力。

总之,虽然可以手动调用 System.gc() 方法建议执行垃圾回收,但最终是否执行取决于JVM的决策。在大多数情况下,我们应该信任JVM的自动垃圾回收机制,并避免过度干预。

最后

导致OOM的原因分析:

  • 虚拟机内存分配不合理。

    根据应用程序的特性和需求,调整了新生代与老年代内存大小的比例。经过对虚拟机各个分区使用情况进行查看,发现新生代使用了很少的空间,而老年代几乎使用殆尽,于是,增加了配置-XX:NewRatio=2 ,意思是将新生代和老年代的内存比例设置为 2:1。也就是说,新生代的内存大小将是老年代的一半。

  • 服务器对当前应用所在实例资源分配不够。

随着应用功能的不断迭代,程序对资源的需求也会越来越大,早期分配的资源早已经捉襟见肘了,很明显,这时候需要进行一定量的扩容了。