【发布时间】:2009-12-31 13:48:55
【问题描述】:
我正在运行递归操作的 NetBeans 配置文件,其中包括创建具有 java.lang.String 字段的类。在类列表中,在配置文件堆转储中,字符串字段的数量对应于按预期创建的类的数量,但也有类似数量的 char[] 实例。 char 数组占内存使用量的近 70%(!),而 String 字段占约 7%。
这里发生了什么?以及如何减少char[] 实例的数量?
谢谢
【问题讨论】:
我正在运行递归操作的 NetBeans 配置文件,其中包括创建具有 java.lang.String 字段的类。在类列表中,在配置文件堆转储中,字符串字段的数量对应于按预期创建的类的数量,但也有类似数量的 char[] 实例。 char 数组占内存使用量的近 70%(!),而 String 字段占约 7%。
这里发生了什么?以及如何减少char[] 实例的数量?
谢谢
【问题讨论】:
看看String source code。 String 对象本身包含一个缓存的哈希码、字符数的计数(同样,出于优化目的)、偏移量(因为 String.substr() 指向原始字符串数据)和字符数组,其中包含实际的字符串数据。因此,您的指标显示 String 消耗相对较少,但大部分内存由底层字符数组占用。
【讨论】:
char数组占近70% 的内存使用(!),而 字符串字段约占7%
这是内存分析的精妙之处,称为“保留大小”和“浅层大小”:
字符串就是一个完美的例子。它包含一些原始字段,以及char[]。 char[] 占内存使用量的绝大部分。 String 的浅层尺寸非常小,但保留的尺寸要大得多,因为其中包括char[]。
NetBeans 分析器可能会为您提供浅尺寸,这不是一个非常有用的数字,但很容易计算。保留大小会将char[] 内存使用量合并到String 内存使用量中,但计算保留大小的计算量很大,因此分析器在明确要求之前不会计算出来。
【讨论】:
byte[] 确实是正确的类型(但这也会改变最初的问题)......
Sun 的 Java 实现中的 String 类使用 char[] 来存储字符数据。
我相信这可以通过使用调试器查看String 的内容或使用反射查看String 对象的内部结构来验证,而无需查看源代码。
因此,很难减少正在创建的char[] 的数量,除非正在创建的String 实例的数量有所减少。
【讨论】:
字符串由 char 数组支持,因此我认为您不能在不减少字符串的情况下减少 char[] 实例的数量。
您是否尝试删除一些字符串以查看 char[] 是否也下降?
【讨论】: