blog

JVMシリーズ:メモリフットプリントのクラスサイズの文字列、配列、コレクション

記事では、単純にクラスのメモリ占有の文字列、配列、およびコレクションを分析するJOLツールの使用は、ここで再び、より詳細な分析と導入を行うには、我々は後でOOMの問題に遭遇することを願っていますときに...

Dec 16, 2020 · 4 min. read
シェア

はじめに

記事では、単純にメモリ使用量の文字列、配列、およびコレクションを分析するためにJOLツールの使用は、ここでより詳細な分析と導入を行うには、私はあなたが後でOOMの問題に遭遇することを願っていますときにもはや頭痛と涙が、章に従うことができる、それを開始します。

配列

まずJOLのコードと出力を見てみましょう:

//byte array
log.info("{}",ClassLayout.parseInstance("www.flydean.com".getBytes()).toPrintable());

出力結果:

INFO com.flydean.CollectionSize - [B object internals:
 OFFSET SIZE TYPE DESCRIPTION VALUE
 0 4 (object header)  00) (1)
 4 4 (object header)  00) (0)
 8 4 (object header)  00) ( 4 (object header) 0f  (000) ( byte [B.<elements> N/A
 31 1 (loss due to the next object alignment)
Instance size: 32 bytes
Space losses: 0 bytes internal + 1 bytes external = 1 bytes total

この記事の結論は、COOPの圧縮オブジェクト・ポインタ技術をオンにして64ビットJVMを実行したことから導き出されたものであることに注意してください。

配列オブジェクトのオブジェクトヘッダのサイズが16バイト、配列内部のコンテンツの長さが15バイト、そして補数が1ビットであることがわかります。最終的に得られるサイズは32バイトです。

同様に、100個のオブジェクトの配列を計算すると、次のような結論になります:

配列に格納されているものが基本型でない場合、実際に格納されているのはそのオブジェクトの実行へのポインターで、サイズは4バイトです。

String

文字列は非常に特殊なオブジェクトで、一番下にバイト配列として格納されます。

JDK9では、Stringの基本的な記憶構造はchar[]であり、charは2バイトの記憶単位を取ることに注意してください。

ほとんどのStringはLatin-1文字エンコーディングで表現されるため、1バイトで済みます。

そのため、JDK9以降、文字列の基礎となるストレージはbyte[]になりました。

今回もJOLで分析:

//String
log.info("{}",ClassLayout.parseInstance("www.flydean.com").toPrintable());

出力結果:

INFO com.flydean.CollectionSize - java.lang.String object internals:
 OFFSET SIZE TYPE DESCRIPTION VALUE
 0 4 (object header)  00) (5)
 4 4 (object header)  00) (0)
 8 4 (object header)  00) ( 4 byte[] String.value [, 2, , , , 1,  int String.hash 0
 20 1 byte String.coder 0
 21 1 boolean String.hashIsZero false
 22 2 (loss due to the next object alignment)
Instance size: 24 bytes
Space losses: 0 bytes internal + 2 bytes external = 2 bytes total

Stringのオブジェクト・ヘッダが12バイトであることがわかり、次にバイト配列への4バイトのポインタを追加します。ハッシュ、コーダー、hasIsZero属性を追加すると、最終的なサイズは24バイトになります。

ここではJDK14のStringバージョンを使っていますが、バージョンによって異なるかもしれません。

もちろん、これはこのStringオブジェクトのサイズであって、基礎となる配列のサイズではありません。

を使用して、String オブジェクトの真のサイズを計算します:

文字列オブジェクトのサイズ + バイト配列のサイズ = 24 + 32 = 56 バイト。

ArrayList

非常に単純なArrayListを構築します:

//Array List
log.info("{}",ClassLayout.parseInstance(new ArrayList()).toPrintable());

出力結果:

INFO com.flydean.CollectionSize - java.util.ArrayList object internals:
 OFFSET SIZE TYPE DESCRIPTION VALUE
 0 4 (object header)  00) (5)
 4 4 (object header)  00) (0)
 8 4 (object header)  00) ( 4 int AbstractList.modCount 0
 16 4 int ArrayList.size 0
 20 4 java.lang.Object[] ArrayList.elementData []
Instance size: 24 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

これを視覚化するために図を描いてください:

ここでmodCountとsizeの初期値はどちらも0です。

HashMap

記事の長さの関係で、ここではコードを列挙せず、写真だけをアップします:

HashSet

LinkedList

treeMap

もっと複雑なTreeMapを見てみましょう:

まとめ

この記事では、メモリ内のコレクション・オブジェクト、配列、文字列の使い方を図解します。

もし興味があれば、下に計算結果を書いて返信してください。

この記事を書いた人: Flydean procedure those things

この記事へのリンク

出典:フライディーンブログ

Read next

テクニカルリーダーへの道:開発者からチームリーダーへの移行方法

ソフトウェア開発があなたのキャリアの目標の一部に過ぎないのであれば、将来テクニカル・リーダーになるにはどうしたらいいかという疑問は、真剣に考え、学ぶべきことかもしれません。テクニカル・リードになるには、チーム・リーダーやテクニカル・マネージャーなど、さまざまな意味があります。例えば、研究開発プロジェクトマネージャーは、チームとプロジェクトに対する説明責任が求められるチームでの役割です。これはまた、チームメンバーがどのように仕事をしているか、ビジネスがどのように成長しているか...にも責任を持つ必要があることを意味します。

Dec 16, 2020 · 7 min read