【问题标题】:Java: How to store and retrieve memory address like in C++Java:如何像在 C++ 中一样存储和检索内存地址
【发布时间】:2011-12-26 12:08:40
【问题描述】:

我来自 C++ 背景。在 C++ 中,我可以将刚刚新建的内存地址存储在全局数组中,然后再使用它。例如,假设我有两个类 X、Y,我创建了两个对象 x、y。全局数组 StoreAddresses[2] 定义为:

 uint32_t StoreAddresses[2];

我写:

 X * x = new X();
 Y * y = new Y();
 StoreAdresses[0] = (uint32t *) x; //for example, 0x12345678
 StoreAdresses[1] = (uint32t *) y; //for example, 0x12345698

在我的程序的任何地方,我都可以通过调用来检索写入内存中的数据:

 X * stored_x = (X*)StoreAdresses[0];
 Y * stored_y = (Y*)StoreAdresses[1];

如何在 Java 中实现这一点? 感谢您的帮助!

【问题讨论】:

  • Java 和 C/C++ 的主要区别之一是 Java 限制了程序员使用和滥用内存的能力。我想您可以使用字节数组来模拟这一点(或使用 unsafe,正如 Peter Lawrey 所说——对他来说是 1+),但更好的是让您学习 Java 的方法并根据其优势调整您的编码,不是它的弱点。
  • 同意@HovercraftFullOfEels - 为了实现您似乎想要做的事情,您应该将XY 的引用存储在静态字段中,而不是乱用内存地址。
  • 真正的问题是:你为什么要这样做
  • 我敢打赌,您需要的是几个大字节数组来进行直接字节操作。如果您不需要直接的字节操作不要访问内存!!访问您的对象!在 Java 中,您总是操纵引用。所以写X x = new X(); x.doThis()等价于C++X* x = new X(); x->doThis()。始终考虑对象指针和箭头访问。
  • 感谢您发帖。我将在下面回复彼得的帖子。我已经不再使用 Unsafe。

标签: java jvm memory-address unsafe


【解决方案1】:

您可以使用 Unsafe 在 Java 中执行此操作。然而,这是一个非常糟糕的主意。这是因为对象的地址可以随时更改(通过 GC)如果您像这样存储地址以便以后使用它,它可能不再有效,甚至会使您的应用程序崩溃。如果 GC 认为一个对象没有强引用,它可能会清理该对象。当您再次尝试引用该对象时,它可能不再在 JVM 中了。

地址的大小可能会根据您启动 JVM 的方式而改变。 64 位 JVM 通常使用 32 位引用(这可能来自 C++ 的惊喜)您可以通过 Unsafe.ADDRESS_SIZE 获得此信息

我只会使用 Unsafe 来查看地址是什么,以查看对象在缓存中的布局方式。 (这不是很有用,因为您对此无能为力:()

很可能您尝试做的事情可以做得更好。你能告诉我们更多细节吗?

【讨论】:

  • 你好彼得。谢谢你详尽的回答。我这么长的原因是我在使用继承时在代码中犯了一个简单的错误……我有一个基类和 4 个子类。即使我在基类中声明了我的原始公共对象,我还是错误地在其中一个孩子中新建了它。所以,所有其他类中的引用都是空的:(这就是我想到 C++ 技巧的原因。现在我在基类中定义了它,问题解决了!顺便说一句,C++ 内存操作在我的商业应用程序中的不同拱门中完美运行没有缺陷。再次感谢您的意见!
  • 它在 C++ 中工作,因为您的指针在使用时不会改变。
【解决方案2】:

彼得说的是对的。我要补充一点,你需要开始用 Java 术语而不是 C++ 术语来思考。

这可能对您有所帮助,Java 中的 X x = new X(); 几乎完全等同于 C++ 中的 X* x = new X();

【讨论】:

  • 嗨,迈克,我知道所有这些东西。请阅读我对彼得的评论:)
【解决方案3】:

是的。 您可以在 Java 中完成此操作。 但是,对于地址操作,C++ 显然是更好的选择。 出于安全原因,Java 没有提供方便地操作地址的工具。

如果你在任何对象上调用 hashCode(),它将返回任何对象地址的字符串表示形式。

【讨论】:

  • 谢谢慕克吉。我还可以使用 toString 并读取 '@' 符号后面的子字符串。
【解决方案4】:

在java中,你可以使用对象引用。没有 void 或 integer 指针,但由于每个对象都继承自 Object,因此您可以改用强制转换对象引用

import java.lang.*;

class test {

    static Object[] StoreObjectRefs = new Object[2];

    public static void main(String args[])
    {
        Integer x = new Integer(1);
        Float y = new Float(2.0);

        StoreObjectRefs[0] = (Object) x;
        StoreObjectRefs[1] = (Object) y;

        System.out.println((Integer)StoreObjectRefs[0]+(Float)StoreObjectRefs[1]);
    }

}

但请注意,引用是在函数中按值传递的。

【讨论】:

    猜你喜欢
    • 2016-09-18
    • 1970-01-01
    • 2014-05-25
    • 1970-01-01
    • 2010-10-02
    • 1970-01-01
    • 2017-03-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多