【问题标题】:Identity Hashcode to Java Object身份哈希码到 Java 对象
【发布时间】:2014-01-06 11:13:25
【问题描述】:

我的一个朋友和我有以下赌注:

可以使用Object 中的System.identityHashCode()Java 中使用收到的Identity Hashcode 再次从内存中获取Object。限制是它还没有被垃圾收集器清理。

我一直在寻找一个很长一段时间的答案,但无法找到一个明确的答案。

我认为使用JVMTI 可能会这样做,但我还没有使用它。

你们中有人对此有答案吗?如果我可以在你的网站上这样做,我会给你买一杯咖啡;)

提前致谢, 费利克斯

p.s:我是说这种行为是可以实现的,我的朋友说不可能

【问题讨论】:

    标签: java hashcode jvmti


    【解决方案1】:

    理论上是有可能的,但是你有一些问题。

    • 它是随机生成的,因此它不是唯一的。任意数量的对象(尽管不太可能)都可以具有相同的身份哈希码。
    • 它不是内存位置,当从伊甸园、幸存者空间周围或永久空间中移动时,它不会改变。
    • 您需要找到所有对象根才能找到它。

    如果您可以假设它对静态集合等已知对象是可见的,那么它应该很容易通过反射进行导航。

    顺便说一句,一旦是 64 位 OpenJDK/Oracle JVM,身份哈希码从偏移量 1 开始存储在标头中,这意味着您可以读取它,甚至可以使用 sun.misc.Unsafe 更改它。 ;)

    BTW2 存储在标头中的 31 位 hashCode(不是 32 位)是惰性设置的,也用于偏向锁定。即,一旦您调用 Object.hashCode() 或 System.identityHashCode(),您就会禁用对象的偏向锁定。

    【讨论】:

    • 好的,所以我今天学到了一些东西!感谢您的详细回答。我在哪里可以给你买咖啡?
    • @Rittel 这些天我在城里时经常出差。 ;) 主要是美国和欧洲。
    • @Rittel 添加了一个更晦涩的注释 ;)
    • 哈哈好吧 :D 如果可以的话,我会很高兴组织一杯咖啡 ;)
    • 彼得,如果你碰巧在新加坡,你有很棒的亚美尼亚葡萄酒或白兰地等着你:D
    【解决方案2】:

    我认为你的朋友会赢得这场赌注。 Java/JVM 会为你管理内存,一旦你删除了对某个东西的所有引用,就无法访​​问它。

    幻影引用、弱引用等都旨在允许您所描述的内容 - 因此,如果您保留对某些内容的弱或幻影引用,您可以。 identityHashCode 两者都不是。

    C 和 C++ 可能允许您这样做,因为您可以更直接地控制内存,但即便如此,您也需要内存位置而不是它的哈希。

    【讨论】:

    • ... 并且 C/C++ 具有指向内存地址的引用/指针,这使得查找它们非常更容易。
    • 好的,谢谢,我会看看那些References :)
    【解决方案3】:

    不,因为 identityHashCodes 不一定是唯一的。它们不是指向对象的指针。

    【讨论】:

      【解决方案4】:

      没有。 identityHashCode 不一定是内存地址:它只是hashCode 的默认实现。也不保证所有对象都是唯一的(但不同的实例应该有不同的identityHashCodes)。

      即使 identityHashCode 是从内存地址派生的,对象也可能被重新分配(但根据定义,identityHashCode 不能改变)。

      【讨论】:

      • 当对象在几代之间移动时哈希码不会改变,因此您可以假设它不是内存地址。 ;)
      • 对。我之所以这么写只是因为我想明确指出 Object.hashCode 文档中的注释“这通常是通过将对象的内部地址转换为整数来实现的”。
      • 我的意思是“内部地址”与任何实际地址都不对应。您可以证明具有相同地址的对象,例如在 GC 之后,它们位于 Eden 空间的底部,您可以显示它们具有相同的地址,但它们每次具有不同的哈希码。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-10-22
      • 1970-01-01
      • 2013-06-18
      • 2017-06-19
      • 2019-09-29
      • 1970-01-01
      • 2015-12-17
      相关资源
      最近更新 更多