Javaの単一のオブジェクトのメモリレイアウトた.md

私たちは、Javaが(どのように記事の共有メモリサイズのJavaオブジェクトを取得する共有メモリのサイズを取得するオブジェクトのユーティリティクラスを書いたObjectSizeFetcher後、私たちはJavaでオブジェクトの様々なタイプで、このツールのクラスの外観を使用して、次の)、メモリのサイズを占め

基本タイプ

メモリ消費量の基本的な種類は次のとおりです。

 

基本タイプ メモリサイズ(単位:バイト)
ブーリアン 1
バイト 1
ショート 2
CHAR 2
int型 4
浮く 4
長いです 8
ダブル 8

Javaのメモリサイズのシェアより多くの基本的なタイプが指定され、参照型共有メモリサイズは、決定されていませんし、我々は株式参照型のメモリサイズを見て、私たちはJavaの単一のオブジェクトのメモリレイアウトで始まります

Javaの単一のオブジェクトのメモリレイアウト

オブジェクトヘッダ

Javaでは、各オブジェクトはオブジェクトヘッダが含まれている、オブジェクトヘッダは、データの2種類が含まれていますオブジェクト自身のランタイムデータ及びポインタデータタイプを格納します

  1. ランタイム・データ・オブジェクト自体を格納し、マーク・ワード(32ビットおよび64ビットのオペレーティングシステムと8バイトの長さは4バイトである)は、以下の情報が含まれます。
    1. オブジェクトのhashCode
    2. オブジェクトGC世代年齢
    3. ロックステータスフラグ(軽量、ヘビー級のロックをロック)
    4. スレッドは(軽量、ヘビー級のロックをロック)ロックを保持しています
    5. 関連偏ったロック
  2. タイプポインタ:オブジェクト・クラス・メタデータへのポインタ(32ビットオペレーティングシステム - > 4バイト、64ビットオペレーティングシステム - > 8バイト(圧縮ポインタがオンになっていない)、4バイト(圧縮開放ポインタ))
    • JVMは、オブジェクトクラス(オブジェクト・ポインタに応じて決定されたクラス)のインスタンスであるポインタによって決定されます

したがって、32ビットオペレーティングシステム、Javaオブジェクトにオブジェクトヘッダによって占められるメモリサイズ8字节

64ビットオペレーティングシステムでは:

  • ポインタが圧縮上にない場合、オブジェクトのサイズは、ヘッドであります16字节
  • ポインタの圧縮を有効にした場合、オブジェクトのサイズは、頭であります12字节

JVMパラメータUseCompressedOops圧縮ポインタ機能をオンにするかどうかを制御するためには、デフォルトで有効になって、私たちは、このパラメータを見てください。

どのように我々は、Javaオブジェクトは、最後の占有メモリサイズは、という問題が残されていたのですかnew Point()、オブジェクトがメモリサイズなぜ占め24字节、それを?以下は、Pointコード:

パブリッククラスPoint { 
    プライベートint型のX; // 4字节
    プライベートint型のy; // 4字节

    パブリック静的無効メイン(文字列[] args){ 
        System.out.printlnは(ObjectSizeFetcher.sizeOf(新しいPoint()))。
    } 
}

  このPointクラスは、2つのプロパティを持っているxyされint、その後、サイズが8つのバイトによって占有財産の2つのint型4バイトint型と共有メモリサイズの種類されているので、24 - 8 = 16字节メモリのシェアは何ですか?

 

ポインタは、圧縮をオンにしません。

私たちは、次のコマンドを実行するとする場合:

##は、ポインタ圧縮をオンにしない
Javaの -UseCompressedOops -javaagent:ObjectSizeFetcherAgent-1.0-SNAPSHOT.jarにcom.twq.Point -XX

new Point()オブジェクトのサイズがあります24字节

 

 そこには、ポインタの圧縮がオンされていないので、オブジェクトのサイズは、ヘッドので、この時間は、16字节(:私のコンピュータは、64ビットオペレーティングシステムであることに注意)。これは、24 - 8 = 16字节メモリサイズによって占め対象ヘッドであります

オープンポインタ圧縮

私たちは、次のコマンドを実行するとする場合:

##オープンポインター圧縮
のjava -XX:+ UseCompressedOops -javaagent:ObjectSizeFetcherAgent -1.0-SNAPSHOT.jarにcom.twq.Point

  new Point()オブジェクトのサイズまたは24字节

 

 

ポインタ圧縮をオンにするのでので、この時点でのオブジェクトの頭の大きさです12字节よう24 - 8 = 16字节16字节含むことに加え12字节、オブジェクトヘッダを、ある4字节多く、これは、4字节アライメントパディング(詰め物)です。

アライメントパディング:、ビットアラインメントを充填する必要がない場合、オブジェクトのJVM必要なサイズは、8の整数倍でなければなりません。

ポインタ圧縮を開くとき、オブジェクトヘッダサイズ12字节+ 2サイズ属性型int 8字节= 20字节ので、20それが必要である8の倍数ではない、すなわち、パディング4つのバイトを整列させるために、24字节

Javaの単一のオブジェクトのメモリレイアウトの概要:

  • アライメントパディング+によって占められるメモリのサイズによって占有属性データメモリサイズの最初のインスタンスによって占められる被写体+オブジェクトメモリサイズ:Javaオブジェクトは、単一のメモリサイズが等しく共有します
  • 記憶対象データ・オブジェクト・ヘッダは、ポインタデータタイプ及びデータのそのランタイムタイプを含みます。64ビットオペレーティングシステムでは、有効になっている場合、次にポインタ圧縮は、オブジェクトヘッダサイズによって占められるメモリは12バイトであり、オープン、その後、ポインタ圧縮されていない場合、オブジェクトヘッダサイズによって占有されるメモリは、16バイトであります
  • アライメントパディング:、ビットアラインメントを充填する必要がない場合、オブジェクトのJVM必要なサイズは、8の整数倍でなければなりません。

静的プロパティを変更します

私たちは、Point修正静的変数、次のコードを追加します。

クラスPoint {パブリック
    プライベートint型のX; 
    プライベートint型Y、

    パブリック静的ロングID = 3000L; //追加変性静的変数

    のpublic static無効メイン(文字列[] args){ 
        System.out.printlnは(ObjectSizeFetcher.sizeOf(新しい新しいポイント())); 
    } 
}

  私たちは、次のコマンドを実行するとする場合:

##は、ポインタ圧縮をオンにしない
Javaの-XX:-UseCompressedOops -javaagent:ObjectSizeFetcherAgent-1.0-SNAPSHOT.jarにcom.twq.Point 

##オープンポインター圧縮
のjava -XX:+ UseCompressedOops -javaagent:ObjectSizeFetcherAgent -1.0-SNAPSHOT.jarにしますcom.twq.Point

  次のように得られた結果は以下の通りでした。

 

 

new Point()このオブジェクトは、メモリサイズを占めているか、24字节静的変数はクラスに属することを証明するために、インスタンスに属していない、グローバルデータセグメントに保存され、共通変数はJavaオブジェクトの計算に含まれていたスペースを占めます。

参照型

各32ビットオペレーティングシステム上で参照タイプは4つのバイトを占有します

64ビットオペレーティングシステムでは:

  • ポインター圧縮は8つのバイトを占有し、その後、開きません
  • オープンポインタ圧縮は、次いで、4つのバイトを占め

私たちは、と呼ばれる書き込みRefTypeSizer読み込み、クラスを、:

人{クラス
} 

publicクラスRefTypeSizer { 
    //これは参照型で
    、個人個人

    のパブリック静的な無効メイン(文字列[]引数)はIllegalAccessExceptionが{スロー
        +:のSystem.out.println(「オブジェクト新しいRefTypeSizer()共有メモリサイズを」 ObjectSizeFetcher.sizeOf(新しいRefTypeSizer())+ " バイト"); 
    } 
}

  私たちは、その後、再パッケージ化して、次のコマンドを実行するには:

##はポインタ圧縮をオンにしない
のjava -XX:-UseCompressedOops -javaagent:ObjectSizeFetcherAgent- 1.0-SNAPSHOT.jarにcom.twq.RefTypeSizer

  得られたオブジェクトのnew RefTypeSizer()共有メモリ・サイズ24字节

 

 

今回はそこには、ポインタ圧縮がオンになっていないので、オブジェクトの頭のサイズなので16字节、型参照用Person personメモリの割合8字节、そのサイズを追加します16 + 8 = 24字节

それでは、圧縮関数ポインタ、次のコマンドを開いてみましょう:

##オープンポインター圧縮
のjava -XX:+ UseCompressedOops -javaagent:ObjectSizeFetcherAgent -1.0-SNAPSHOT.jarにcom.twq.RefTypeSizer

  

得られたオブジェクトのnew RefTypeSizer()共有メモリ・サイズ16字节

 

 この時間は、ポインタの圧縮、そのオブジェクトの頭のサイズになっているので12字节、型参照用Person personメモリの割合を4字节、そのサイズを追加12 + 4 = 16字节

配列

64ビットオペレーティングシステムでは、オブジェクトヘッダ配列オブジェクトは、24バイトを占有し、圧縮を有効にするポインタは、複数のアレイがアレイの長さを格納するために追加のスペースを必要とするためである理由を占める従来のオブジェクトよりもメモリの16バイトを占有します。

私たちは、次のように計算された配列のコード長を見て:

{クラスArraySizer公共
    のpublic static無効メイン(文字列[] args){ 
        するSystem.out.println( "新しい新しい整数[0]共有メモリサイズ:" + ObjectSizeFetcher.sizeOf(新しい整数[ 0])+ " バイト" ); 
        のSystem.out.println( "新しい新しい整数共有メモリサイズ[1]:" + ObjectSizeFetcher.sizeOf(新しい整数[ 1])+ " バイト")
        のSystem.out.println(「新しい新しい整数[2 】共有メモリサイズは"+ ObjectSizeFetcher.sizeOf(新しい整数[ 2])+" バイト")
        のSystem.out.println("新しい新しい整数[3]共有メモリサイズ:「+ ObjectSizeFetcher.sizeOf(。新しい整数[3])+ "バイト")
        のSystem.out.println( "新しい新しい整数共有メモリのサイズである[4]:" + ObjectSizeFetcher.sizeOf(新しい整数[ 4])+ " バイト")。
    } 
}

  私たちは、その後、再パッケージ化して、次のコマンドを実行するには:

##はポインタ圧縮をオンにしない
のjava -XX:-UseCompressedOops -javaagent:ObjectSizeFetcherAgent- 1.0-SNAPSHOT.jarにcom.twq.ArraySizer

  次のように得られた結果は以下のとおりです。

 

 

 我々が見ることができるnew Integer[0]サイズを24字节配列の長さがゼロであるため、サイズがアレイ配列オブジェクトの頭の大きさであるが、またように、そこにはポインタの圧縮がオンされていないので、配列オブジェクトの頭のサイズがあるため24字节、他の長さは、アレイ共有メモリを説明します。

 

 

  • new Integer[1]サイズ:オブジェクトヘッダ24バイト+ 1バイト= 8参照型サイズ32のバイト
  • new Integer[2]サイズ:オブジェクトヘッダ24バイト+ 2バイトの参照型サイズ16バイト40 =
  • new Integer[3]サイズ:オブジェクトヘッダ24バイト+ 3バイトの参照型サイズ24バイト48 =
  • new Integer[4]サイズ:オブジェクトヘッダ24バイト+ 4バイトの参照型サイズ32バイト56 =
  • new Integer[]{2, 3, 4, 5}ビットサイズ:new Integer[4]56バイトのサイズ+ 4 *(整数Integerオブジェクトヘッダ+サイズ属性タイプINT + 4バイト4バイトアライメントパディングで16バイト)= 152のバイト

その後、我々は、ポインタ圧縮を回し、次のコマンドを実行します。

##オープンポインター圧縮
のjava -XX:+ UseCompressedOops -javaagent:ObjectSizeFetcherAgent -1.0-SNAPSHOT.jarにcom.twq.ArraySizer

  次のように得られた結果は以下のとおりです。

 

 

我々が見ることができるnew Integer[0]サイズを16字节配列の長さがゼロであるため、サイズがアレイ配列オブジェクトの頭の大きさになるように、だけでなく、ポインタ圧縮を開放するので、配列オブジェクトヘッドサイズので、16字节アレイ共有メモリを説明するために、他の長さ:

  • new Integer[1]サイズ:+ 4基準配向型サイズオブジェクトヘッダ16バイト+ 1バイト4バイト= 24バイトが追加
  • new Integer[2]サイズ:8バイトのオブジェクトヘッダ16バイト+ 2バイトの基準文字サイズ= 24
  • new Integer[3]サイズ:オブジェクト参照型サイズの最初の16のバイトは、+ 3 + 12バイト= 4バイトアライメントが32バイトを追加しました
  • new Integer[4]サイズ:オブジェクトヘッダ16バイト+ 4バイトの参照型サイズ16バイト32 =
  • new Integer[]{2, 3, 4, 5}ビットサイズ:new Integer[4]32バイトのサイズ+ 4 *(Integerオブジェクトヘッダバイト12 + 4バイトの整数型のint属性サイズ)が96バイト=

概要

Javaの単一のオブジェクトのメモリレイアウトの概要:

  • アライメントパディング+によって占められるメモリのサイズによって占有属性データメモリサイズの最初のインスタンスによって占められる被写体+オブジェクトメモリサイズ:Javaオブジェクトは、単一のメモリサイズが等しく共有します
  • 記憶対象データ・オブジェクト・ヘッダは、ポインタデータタイプ及びデータのそのランタイムタイプを含みます。64ビットオペレーティングシステムでは、有効になっている場合、次にポインタ圧縮は、オブジェクトヘッダサイズによって占められるメモリは12バイトであり、オープン、その後、ポインタ圧縮されていない場合、オブジェクトヘッダサイズによって占有されるメモリは、16バイトであります
  • アライメントパディング:、ビットアラインメントを充填する必要がない場合、オブジェクトのJVM必要なサイズは、8の整数倍でなければなりません。
  • グローバル・データ・セグメントに格納されたインスタンスに属さない、クラスに属する静的変数は、共通の変数は、オブジェクトのJavaによって占められる空間の計算に含まれていました
  • 各32ビットオペレーティングシステム上で参照タイプは、64ビットオペレーティングシステムでは4つのバイトを占有します。
    • ポインター圧縮は8つのバイトを占有し、その後、開きません
    • オープンポインタ圧縮は、次いで、4つのバイトを占め
  • 64ビットオペレーティングシステムでは、オブジェクトヘッダ配列オブジェクトは、24バイトを占有し、圧縮を有効にするポインタは、複数のアレイがアレイの長さを格納するために追加のスペースを必要とするためである理由を占める従来のオブジェクトよりもメモリの16バイトを占有します。

上記1つの単純なJavaオブジェクトが計算で複雑なJavaのための占有メモリのサイズは、共有メモリサイズメーターオブジェクト

おすすめ

転載: www.cnblogs.com/tesla-turing/p/11487785.html