大家下午好

我有一堂课,看起来像这样:

public class Grapheme {
    public Grapheme(int[] code_points) {
        this.code_points = code_points;
    }
    int[] code_points;
}


从bdonlan link提供的below中,我了解到一个Grapheme对象通常需要8个字节的对象标头,4个字节的变量code_points(其类型为引用)和4个字节的填充。

因此,如果我使用代码new Grapheme(null)创建Grapheme实例,则该Grapheme实例通常需要总共16个字节。由于是否为16字节是特定于实现的,因此从这里开始,我将此数字称为x字节。

基本上,我想知道是否创建n个Graphemes,将所有元素的null传递给构造函数Grapheme(int[]),并将这些Graphemes存储到长度为n的数组中,

运行时(用于存储Grapheme实例)所需的总内存是否严格为n * x字节?

还是JVM有机会尝试做一些魔术优化,使所需的内存低于n * x字节?

最佳答案

否。对象的大小是固定的。考虑-如果JVM确实将您的Graphemes打包成一个数组,并且它们之间没有空格,那么如果某些代码稍后更改code_points的值会发生什么呢?它必须四处移动所有其他的Graphemes,并重写指向其中任何一个的任何指针。这将对性能产生巨大的影响(您可能需要执行完整的GC来重写所有这些指针...),并且对于试图弄清为什么简单的分配如此缓慢的程序员,这是完全不可理解的。因此,JVM不会进行此类优化。

另请注意,您的间接费用估算有些偏差。根据this page,对象的开销为8个字节,加上任何内部字段的空间为12个字节。然后将其舍入为8字节的倍数-因此,在32位平台和Hotspot JVM上,这里的Grapheme对象总共为16字节。任何指向Grapheme对象的指针都将占用额外的空间(每个指针可能大约4个字节)。对象本身不需要空间来存放其自身的地址。该内存由其他东西拥有(例如,堆栈框架或其他对象)。

10-01 00:32