文件大小与Java中的内存大小

File size vs. in memory size in Java

本文关键字:内存 Java 文件大小      更新时间:2023-10-16

如果我在磁盘上取一个大约2kB的XML文件,并在Java中将内容作为字符串加载到内存中,然后测量对象大小,它大约33kB

为什么尺寸会大幅增加?
如果我在c++中做同样的事情,内存中的结果字符串对象更接近2kB。

为了测量Java中的内存,我使用了Instrumentation。对于c++,我取序列化对象(例如string)的长度

我认为有多种因素。首先,正如Bruce Martin所说,java中的对象每个对象有16字节的开销,而c++没有。其次,Java中的字符串每个字符可能是2字节,而不是1字节。第三,可能是Java为string保留了比c++ std::string更多的内存。

假设您的XML文件主要包含ASCII字符,并使用将它们表示为单个字节的编码,那么您可以预期内存大小至少是两倍,因为Java内部使用UTF-16(尽管我听说有些jvm尝试优化这一点)。除此之外,还有2个对象(String实例和一个内部字符数组)和一些字段的开销,总共大约40字节。

所以你的"对象大小"33kb肯定是不正确的,除非你使用一个奇怪的JVM。你测量它的方法一定有问题

在Java字符串对象中有一些额外的数据,这增加了它的大小。
它是对象数据,数组数据和其他一些变量。可以是数组引用,偏移量,长度等。

String: String的内存增长跟踪其内部char数组的增长。但是,String类又增加了24字节的开销。对于大小为10个字符或更少的非空字符串,相对于有用负载(每个char 2字节加上4字节的长度),增加的开销成本范围为100%到400%。

:Java中对象的内存消耗是什么?

是的,您应该进行GC并给它时间来完成。只是system . gc ();并在循环中打印totalMem()。您还最好在数组中创建一百万个字符串副本(测量空数组的大小,然后用字符串填充),以确保您测量的是字符串的大小,而不是程序中可能出现的其他服务对象的大小。字符串本身不能占用32 kb。但是XML对象的层次结构可以。

说到这里,我无法抗拒在Java世界中没有人关心内存(和缓存命中)的讽刺。我们知道JIT正在改进,在某些情况下,它的性能可以超过本地c++代码。因此,不需要为内存优化而烦恼。初步优化是万恶之源。

如其他答案所述,Java的String增加了开销。如果您需要在内存中存储大量字符串,我建议您将它们存储为byte[]。这样,内存中的大小应该与磁盘上的大小相同。

String -> byte[]:

String a = "hello";
byte[] aBytes = a.getBytes();

byte[] -> String:

String b = new String(aBytes);