この記事の例では、Java オブジェクトが占有するメモリ量を計算 (または推定) する方法について説明します。皆さんの参考に共有してください。具体的な分析は次のとおりです。
通常、ヒープ メモリの使用量については「一般的なケース」という文脈で話します。次の 2 つの状況は含まれません。
場合によっては、JVM がオブジェクトをヒープにまったく入れないことがあります。例: 原則として、小さなスレッドローカル オブジェクトはヒープではなくスタック上に存在します。
オブジェクトが占有するメモリの量は、オブジェクトの現在の状態によって異なります。例: オブジェクトの同期ロックが有効かどうか、またはオブジェクトがリサイクルされているかどうか。
まず、ヒープ内の単一のオブジェクトがどのように見えるかを見てみましょう。
ヒープ内の各オブジェクトは 4 つのフィールド (A、B、C、D) で構成されます。以下でそれぞれについて説明します。
A: オブジェクト ヘッダー。わずかなバイトしか占有せず、オブジェクトの現在のステータスに関する情報を表します。
B: 基本型フィールドが占めるスペース (ネイティブ フィールドは int、boolean、short などを指します)
C: 参照型フィールドが占めるスペース (参照型フィールドは他のオブジェクトへの参照を参照し、各参照は 4 バイトを占有します)
D:フィラーが占める空間(フィラーとは何かについては後述)
以下、A、B、C、Dを一つずつ説明していきます
A: オブジェクトヘッダー
メモリ内で各オブジェクトが占める合計スペースには、オブジェクト内で宣言された変数に必要なスペースだけでなく、オブジェクトのヘッダーやフィラーなどの追加情報も含まれます。 「オブジェクト ヘッダー」の機能は、オブジェクトのインスタンス名、ID、インスタンス ステータス (たとえば、現在のインスタンスが「到達可能」かどうか、現在のロックのステータスなど) を記録することです。
現在の JVM バージョン (ホットスポット) では、「オブジェクト ヘッダー」が占めるバイト数は次のとおりです。
8バイトを占める通常のオブジェクト
配列、8 バイト + 通常のオブジェクトの 4 バイト (配列長) を含む 12 バイトを占有します。
B:ベーシックタイプ
boolean と byte は 1 バイトを占め、char と short は 2 バイトを占め、int と float は 4 バイトを占め、long と double は 8 バイトを占めます。
C: 参照型
各参照型は 4 バイトを占有します
D:フィラー
Hotspot では、各オブジェクトが占める合計スペースは 8 の倍数として計算されます。オブジェクトが占める合計スペース (オブジェクト ヘッダー + 宣言された変数) が 8 の倍数未満の場合、自動的に埋められます。ただし、これらの塗りつぶされたスペースを「フィラー」と呼ぶこともできます。具体的な例を見てみましょう。
空のオブジェクト (変数が宣言されていない) は 8 バイトを占有します --> オブジェクト ヘッダーは 8 バイトを占有します
ブール型変数を 1 つだけ宣言するクラスは 16 バイトを消費します --> オブジェクト ヘッダー (8 バイト) + ブール値 (1 バイト) + フィラー (7 バイト)
8 個のブール型変数を宣言するクラスは 16 バイトを消費します --> オブジェクト ヘッダー (8 バイト) + ブール型 (1 バイト) * 8
上記の例は、Java プログラミングについての理解を深めるのに役立ちます。