Netbeans 包含堆栈帧变量的保留大小计算?

Netbeans 包含堆栈帧变量的保留大小计算?,netbeans,jvm-hotspot,hprof,Netbeans,Jvm Hotspot,Hprof,我发现了很多关于“保留尺寸”的问题,问题似乎是: 对象的保留大小是该对象从垃圾收集中保留的内存量 现在,我一直在使用(保留大小计算在hprof.java中完成)对hprof文件(定义)中的保留大小进行编程计算。工作正常(抱歉,为了简洁起见,使用了kotlin): 当sizeMap只有少量保留大小时,我注意到Netbeans只为不在堆栈上的对象计算保留大小。因此,分配给线程的局部变量(在堆栈上分配)将不包括在保留大小中 我的问题是:有没有办法让NETBeas库将堆栈元素视为依赖对象?例如,YouK

我发现了很多关于“保留尺寸”的问题,问题似乎是:

对象的保留大小是该对象从垃圾收集中保留的内存量

现在,我一直在使用(保留大小计算在
hprof.java
中完成)对
hprof
文件(定义)中的保留大小进行编程计算。工作正常(抱歉,为了简洁起见,使用了kotlin):

sizeMap
只有少量保留大小时,我注意到Netbeans只为不在堆栈上的对象计算保留大小。因此,分配给
线程的局部变量(在堆栈上分配)将不包括在保留大小中


我的问题是:有没有办法让NETBeas库将堆栈元素视为依赖对象?例如,YouKIT剖析器是计算吗?如果上一个问题的答案是“否”,我将如何添加这样一个功能?

经过一番挖掘,发现JVM堆转储程序为堆栈局部变量(比较)创建了一个
ROOT JAVA FRAME
类型的条目。因为我可以在堆中对此进行grep,所以我所做的如下:

val threadClass: JavaClass = heap.getJavaClassByName("java.lang.Thread")

val keyTransformer = { it: Instance -> findThreadName(it) }
val instanceFilter = { it: Instance -> it.getJavaClass() == threadClass }

val stackLocals = heap.gcRoots
        .filter { it.kind == GCRoot.JAVA_FRAME }
        .groupBy { (it as JavaFrameGCRoot).threadGCRoot }

val sizeMap = heap.allInstances
      .filter { instanceFilter(it) }
      .toMap(
          { keyTransformer(it) }, 
          { 
              val locals = stackLocals[heap.getGCRoot(it)]
              val localSize = locals!!.sumBy { it.instance.retainedSize.toInt() }
              it.retainedSize + localSize
          })

return Report(
        sizeMap.values.sum(),
        sizeMap.keys.size.toLong(),
        sizeMap.maxBy { it.value }?.let { it.toPair() } ?: ("n/a" to 0L))
此解决方案基于查找每个线程的GC根(应该是
线程
本身),然后排序到
JAVA框架
的存储GC根(线程[=GC根]id是存储的条目数据的一部分)

与Yourkit中的值相比,仍然有一些细微的差异,可能是因为我缺少
根JNI LOCAL
实体,但对我来说已经足够接近了

val threadClass: JavaClass = heap.getJavaClassByName("java.lang.Thread")

val keyTransformer = { it: Instance -> findThreadName(it) }
val instanceFilter = { it: Instance -> it.getJavaClass() == threadClass }

val stackLocals = heap.gcRoots
        .filter { it.kind == GCRoot.JAVA_FRAME }
        .groupBy { (it as JavaFrameGCRoot).threadGCRoot }

val sizeMap = heap.allInstances
      .filter { instanceFilter(it) }
      .toMap(
          { keyTransformer(it) }, 
          { 
              val locals = stackLocals[heap.getGCRoot(it)]
              val localSize = locals!!.sumBy { it.instance.retainedSize.toInt() }
              it.retainedSize + localSize
          })

return Report(
        sizeMap.values.sum(),
        sizeMap.keys.size.toLong(),
        sizeMap.maxBy { it.value }?.let { it.toPair() } ?: ("n/a" to 0L))