当前位置: 首页 > 知识库问答 >
问题:

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

穆宾白
2023-03-14

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

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

共有2个答案

贺浩壤
2023-03-14

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

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

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

陶英纵
2023-03-14

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

也可以从过程内部找到旧一代Java地址,参见相关问题。

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");
        }
    }
}
 类似资料:
  • 我正在尝试将Java进程的Linux核心转储转换为堆转储文件,适合用Eclipse MAT进行分析。根据这篇博客文章,适应于较新的OpenJDK 12,我创建了一个核心转储,然后运行将转储转换为HPROF格式: 核心转储文件是22GB,而堆转储文件只有3MB,因此命令可能无法处理整个核心转储。此外,Eclipse MAT无法打开堆转储文件,并显示以下消息:

  • 我正在分析几个堆转储,并对从堆转储获取jvm参数的方法感兴趣。使用eclipse memory analyzer我可以很容易地获得系统属性和类路径,但我想知道是否有方法获得其他参数,如-xms-xmx等。

  • 问题内容: 我收到以下错误: 问题答案: 以下是一些可用来更改堆大小的选项。

  • 我正在尝试使用java堆转储来帮助调查内存泄漏。每当我使用它时: 堆转储文件到达大约16,048 kb并停止增长,jmap将永远运行并且不会停止,除非我杀死它。或者我尝试使用它: 但由于我是从根目录执行它的,并且该过程是从另一个用户运行的,因此我得到了以下结果: 所以我想我的问题是我做错了什么,在尝试获得这个堆转储时,最好的方法是什么?

  • 问题内容: 我正在尝试将一台IBM DB2 UDB服务器中特定模式的内容转储到sql文本文件中(非常类似于mysql的mysqldump功能)。 我遇到了db2look,但是它仅转储模式的结构(仅ddl,没有dml)。 那我该怎么办呢? jrh。 问题答案: 您可以使用SQquirreL(以Java实现的SQL客户端)来完成此任务。在其“对象”树中,将选择所有所需的表,然后从上下文菜单中选择“脚本