空Java字符串的大小

我听到一位同事说如果我在Java类中删除一个String成员,即使String为空,我也会支付“24字节”。 这是准确的吗? Integer,Float,Double是一样的吗? (而不是int,float,double,每个只有4,4和8个字节)。

您将支付4或8个字节作为参考 。 是否为每个“容器”对象实例支付额外对象的费用取决于您获取空字符串的方式。 例如,如果您使用文字""那么所有实例都将引用同一个对象,因此您只需要为引用本身付费。

如果您为每个实例创建一个单独的空字符串,那么显然会占用更多内存。

借用这个答案 :程序打印空字符串的32个字节(0表示字符串池中的“”)。

 public static void main(String... args) { long free1 = free(); String s = ""; long free2 = free(); String s2 = new String(""); long free3 = free(); if (free3 == free1) System.err.println("You need to use -XX:-UseTLAB"); System.out.println("\"\" took " + (free1 - free2) + " bytes and new String(\"\") took " + (free2 - free3) + " bytes."); } private static long free() { return Runtime.getRuntime().freeMemory(); } 

确实,你会为Integer而不是int付出更多。 我记得回来检查几个Java版本,整数大约需要24个字节。 只要你有一个String指向一个空对象(也就是什么都没有),你只是在内存中保留一个指针,我不认为JVM会保留一个位置来初始化它,在这种情况下你不是浪费24个字节,只有8个。如果你创建了字符串(即使是空字符串“”)那么你已经在内存中有了一个对象,并且由于所有对象都inheritance了Object,它们会带来一些包袱并占用比你直觉所期望的更多的内存。 根据您对字符串的使用,常见的解决方案是从null对象开始,并在需要时对其进行延迟初始化。

字符串由对象标题(HotSpot上的2个字,J9上的3个字),int字段和char数组引用组成。 Char数组本身由header,int字段和数组的其余部分组成。 一切都填充到8个字节。 通常,字符编码为每个字符2个字节。 一些JVM可以使用替代编码进行char。 有时J9可以用UTF8编码字符串。 如果字符串由简单字符组成,则现代HotSpot将使用每个字符1个字节(基本上是1字节编码的UTF-8字形,如英文字母,数字等)。 否则,对于整个数组,每个字符使用2个字节。

因此,空字符串大小的深度如此:

  • 32位HotSpot上的32个字节(String为16字节,char []为16字节)
  • 64位HotSpot上的56个字节(String为32个字节,char []为24个字节)
  • 带有压缩引用的64位HotSpot上的40个字节(String为24字节,char []为16字节)

通常,不会分配空char数组,因为它的值将被推断。 毕竟所有空的char数组都相等。 因此,空字符串的实际惩罚将是一个浅的字符串大小; 对于今天最常见的情况,这是24个字节 (带有压缩ref的64位HotSpot)。

IBM J9 JVM具有更大的对象标头,它将分配更多。