【问题标题】:Does class without data member have memory footprint in java?没有数据成员的类在java中有内存占用吗?
【发布时间】:2011-03-02 22:37:23
【问题描述】:

我的问题与 java 中没有数据成员的类的内存占用有关。假设在java中我有一个没有数据成员的类,它只包含方法。因此,如果我正在创建特定类的实例,那么它是否会占用除对象引用内存之外的主内存中的内存?

【问题讨论】:

    标签: java performance memory-management garbage-collection


    【解决方案1】:

    最终,每个 Java 对象都知道它的类,并且可以选择附加一个同步原语(尽管this 可以是合成的)。这是两个很难让java.lang.Object 实例没有的引用。其他所有内容都来自该类,因此您有一个成本下限,至少为8 bytes in Java 1.3.1。如果您确实需要,分析器会告诉您当前的成本。

    【讨论】:

    • 现代 JVM 将对象监视器数据保存在它所持有的其他指针的未使用位中(例如类指针的底部两位)
    • @Danny:它有 3 位可用; “现代”内存管理器在 8 字节边界上对齐(当不使用更密集的数组时)。我所说的“现代”是指 10 年或更长时间的一切
    【解决方案2】:

    由于各种干扰源(堆增长、GC),对内存进行基准测试很困难,但仍然值得一试:

    public static void main(String[] args)
    {
        final int n = 1000000;
    
        final Runtime runtime = Runtime.getRuntime();
    
        final Object[] objects = new Object[n];
    
        final long memory0 = runtime.totalMemory() - runtime.freeMemory();
    
        for (int i = 0; i < objects.length; i++)
        {
            objects[i] = new Object();
        }
    
        final long memory1 = runtime.totalMemory() - runtime.freeMemory();
    
        final long memory = memory1 - memory0;
    
        System.out.printf(
            "%s %s\n",
            System.getProperty("java.vm.name"),
            System.getProperty("java.vm.version"));
    
        System.out.printf("%d %d %.1f\n", n, memory, 1.0 * memory / n);
    }
    

    Java HotSpot(TM) 服务器虚拟机 14.3-b01 1000000 8000336 8.0

    【讨论】:

      【解决方案3】:

      让我们说清楚。当然,对您的对象的引用会占用空间。但是您的对象还将为其“this”指针占用空间(即,您可以区分不同的实例)以及任何超类的字段 - 例如对象 - 最后是堆内部数据结构的开销。

      【讨论】:

      • 对象不需要存储“this”指针(因为代码必须已经有可用的this指针才能访问对象......)
      • 是的。他们需要一个指向 C++ 中称为虚方法表的指针。
      【解决方案4】:

      是的,确实如此,因为至少“空”对象也有指向其类型信息的指针。

      【讨论】:

      • 你是对的。这就是为什么我提到除了对象引用/指针之外的问题。那么除了参考/点之外,它还有内存占用吗?
      • 取决于 JVM 实现。可能会有某种针对每个对象的同步机制,或者垃圾收集器的标记标志。我的最佳猜测是在 32 位机器上每个对象的开销至少为 8 字节。
      • 对于 32 位 JVM,开销最多可达 16 个字节……取决于 JVM 实现细节。开销包括原始对象大小、到类的链接、原始互斥体的表示、身份哈希码的表示、最终确定的标志等等。
      • @Stephen:默认的身份哈希码是从this派生出来的,原始对象的大小是从类型知道的,终结处理保持在对象之外(即找出一个对象是否被如果您不是内存管理器,finalized 相对昂贵)。
      • 身份哈希图无法由此计算,否则会在发生 GC 并压缩堆时发生变化
      猜你喜欢
      • 2012-12-15
      • 2012-10-24
      • 2021-10-17
      • 2013-01-30
      • 2011-06-18
      • 2017-12-22
      • 1970-01-01
      • 2017-12-04
      • 1970-01-01
      相关资源
      最近更新 更多