2012-03-09 53 views
6

我目前正在为Java 1.7构建本机JVMTI代理。问题是我需要索引关于特定Java对象实例的一些数据。所以我的问题是我可以使用jobject类型的值作为对象的实例ID来检索我的索引数据?如何唯一区分Java的对象实例

我已查找有关jobject类型的语义是什么的任何信息。它是Object的内存位置上的指针吗?它是一个堆栈指针地址?它是否是JVM内部结构的地址?所以我无法弄清楚jobject的价值是否独一无二,并且随着Java对象的生活而不可变。

感谢您的帮助。

编辑

按照JNI的规范发现here,jobject似乎是对对象实例的指针。

+0

到目前为止,你做了什么?根据你所获得的信息,你试图获取和索引或检索的信息的确切类型是什么? – 2012-03-09 19:35:04

+0

可能类似:http://stackoverflow.com/questions/909843/java-how-to-get-the-unique-id-of-an-object-which-overrides-hashcode – 2012-03-10 00:31:15

+0

其实,我的问题是关于一个用C语言编写的JVMTI代理程序。我想将Object的实例用作缓存目的的主键(例如实现为哈希映射或红黑树)。现在,我使用SetTag标记每个对象的唯一标识&GetTag功能。 – Gu0sur20 2012-03-10 21:12:46

回答

2

当你说你“jobject类型的价值”我猜你的意思是由toString返回的值。如果你看一下Java文档它指出:

Object类的toString方法返回一个包含其中的对象是一个实例,则在符号字符'之类的名称的字符串@”,以及该对象的哈希码的无符号十六进制表示。换句话说,该方法返回一个字符串等于值:

getClass().getName() + '@' + Integer.toHexString(hashCode()) 

如果你看一下Java文档的hashCode方法它指出:

每当调用上一个Java应用程序的执行期间,在同一对象一次以上,hashCode方法必须一致地返回相同的整数

并且还

尽管合理实际,类Object定义的hashCode方法确实为不同的对象返回不同的整数。 (这一般是通过将该对象的内部地址转换成一个整数来实现的,但不是由的JavaTM编程语言不需要这种实现技巧。)

更新:回应莱恩的评论:System.identityHashCode会把你原来的哈希码,即使哈希码方法被覆盖。然而,像评论一样,它并不是真正独特的。

所以我想你的问题的答案是肯定它是不可变的,它很可能是独一无二的,但你应该阅读你的JVM的文档或源代码。

+0

HashCode对每个对象都是唯一的。但是,如果您覆盖equals,则它应该被覆盖,以便它与任何其他等同于equals的对象相同。 – 2012-03-10 00:29:57

+3

@Ryan不,它肯定是**不总是独一无二的。很明显这样:你将很难保证在64位系统上使用32位的唯一标识符。 – Voo 2012-03-10 00:35:25

+0

此外,equals/hashcode约定表示2个相等的对象具有相同的散列码。所以如果两个对象在语义上相同,它们的哈希码应该是相同的。尽管两个不相等的对象可能具有相同的哈希码,所以System.identityHashCode(或任何哈希码实现)不能保证唯一性。 – 2012-03-10 00:42:26

1

至少在HotSpot中,jobject确实是一个指向对象位置的指针,也就是说,取消引用它会为每个对象提供一个唯一的地址,这是您请求的“唯一且不可变的身份”的一半关于。问题在于垃圾收集过程中地址可能会更改,因为HotSpot可以移动对象。

JVMTI GetTag和SetTag函数内部使用哈希表从对象位置到标记。无论何时移动对象,HotSpot都会更新此散列表,这是您无法从JVMTI代理的位置轻松复制的。如您所说已经在做的事情,为您的标签分配您自己的唯一标识值可能是唯一的途径。