我有一个重复的过程:
- 从数据库获取一些数据
- 在内存中构建一些对象,添加到集合中
- 将集合中的数据写入文件
每次迭代后,所有对象/集合都会超出范围或设置为 null。 (每次迭代都会重用该集合。)
使用 Java VisualVM,我看到一个如下所示的图表,考虑到这是一个重复的过程,这似乎很奇怪。是的,从数据库返回的数据不同,但通常数量相同。
为什么堆大小一开始会减小?
为什么已用堆与中间的堆大小如此接近?
最佳答案
我不像某些人那样是 GC 方面的专家,但总体思路是,当您启动程序时,您已经给了它初始堆大小、最大堆大小和其他相关参数,然后出发时间到了。
然而,GC 拥有大量智能和针对不同类型任务进行优化的不同算法。一个幼稚的实现只是保持堆大小静态,然后在堆满时收集垃圾。这被称为“停止世界”收集,因为收集器需要停止一切,以便它可以执行一些(或大的)清理。
现代 GC 不仅会因为需要清理而导致运行程序长时间暂停,因此从锯齿波中可以看出,总会进行一些清理工作。但是当您启动一个程序时,GC 不知道该程序将要做什么以及它将如何使用内存。因此,它必须观察发生的情况,分析内存使用情况,然后决定需要保留多少内存以供立即使用,是否需要增加当前堆大小或是否可以减小当前堆大小。
根据程序的行为和所使用的 GC 算法,您可以看到许多不同的模式。只要您没有遇到导致 OutOfMemoryError
的线性增长,您就应该相对安全。当然,除非您想优化正在发生的事情以提高吞吐量、响应能力等,但这是一个更高级的主题,并且当您让代码按照您想要的方式工作时更相关。
关于java - 奇数堆使用模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40162517/