java - 奇数堆使用模式

标签 java heap-memory visualvm

我有一个重复的过程:

  1. 从数据库获取一些数据
  2. 在内存中构建一些对象,添加到集合中
  3. 将集合中的数据写入文件

每次迭代后,所有对象/集合都会超出范围或设置为 null。 (每次迭代都会重用该集合。)

使用 Java VisualVM,我看到一个如下所示的图表,考虑到这是一个重复的过程,这似乎很奇怪。是的,从数据库返回的数据不同,但通常数量相同。

为什么堆大小一开始会减小?

为什么已用堆与中间的堆大小如此接近?

enter image description here (1:43 处大约 30 秒的短暂现象正是 VisualVM 暂时卡住时发生的)

最佳答案

我不像某些人那样是 GC 方面的专家,但总体思路是,当您启动程序时,您已经给了它初始堆大小、最大堆大小和其他相关参数,然后出发时间到了。

然而,GC 拥有大量智能和针对不同类型任务进行优化的不同算法。一个幼稚的实现只是保持堆大小静态,然后在堆满时收集垃圾。这被称为“停止世界”收集,因为收集器需要停止一切,以便它可以执行一些(或大的)清理。

现代 GC 不仅会因为需要清理而导致运行程序长时间暂停,因此从锯齿波中可以看出,总会进行一些清理工作。但是当您启动一个程序时,GC 不知道该程序将要做什么以及它将如何使用内存。因此,它必须观察发生的情况,分析内存使用情况,然后决定需要保留多少内存以供立即使用,是否需要增加当前堆大小或是否可以减小当前堆大小。

根据程序的行为和所使用的 GC 算法,您可以看到许多不同的模式。只要您没有遇到导致 OutOfMemoryError 的线性增长,您就应该相对安全。当然,除非您想优化正在发生的事情以提高吞吐量、响应能力等,但这是一个更高级的主题,并且当您让代码按照您想要的方式工作时更相关。

关于java - 奇数堆使用模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40162517/

相关文章:

java - 如何根据 JSF 中的用户角色隐藏某些内容?

.net - 托管堆和非托管堆

java - PageOutputStream 导致 java.lang.OutOfMemory

java - VisualVM 连接到本地 TomEE 非常慢,无法进行堆转储

java - 我的服务器结果集在循环时花费了很长时间

Java - 直接在 hh :m5 处运行函数

java - 扫描仪和用户输入

java - 谷歌应用程序引擎实例共享堆和堆栈吗?

java - 如何对包装为 .exe 的 Java 应用程序运行分析?

java - BTrace 脚本杀死 Java 虚拟机线程