我正在阅读Peter Norvig的IAQ(不经常问的问题-link),然后发现了这个:
您可能会惊讶地发现,在Sun JDK VM中,一个对象占用16个字节或4个字,这可以分解如下:有一个两个字的头,其中一个字是指向对象类的指针,另一个指向实例变量。即使Object没有实例变量,Java仍然为变量分配了一个字。最后,还有一个“句柄”,它是另一个指向两个字头的指针。Sun表示,这种额外的间接层使垃圾收集更简单。(至少15年来,已经有高性能的Lisp和Smalltalk垃圾收集器不使用额外的层次。我听说但尚未证实Microsoft JVM没有额外的间接层。)创建一个空的new String()需要40个字节或10个字:3个指针开销,3个用于实例变量(起始索引,结束索引和字符数组)的字,以及4个用于空字符数组的字。创建现有字符串的子字符串只需6个字,因为字符数组是共享的。将整数键和整数值放入Hashtable中需要64个字节(除了Hashtable数组中预先分配的4个字节之外):我会让您自己思考原因。我显然尝试了,但是我想不出来。在下面的计数中,我只计算单词数:Hashtable put 创建一个 Hashtable$Entry:3(开销)+ 4 个变量(3 个引用,我假设每个引用占 1 个字 + 1 个 int)。我进一步假设他的意思是 Integer 是新分配的(因此不是由 Integer 类缓存或已存在),这样就会得到 2 *(3 [开销] + 1 [1 个 int 值])。所以最终我们得到..15 个单词或 60 字节。所以我最初想到的是 Entry 作为内部类需要引用其外部对象,但遗憾的是它是静态的,所以这没有太多意义(当然,我们必须存储指向父类的指针,但我认为该信息存储在 VM 的类头中)。只是好奇,我很清楚所有这些都取决于实际的 JVM 实现(在 64 位版本上,结果将不同),但我仍然不喜欢我无法回答的问题 :)
编辑:为了让这更加清晰:虽然我很清楚更紧凑的结构可以带来一些性能优势,但我同意总体上担心这里或那里的几个字节是浪费时间。我肯定不会仅仅因为有几个字节的开销就停止使用Hashtable,就像我不会使用纯char数组而不是String(或开始使用C)一样。这纯粹是学习Java / JVM内部的一点学术兴趣 :)