如何转储来自旧一代JVM堆的Java对象?

如何转储来自旧一代JVM堆的Java对象?,java,garbage-collection,jvm,mat,Java,Garbage Collection,Jvm,Mat,是否有任何工具可以转储旧一代JVM堆 换言之,我如何判断一个物体是来自年轻一代还是老一代?一般来说,答案是否定的,没有。这是因为尽管JVM将堆组织成不同的部分,但没有一种只查看旧区域的转储机制。事实上,在较新的JVM上有几种不同类型的区域,包括eden、survivor(一代和两代)和旧代,它们可以包括新生成的巨大对象 您可以使用jmap或jcmd执行堆转储,它们可以选择只生成活动对象或所有对象。如果您真的需要知道,您可能能够分析堆转储并确定它在任何时候来自哪个区域,但一般来说,您真的不需要知道

是否有任何工具可以转储旧一代JVM堆


换言之,我如何判断一个物体是来自年轻一代还是老一代?

一般来说,答案是否定的,没有。这是因为尽管JVM将堆组织成不同的部分,但没有一种只查看旧区域的转储机制。事实上,在较新的JVM上有几种不同类型的区域,包括eden、survivor(一代和两代)和旧代,它们可以包括新生成的巨大对象

您可以使用
jmap
jcmd
执行堆转储,它们可以选择只生成活动对象或所有对象。如果您真的需要知道,您可能能够分析堆转储并确定它在任何时候来自哪个区域,但一般来说,您真的不需要知道。如果选择“活动”对象,则它将(实际上)在heapdump上执行GC以删除任何不被视为活动的对象


一个更好的问题是尝试并理解您试图实现的目标,并确定是否有工具(如各种PrintGC*标志)可以向您显示答案,例如对象升级的频率。

如果您运行Oracle JDK或OpenJDK,您可以使用
sa jdi.jar
来实现这一点。它可以发现老一代的界限。下面是一个在OldGen边界内的对象之间收集堆直方图的示例

也可以从Java进程中找到旧一代的地址,请参阅

整洁的工具:)然而,将老一代从新一代中分离出来的想法实际上只适用于旧的地面军事系统;G1GC以不同的方式管理堆布局,不再像以前那样拆分为两个连续的部分。
import sun.jvm.hotspot.gc_implementation.parallelScavenge.ParallelScavengeHeap;
import sun.jvm.hotspot.gc_interface.CollectedHeap;
import sun.jvm.hotspot.memory.GenCollectedHeap;
import sun.jvm.hotspot.memory.MemRegion;
import sun.jvm.hotspot.oops.ObjectHistogram;
import sun.jvm.hotspot.oops.Oop;
import sun.jvm.hotspot.runtime.VM;
import sun.jvm.hotspot.tools.Tool;

public class OldGen extends Tool {

    public static void main(String[] args) {
        new OldGen().execute(args);
    }

    @Override
    public void run() {
        MemRegion oldRegion = getOldRegion(VM.getVM().getUniverse().heap());

        ObjectHistogram histogram = new ObjectHistogram() {
            @Override
            public boolean doObj(Oop obj) {
                return oldRegion.contains(obj.getHandle()) && super.doObj(obj);
            }
        };

        VM.getVM().getObjectHeap().iterate(histogram);
        histogram.print();
    }

    private MemRegion getOldRegion(CollectedHeap heap) {
        if (heap instanceof ParallelScavengeHeap) {
            return ((ParallelScavengeHeap) heap).oldGen().objectSpace().usedRegion();
        } else if (heap instanceof GenCollectedHeap) {
            return ((GenCollectedHeap) heap).getGen(1).usedRegion();
        } else {
            throw new UnsupportedOperationException(heap.kind() + " is not supported");
        }
    }
}