Java中对象引用的大小是多少,它包含哪些信息?

57

作为程序员,我认为这些看起来像是"位于地址1a234552的java.lang.Object"或类似于s在中的某些内容。

Object s = "hello";

这是否正确?因此,所有引用都是固定大小的吗?

5个回答

66

虽然在许多虚拟机上,引用的大小是本地指针大小(即32位JVM的32位和64位JVM的64位),但这并不是保证 - 特别是HotSpot现在或不久将支持"Compressed Oops",它们是64位JVM中的32位引用。(这并不意味着每个引用都被压缩了 - 阅读链接的文章以获取更多信息,并且还有很多博客文章可供参考。)

针对另一个评论,需要注意的是,引用本身通常只是寻址对象本身的一种方式。无论它是直接内存指针还是其他类型,其目标都是获取对象的数据。这基本上是所有真正重要的事情。如果有一些“备用”位(例如它是64位引用,您不需要所有宽度来表示对象的位置),则VM可以使用该数据进行其他信息,例如其类型,这可能允许一些优化。(有关详细信息,请参见Tom的评论。)

对象本身包含类型信息(可能以Class实例的引用形式或类似形式存在 - 我不太清楚),以及头部中必要的其他“东西”,然后才能到达对象的用户数据。


2
Azul在oop中添加了一些类型信息。如果我没记错的话,48位用于地址,16位用于类型信息(特别是如果48位底部的某些位始终为零,我可能会略微偏离)。我相信这可以快速检查内联、非Megamorphic虚拟方法调用。 - Tom Hawtin - tackline
2
@santiagobasulto:这将根据虚拟机而异。不过差别不大——一个类信息的引用,指示其监视器(锁定状态等)的东西,以及可能被垃圾收集器使用的一些东西。 - Jon Skeet
@JonSkeet 为什么引用的大小通常等于字长?这有什么帮助吗? - Geek
有趣的是,引用的读取和写入是原子性的,即使它们可能是8字节,不像它们的长整型和双精度浮点型8字节对应物(其他基本类型是原子性的)。 - Ciro Santilli OurBigBook.com
1
@CiroSantilli: 我猜想这个想法是,如果底层的 CPU 和操作系统是 64 位的话,引用将只有8个字节宽,这种情况下你很可能会免费获得64位原子性...而在32位CPU上,您将使用32位引用,但long和double仍将是64位。 - Jon Skeet
显示剩余4条评论

10

这不属于JLS或JVM规范,但实际上它将是一个地址:32位CPU上为32位,64位CPU上为64位。

pqism: 好的,我明白了,因为在编译后,我们不再关心声明的类型了?

我们确实关心。这就是为什么存在Class对象的原因。事实上,从其他答案中可以看出,我们足够关心类型以至于通过将类型信息的一部分放入引用中来优化与其交互的方式。


1
32位似乎不算太多,如果包括类型信息的话? - pqism
2
@pqism - 引用本身可能只是指向实际对象的指针。类型信息将与其余对象数据一起存储。也许一个更好的问题是“Java对象的最小大小是多少,它包含什么?” - Eric Petroelje
好的,我明白了。因为编译后我们不再关注声明的类型,所以它真的只是“那个地址上的某个东西”。 - pqism
@pquism:从这个角度看待它。你可以分配一个数组 Object[10000],就像 Map 的支撑数组一样。你实际上不知道是否会使用所有这些条目,而且由于负载因子,它们几乎肯定不会被使用。在这种情况下,在数组序列中存储类型信息是极其愚蠢的。最好将类型信息放在各个对象本身上。 - Sune Rasmussen

3
对象引用的大小取决于JVM和机器架构。通常情况下,在32位机器上,它是32位,在64位机器上,它是64位。但是,我认为OpenJDK 7 JVM将支持“压缩指针”,以在64位机器上节省一些空间。
关于对象类型的信息存储在对象本身中;也就是说,如果您跟随32位或64位指针(或更可能的是句柄)到对象,您会发现另一个指向描述类型的Class实例的指针,以及对象的数据字段。

3

我只想补充一下,在64位平台上,引用可以有32位64位

当启用压缩OOP(默认情况下启用)时,它的大小可以为32位

另一种情况是当堆比4 GB小并且适合于4 GB的初始虚拟空间时,引用可以为32位。例如:

0                            4GB
..................................................
|   < your heap fits here>    |

在这种情况下,源代码表明这是 UnscaledNarrowOop 堆对齐的类型,而对于该类型,引用有32位

2

大多数人倾向于将对象引用视为类似于C语言内存指针的东西。虽然这在技术上并不正确,但大多数实现确实将其实现为指针。例如,在使用压缩对象指针的情况下,JVM仅在64位平台上存储64位指针的3到34位。其他实现也可以选择使用不同的方案:引用可以是包含所有对象的指针数组中的索引。


你的意思是说JLS并没有禁止使用除了类似C语言内存指针的方式之外的其他对象引用存储方式吗? - Pacerier
@Pacerier,这不是JLS,而是JVMS,但除此之外 - 是的,规范并没有禁止这样做。 - Eugene

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接