引用它自己如何存储在堆栈内存中。例如,假设,
A a = new A();
这个a
也应该存储在内存中,并且应该有一个内存地址吗?
如果我解释更多,如果我们打印System.out.println(a)
,它将打印"对象A"的内存地址。但是如何打印引用a
的内存地址?
更正:如果我们打印System.out.println(a)
,它将打印"对象A"的哈希码。不是对象A的内存地址
答案 0 :(得分:1)
但是如何打印参考文件的内存地址?
你不能,非常简单。 JVM规范没有以任何方式定义堆栈的底层属性,并且严格遵守规范,不能保证它甚至具有内存地址。实际上,在当前的实现中,它确实如此,但是规范留下了未定义的,因此Java没有用于检查堆栈内存布局的接口。
此外,应该注意的是,事实上,堆栈变量根本不能保证具有存储器地址。他们完全驻留在寄存器中并且永远不会被刷新到内存中并不罕见。
但是,还应该提到的是,与您所说的不同,System.out.println(a)
将不打印a
引用的对象的地址。它的打印内容也未被规范定义,但Oracle的实现打印了a
的身份哈希码,而不是其地址。 a
的地址甚至不能保证在其生命周期内保持不变,因为GC可能会移动它。
答案 1 :(得分:0)
你的假设是错误的; System.out.println(a);
将打印对象句柄的地址,而不是objcet本身:
在Oracle的一些Java虚拟机实现中,a 对类实例的引用是指向自身句柄的指针 一对指针:一对包含方法的表 object和指向Class对象的指针,表示类型 对象,另一个是从堆分配的内存 对象数据。
(https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-2.html#jvms-2.7)
由于JVM“保留在执行期间在内存中移动内容的权利”,因此无法保证对JVM对象本身的引用可用于任何事情。事实上,当Java执行垃圾收集时,它无法保证将转发指针放置到活动对象的新地址,这使得垃圾收集可能会呈现JVM地址(即使您可能获取它没用。
有关垃圾收集如何工作的简化说明,请参阅http://www.cs.cornell.edu/courses/cs312/2003fa/lectures/sec24.htm。
答案 2 :(得分:0)
System.out.println(a)
打印a.hashCode()
(除非覆盖a.toString()
),不必是a的地址。