如果我在磁盘上获取 2kB 的XML文件,并将内容作为String加载到Java内存中,然后测量对象大小 33kB 。
为什么尺寸大幅增加?
如果我在C ++中做同样的事情,那么内存中生成的字符串对象就更接近2kB。
要测量Java中的内存我正在使用Instrumentation。 对于C ++,我取序列化对象的长度(例如字符串)。
答案 0 :(得分:3)
我认为涉及多个因素。 首先,正如Bruce Martin所说,java中的对象每个对象的开销为16字节,c ++则没有。 其次,Java中的字符串可能是每个字符2个字节而不是1个字节。 第三,可能是Java为其字符串保留了比C ++ std :: string更多的内存。
请注意,这些只是可能产生重大差异的想法。
答案 1 :(得分:3)
假设您的XML文件主要包含ASCII字符并使用表示它们作为单个字节的编码,那么您可以认为内存大小至少是两倍,因为Java在内部使用UTF-16(我听说过一些JVM尝试优化这一点,thouhg)。除此之外,还有2个对象(String实例和一个内部char数组)的开销,其中包含一些字段,IIRC总共大约40个字节。
所以33kb的“对象大小”肯定是不正确的,除非你使用了一个奇怪的JVM。用于测量它的方法肯定存在一些问题。
答案 2 :(得分:1)
在Java String对象中有一些额外的数据,这会增加它的大小 它是对象数据,数组数据和一些其他变量。这可以是数组引用,偏移,长度等。
访问http://www.javamex.com/tutorials/memory/string_memory_usage.shtml了解详情。
答案 3 :(得分:1)
String:String的内存增长跟踪其内部char数组的增长。但是, String类会增加另外24个字节的开销。 对于大小为10个字符或更小的非空字符串,相对于有用负载的额外开销成本(每个字符的2个字节加上4个字节的长度),范围从100到400%。
答案 4 :(得分:0)
是的,你应该GC并给它时间来完成。 Just System.gc();并在循环中打印totalMem()。你最好在数组中创建数百万个字符串副本(测量空数组大小,然后填充字符串),以确保测量字符串的大小而不是程序中可能存在的其他服务对象。单独的字符串不能占用32 kb。但XML对象的层次结构可以。
说,我无法抗拒在Java世界中没有人关心内存(和缓存命中)的讽刺意味。我们知道JIT正在改进,在某些情况下它可以胜过本机C ++代码。因此,不需要为内存优化而烦恼。初步优化是所有邪恶的根源。
答案 5 :(得分:0)
正如其他答案中所述,Java的String正在增加开销。如果您需要在内存中存储大量字符串,我建议您将它们存储为byte []。这样做的内存大小应该与磁盘上的大小相同。
字符串 - > byte []:
String a = "hello";
byte[] aBytes = a.getBytes();
byte [] - >字符串:
String b = new String(aBytes);