2015-06-03 24 views
1

我希望能够获得Java堆转储(通过jmap或JMX等创建的)中使用的相同ID。这是为了能够识别仍在运行的应用程序中的活动对象,而不是相同应用程序的旧内存快照(堆转储)。如何获得在堆转储中使用的对象ID

我已经测试了一下,它并不是hashCode,也不是JDI唯一的ID(您可以在调试器中看到)。

从检查sun.jvm.hotspot.utilities中的代码我假设它是内存中的对象地址。但是,我对sun.misc.Unsafe的测试也没有导致与堆转储中使用的相同的id值。 (在这里看到一些不安全的解释:http://zeroturnaround.com/rebellabs/dangerous-code-how-to-be-unsafe-with-java-classes-objects-in-memory/

任何想法?谢谢 :) !

+0

对象(或其任何超级对象)是否重写hashCode?如果是这样,你可能会运气['System.identityHashCode()'](http://docs.oracle.com/javase/6/docs/api/java/lang/System.html#identityHashCode%28java.lang。 Object%29) – blazetopher

+0

或者它可能像需要hashCode的十六进制值一样简单? 'Integer.toHexString(obj.hashCode())'... – blazetopher

+0

感谢您的评论,但没有,正如我所说的不幸的是不是hashCode。也不是System.identiyHashCode(如果它没有被覆盖,它与普通对象hashCode相同)。不,十六进制或十进制无关紧要。最后它是相同的价值,对吧?大多数堆转储分析器倾向于将值显示为十六进制。在我的情况下,这个值是一个简单的长整型值(可能是因为64位jvm)。 –

回答

2

有两种不同的方法来创建堆转储:从JVM进程内

  1. 使用Dynamic Attach Mechanismjmap这样做),或从外部过程
  2. 使用Serviceability Agentjmap -F

在这两种情况下,堆转储中的对象标识都是创建转储时对象的内存地址。以下是相关的HotSpot源代码:[1][2]

但是,此对象标识在转储文件外部没有意义,因为在垃圾收集期间对象可以在内存中移动。

另一个问题是从Java应用程序中获取Java对象的可靠地址是困难的(甚至是不可能的) - 同样,因为对象可能沿着堆移动,并且因为对象引用的表示可能会有所不同不同的体系结构,环境和JVM选项,例如取决于堆的大小,UseCompressedOops等。这里是an example从Java应用程序中获取对象地址,但这不能保证适用于所有JVM版本。