Java:内部类的大小

时间:2012-08-30 08:47:25

标签: java inner-classes

我有这堂课:

public class Stack {

   private class Node {
       String item;
       Node next;
   }
   // some other methods here

}

在我的书中,作者说每个堆栈节点的大小是40个字节,包括:

16 bytes (object overhead)
8 bytes (inner class extra overhead)
8 bytes (references to string)
8 bytes (references to node)
----------------------------------------------
40 bytes per stack node

据我所知,最后两件事指的是String和Node的引用大小。但我不知道object overheadinner class extra overhead对应的内容。你能解释一下吗?

8 个答案:

答案 0 :(得分:6)

  

对象开销

每个对象都有一个标题,通常为8-12个字节。每个对象也是8字节对齐的,你说它的长度约为16个字节。

  

内部类额外开销

由于您的内部类不是静态的,因此它具有对外部类的引用。

如果这是一个匿名内部类,您可能拥有任意数量的最终变量的副本(在匿名类代码中使用的任何变量)

  

8个字节(内部类额外开销)   8个字节(对字符串的引用)   8个字节(对节点的引用)

大多数JVM使用32位引用,因此大小为4个字节。即使是堆高达32 GB的64位JVM也可以使用32位引用。

答案 1 :(得分:3)

首先:您引用的所有具体数字都是非常依赖于实现,并且根据您使用的JVM可能会有很大不同。

但是,大多数JVM都具有类似的值(例如,大多数JVM使用对象头)。

对象标头包含JVM需要跟踪对象的“簿记”信息。例如,它通常包含指示对象的确切类型的东西。

你所谓的“内部类额外开销”可能是指非静态内部类的每个实例都“绑定”到外部类的实例。您可以将其视为隐含字段,如下所示:private final Stack Stack_this。实际上,您可以通过在Stack.this的代码中引用Node来实际使用该值。该implcit字段将占用与普通引用变量相同的内存量(通常为4或8个字节,具体取决于您的体系结构/ JVM)。

答案 2 :(得分:2)

在这里你可以找到答案: What is the memory overhead of an object in Java?

这里有一个更详细的答案:

Java中的对象内存使用情况: http://www.javamex.com/tutorials/memory/object_memory_usage.shtml

  

Java堆上的对象实例不仅占用了实际字段的内存。不可避免地,它们还需要一些“管家”信息,例如记录对象的类,ID和状态标志,例如对象当前是否可访问,当前是否同步锁定等。

答案 3 :(得分:2)

内部类的实例将根据正常规则进行垃圾收集(即,不再引用它们时)。但是,内部类的每个实例都包含对其外部类的父实例的隐藏引用。这意味着如果对内部类的实例有任何实时引用,它们将阻止外部类的关联实例被垃圾回收。但它只适用于那个方向,而不是相反。

答案 4 :(得分:1)

内部类具有对外部类的隐式引用,就好像它具有在构造函数中初始化的Stack outer对象一样。该引用消耗了额外的8个字节,它允许您在内部类中使用Stack.this。这是一个示例代码段:

public class Stack {
    String item;   // intentionally named the same as the one in the inner class

    private class Node {
        String item; // hides the field in the outer class!
        Node next;

        void doSomething() {
            this.item = null;
            Stack.this.item = null; // << note the reference to the outer instance
        }
    }
}

请注意,static内部类不会产生这种开销,因为它没有指向外部对象的指针。

答案 5 :(得分:1)

  

任何特定对象的确切大小未在具体定义中   任何Java平台规范

     

未定义与对象关联的开销量,但为8   字节是典型的。

Refer here for more info

答案 6 :(得分:1)

首先,对象引用的值假定为64位JVM,在32位JVM上,引用使用4个字节。

对象开销是对象的标头,它包含有关JVM使用的对象的信息,通常为16个字节。

内部类是由于内部类保存对包含对象(Stack实例)的引用这一事实。

答案 7 :(得分:0)

我仍然不明白“每个堆栈节点40个字节”是什么意思。您知道当我创建新的Node实例时,我不会创建新的Stack实例。在创建新的Node实例时,如何将16bytes(对象开销)考虑在内?我也在跟踪算法,我在这里被迷惑了。

相关问题