java 为什么是锯齿形图?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7219532/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 19:09:37  来源:igfitidea点击:

Why a sawtooth shaped graph?

javajvmmemory-managementheap-memoryjvisualvm

提问by buch11

When I run the below mentioned code using NetBeans, the allocated heap size graph resembles a sawtooth shape. I am attaching the screen capture from JVisualVM which shows the heap allocation graph in with a sawtooth shape. The program is a simple infinite loop printing "Hello, World!" into the console.

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

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

enter image description hereCan anyone explain the reason behind the shape of the graph of used heap?

在此处输入图片说明任何人都可以解释已用堆图形形状背后的原因吗?

PS: This happens even if I run it without using NetBeans, so it is most likely not related to NetBeans...

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

回答by Vineet Reynolds

The sawtooth pattern in the heap usage can be explained by the fact that several local variables are created during the invocation of the System.out.printlninvocation. Most notably in the Oracle/Sun JRE, several HeapCharBufferinstances are created in the young generation, as noted in the following snapshot obtained using the memory profiler of VisualVM:

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

Visual VM - Memory snapshot

Visual VM - 内存快照

The interesting bit is in the number of live objects that are present on the heap. The sawtooth pattern results from the young-gen garbage collection cycle that occurs when the eden space fills up; since there is no heavy computational activity performed in the program, the JVM is able to execute several iterations of the loop, resulting in the eden space (of 4MB is in size) filling up. The succeeding young-gen collection cycle then clears out most of the garbage; it is almost always the whole of the eden space, unless the objects are still in use, as indicated by the following gc trace obtained from VisualVM:

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

Visual VM GC probes

可视化 VM GC 探测

The behavior of the sawtooth pattern can thus be explained by a series of object allocations in rapid succession that fill up the eden space, triggering a young gen garbage collection cycle; this process repeats cyclically with no delays as the underlying JVM process is not preempted by another process, and the main thread within the JVM that is responsible for the object allocations is also not preempted by another thread.

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

回答by meriton

Any process allocating objects at regular rate will result in a steady increase in heap memory consumption, followed by instantaneous drops when the garbage collector collects the no longer used objects, resulting in that sawtooth shape.

任何以固定速率分配对象的进程都会导致堆内存消耗的稳定增加,然后在垃圾收集器收集不再使用的对象时瞬间下降,从而导致锯齿形状。

In case you wonder why your java process keeps allocation memory while writing to System.out, keep in mind that other threads (for instance the one feeding the current memory statistics to JVisualVM) may be the ones allocating the memory.

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

回答by Burleigh Bear

There's lots of places it could be coming from, and it's likely implementation dependent. At least the following are possible (but are all merely speculation)

它可能来自很多地方,并且可能取决于实现。至少以下是可能的(但都只是猜测)

  • somewhere in the stack of streams underneath System.out.println there is a byte array allocation (given that one of the basic methods of an output stream is write(bytes []b, int off, int len))

  • it's overhead used by the monitoring software you're using (I've not used it)

  • it's overhead in the netbeans VM where it ends up showing the output

  • System.out.println 下的流堆栈中的某处有一个字节数组分配(假设输出流的基本方法之一是 write(bytes []b, int off, int len))

  • 它是您正在使用的监控软件使用的开销(我没有使用过)

  • 它是 netbeans VM 中的开销,它最终显示输出

回答by ozzo

Actually jVisualVM causing additional object allocation. jVisualVM and jconsole are using Java Management Extensions. Attaching to running application and requesting JVM metrics causing that additional objects are being created. You can verify this by adding to your program call to

实际上 jVisualVM 会导致额外的对象分配。jVisualVM 和 jconsole 正在使用 Java 管理扩展。附加到正在运行的应用程序并请求 JVM 指标导致正在创建其他对象。您可以通过添加到您的程序调用来验证这一点

Runtime.getRuntime().freeMemory() 

which reports free memory in JVM heap. It will show [almost] no memory change by running your code, but as soon as you connect jVisualVM to your program you'll see memory usage increase.

它报告 JVM 堆中的可用内存。通过运行您的代码,它会显示[几乎] 没有内存变化,但是一旦您将 jVisualVM 连接到您的程序,您就会看到内存使用量增加。