14

私はこのクラスを持っています:

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

最後の 2 つのことは、String と Node への参照のサイズを参照していることを理解しています。object overheadしかし、 andが何にinner class extra overhead対応するのかわかりません。説明していただけますか?

4

8 に答える 8

6

オブジェクトのオーバーヘッド

すべてのオブジェクトには、通常 8 ~ 12 バイトの長さのヘッダーがあります。各オブジェクトも 8 バイトにアラインされており、単純な見積もりでは、約 16 バイトの長さと言われています。

内部クラスの余分なオーバーヘッド

内部クラスは静的ではないため、外部クラスへの参照があります。

これが匿名の内部クラスである場合、任意の数の最終変数 (匿名クラス コードで使用されるもの) のコピーを持つ可能性があります。

8 バイト (内部クラスの余分なオーバーヘッド) 8 バイト (文字列への参照) 8 バイト (ノードへの参照)

ほとんどの JVM は 32 ビット参照を使用するため、サイズは 4 バイトになります。最大 32 GB のヒープを持つ 64 ビット JVM でも、32 ビット参照を使用できます。

于 2012-08-30T08:54:29.613 に答える
3

まず第一に、引用するすべての具体的な数値は実装に大きく依存し、使用する JVM によって大きく異なる可能性があります。

ただし、ほとんどの JVM は同様の値を持ちます (たとえば、ほとんどの JVM はオブジェクト ヘッダーを使用します)。

オブジェクト ヘッダーには、JVM がオブジェクトを追跡するために必要な「簿記」情報が含まれています。たとえば、通常、オブジェクトの正確なタイプを示す何かが含まれます。

「内部クラスの余分なオーバーヘッド」と呼ばれるものは、おそらく非静的内部クラスのすべてのインスタンスが外部クラスのインスタンスに「バインド」されているという事実を指しています。次のような暗黙的なフィールドと考えることができますprivate final Stack Stack_thisStack.this実際、のコード内でを参照することで、実際にその値を使用できますNode。その暗黙フィールドは、通常の参照変数と同じ量のメモリを使用します (アーキテクチャ/JVM に応じて、通常は 4 または 8 バイトです)。

于 2012-08-30T08:54:36.410 に答える
2

ここで答えを見つけることができます: Java のオブジェクトのメモリ オーバーヘッドとは何ですか?

そして、ここでより詳細な答え:

Java でのオブジェクトのメモリ使用量: http://www.javamex.com/tutorials/memory/object_memory_usage.shtml

Java ヒープ上のオブジェクトのインスタンスは、実際のフィールドのためにメモリを消費するだけではありません。必然的に、オブジェクトのクラス、ID、およびオブジェクトが現在到達可能かどうか、現在同期ロックされているかどうかなどのステータスフラグの記録など、いくつかの「ハウスキーピング」情報も必要になります。

于 2012-08-30T08:52:26.367 に答える
2

Stack outer内部クラスには、コンストラクターで初期化されるオブジェクトがあるかのように、外部クラスへの暗黙的な参照があります。Stack.thisその参照は、余分な 8 バイトを消費するものであり、内部クラスで使用できるものです。サンプル スニペットを次に示します。

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内部クラスには外部オブジェクトへのポインターがないため、そのオーバーヘッドは発生しないことに注意してください。

于 2012-08-30T08:53:53.150 に答える
2

内部クラスのインスタンスは、通常の規則に従って (つまり、参照されなくなったときに) ガベージ コレクションされます。ただし、内部クラスの各インスタンスには、外部クラスの親インスタンスへの隠し参照が含まれています。これは、内部クラスのインスタンスへのライブ参照がある場合、関連する外部クラスのインスタンスがガベージ コレクションされるのを防ぐことを意味します。しかし、それはその方向にのみ機能し、その逆には機能しません。

于 2016-12-08T16:42:41.337 に答える
1

特定のオブジェクトの正確なサイズは、どの Java プラットフォーム仕様でも明確に定義されていません。

オブジェクトに関連するオーバーヘッドの量は定義されていませんが、8 バイトが一般的です。

詳細については、こちらを参照してください

于 2012-08-30T08:53:55.790 に答える
1

まず、オブジェクト参照の値は 64 ビット JVM を想定しています。32 ビット JVM では、参照は 4 バイトを使用します。

オブジェクト オーバーヘッドは、オブジェクトに関する情報を含むオブジェクトのヘッダーであり、JVM によって使用され、通常は 16 バイトです。

内部クラスのオーバーヘッドは、内部クラスがそれを含むオブジェクト (Stack インスタンス) への参照を保持しているためです。

于 2012-08-30T08:53:59.910 に答える
0

「スタックノードあたり40バイト」の意味がまだわかりません。新しいノードインスタンスを作成するとき、新しいスタックインスタンスは作成しません。新しいノードインスタンスを作成するときに、16バイト(オブジェクトオーバーヘッド)をどのように考慮することができますか?私もアルゴリズムに従っていて、ここで混乱しました。

于 2013-02-19T03:18:31.800 に答える