为什么是锯齿形图?

buc*_*h11 17 java jvm memory-management heap-memory jvisualvm

当我使用NetBeans运行下面提到的代码时,分配的堆大小图类似于锯齿形状.我附加了JVisualVM的屏幕截图,它显示了锯齿形状的堆分配图.该程序是一个简单的无限循环打印"Hello,World!" 进入控制台.

public class HelloWorld {
    public static void main(String a[]){
        while(true) {
            System.out.println("Hello, World!");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述 任何人都可以解释使用堆图形状背后的原因吗?

PS:即使我在不​​使用NetBeans的情况下运行它也会发生这种情况,因此它很可能与NetBeans无关......

Vin*_*lds 23

堆使用中的锯齿模式可以通过在调用调用期间创建几个局部变量的事实来解释System.out.println.最值得注意的是在Oracle/Sun JRE中,HeapCharBuffer在年轻代中创建了几个实例,如使用VisualVM的内存分析器获得的以下快照中所述:

Visual VM  - 内存快照

有趣的是在堆上存在的活动对象的数量.锯齿形图案是由伊甸园空间填满时发生的年轻垃圾收集周期产生的; 由于在程序中没有执行繁重的计算活动,JVM能够执行循环的多次迭代,从而导致伊甸园空间(大小为4MB)填满.随后的年轻人收集周期然后清除大部分垃圾; 它几乎总是整个伊甸园空间,除非对象仍在使用中,如从VisualVM获得的以下gc跟踪所示:

Visual VM GC探针

因此,锯齿形图案的行为可以通过一系列快速连续的物体分配来解释,这些物体分配填满了伊甸园空间,触发了年轻的垃圾收集循环; 由于底层JVM进程没有被另一个进程抢占,因此该进程不间断地重复循环,并且JVM中负责对象分配的主线程也不会被另一个线程抢占.

  • 局部变量是无关紧要的。垃圾收集是关于*对象*,而不是变量。此外,值得注意的是,这种模式并不特定于年轻代,而是每次有多个分配但有一个释放操作时都会发生。 (2认同)

mer*_*ike 6

以常规速率分配对象的任何进程将导致堆内存消耗的稳定增加,随后在垃圾收集器收集不再使用的对象时瞬间下降,从而产生锯齿形状.

如果您想知道为什么您的java进程在写入时会保留分配内存System.out,请记住其他线程(例如将当前内存统计信息提供给JVisualVM的线程)可能是分配内存的线程.