*

Java8のHotSpotVMからPermanent領域が消えた理由とその影響

公開日: : 最終更新日:2014/05/18 HotSpotVM, Java, Java8, ヒープ管理, 技術

今回も前回の記事につづき、Java8による変更点で未だあまり紹介されていないポイントを記事にしようと思う。

今回はJava8のHotSpotVMの話。Java8ではJEP122が取り込まれ、VMのメモリモデルが変更された。JEP122のタイトル「Remove the Permanent Generation」から想像できるとおり、Java8のHotSpotVMからは従来のPermanent領域が無くなった。

なぜ、こういった変更が行われたのだろうか?また、元々Permanent領域に格納されていた情報は何処にいってしまったのか?JVM付属のツールにどういった影響があるのか? 今回の記事ではこの点をまとめていこうと思う。

なお、HotSpotVMのメモリモデルについて詳しくない方は、先にこちらの項番(「補足 – HotSpotVMのメモリ構造概説)を読んでいただくとスムーズに読み進められるだろう。

それでは始めよう。

Java7版HotSpotとJava8版HotSpotを比較

メモリモデルを比較

先ずはJava7版とJava8版のHotSpotVMのメモリモデルを比較してみよう。

java7-8HotSpotVM

Permanent領域がMetaspaceと呼ばれる領域に変更されている。また、これまでのPermanent領域はヒープ領域の一種として扱われていたが、MetaspaceはNativeメモリとして扱われている。

Permanent領域とMetaspace領域を比較

では、従来のPermanent領域とMetaspace領域を様々な要素から比較してみよう。

比較項目Permanent領域Metaspace領域
1.領域の取り扱いヒープの一種ネイティブメモリ
2.デフォルトの最大容量環境依存だが60〜80MByte程度無尽蔵
3.サイズ調整用Javaパラメータ-XX:PermSize
-XX:MaxPermSize
-XX:MetaspaceSize
-XX:MaxMetaspaceSize
4.格納する情報クラス/メソッド
static変数
定数や文字列のintern表現(〜Java6まで)
クラス/メソッド
5.ガーベッジコレクトの有無有(FullGC対象)有(FullGC対象)

異なるポイントを順番に解説していく。

1.メモリの扱いの違い〜ヒープからNativeメモリへ〜

MetaspaceはヒープではなくNativeメモリとして取り扱われる。
ヒープ領域はJVMによって管理された領域であるのに対して、NativeメモリはOSが管理する直のメモリ領域の事を指す。従来のNativeメモリではJNI等を利用した場合のネイティブコードが配置されたり、JVM自体が利用する領域(Cヒープ)があった。
MetaspaceにNativeメモリを利用することで、領域確保の上限を意識する必要がなくなる。領域の上限については次項で解説する。

2.デフォルトの最大容量の違い〜Metaspaceは無尽蔵?〜

Permanent領域とMetaspace領域は領域の最大サイズのデフォルト値が大きく異なる。それぞれの最大値を比較してみよう。

$ uname -mrs
Linux 2.6.32-431.el6.x86_64 x86_64

$ #Java7HotSpotVMのPermanentサイズ初期値と最大値
$ /usr/java/jdk1.7.0_55/bin/java -XX:+PrintFlagsFinal -version -server | grep "PermSize "
    uintx MaxPermSize                               = 85983232        {pd product}        
    uintx PermSize                                  = 21757952        {pd product}        
java version "1.7.0_55"
Java(TM) SE Runtime Environment (build 1.7.0_55-b13)
Java HotSpot(TM) 64-Bit Server VM (build 24.55-b03, mixed mode)

$ #Java8HotSpotVMのMetaspaceサイズ初期値と最大値
$ /usr/java/jdk1.8.0_05/bin/java -XX:+PrintFlagsFinal -version -server | egrep " (Max)?MetaspaceSize"
    uintx MaxMetaspaceSize                          = 18446744073709547520{product}
    uintx MetaspaceSize                             = 21807104        {pd product}
java version "1.8.0_05"
Java(TM) SE Runtime Environment (build 1.8.0_05-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.5-b02, mixed mode)

私の環境ではJava7のMaxPermSizeは85,983,232Byte(82MByte)であるのに対し、Java8のMaxMetaspaceサイズは18,446,744,073,709,547,520Byteというとんでもない数値になっている。この数値は16エクサバイトだそうだ。

exbyte

この16エクサバイトは、64bitプロセッサが取り扱えるメモリの上限値だ。
MetaspaceはNativeメモリとして扱われる(JVMにサイズを強制されない)ため、プロセッサが利用できるメモリ資源を最大限活用できるのだろう。この領域を制限するためには、次節で解説するパラメータを利用する。

3.サイズ調整用Javaパラメータの違い

従来、Permanent領域のサイズ指定は「-XX:PermSize」と「-XX:MaxPermSize」を利用してきた。
これらのパラメータは「-XX:MetaspaceSize」と「-XX:MaxMetaspaceSize」に置き換わると同時に、PermSizeとMaxPermSizeオプションは非推奨となり、Java8において利用した場合は警告メッセージが表示される。

$ /usr/java/jdk1.8.0_05/bin/java -version
java version "1.8.0_05"
Java(TM) SE Runtime Environment (build 1.8.0_05-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.5-b02, mixed mode)

$ #Java8でPermanent領域に関するパラメタを利用すると警告表示され、設定値は無視される
$ /usr/java/jdk1.8.0_05/bin/java -XX:PermSize=128M -XX:MaxPermSize=128M HelloWorld
Java HotSpot(TM) 64-Bit Server VM warning: ignoring option PermSize=128M; support was removed in 8.0
Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=128M; support was removed in 8.0

$ #Permanent領域のパラメタはMetaspace用のパラメタに置き換えるべき
$ /usr/java/jdk1.8.0_05/bin/java -XX:MetaspaceSize=128M -XX:MaxMetaspaceSize=128M HelloWorld

このようにJava8からはPermSizeとMaxPermSizeオプションが削除され、無視されていることが分かる。(ただし、このような警告メッセージが表示されパラメータが無視されるだけであって、実行は可能だ)
従来利用していたPermSizeとMaxPermSizeはMetaspaceSizeとMaxMetaspaceSizeに置き換える必要が有る。

3.の補足 – MaxMetaspaceパラメータは設定すべきか?

本番環境では基本的に従来のMaxPermanentSizeと同様に設定すべきだろう。
特に、独自のクラスローダを実装しており、且つこれらのクラスローダにメモリリークの疑いがある場合、パラメータ「-XX:MaxMetaspaceSize」を指定するべきだ。

Metaspaceは魔法の領域ではない。従来発生していたメモリリークが解消される訳ではないのだ。クラスローディングのメモリリークが疑われる環境では、従来のPermanent領域の上限値が、ある種の”ストッパー”の役割を果たしてきた。
Metaspaceではこのストッパーが存在しないため、無尽蔵にリークされた領域が広がっていく恐れがある。こういった環境では上限値(-XX:MaxMetaspaceSize)を明示的に設定すべきだろう。

とはいうものの、個々の開発環境では、当領域を意識する頻度は下がると思われる。
Metaspace内に格納される情報はクラスおよびメソッドのメタ情報であり、結局の所、これらは”アプリケーションを動かすために必須な情報”である。
上限値を設定したとしても、領域が不足するようであれば、領域を拡張せざるを得ない。Metaspaceは自動的に伸張されるため、個々の開発者の環境では特段注意を払って設定する必要は無いだろう。

4.格納する情報の違い

従来のPermanent領域はクラスやメソッドのメタ情報の他、staticな変数や定数等も領域内に格納していた。ところがMetaspaceではクラス、メソッドの情報のみ保持し、その他の情報はJavaヒープ上の保持に変更された。

この変更の理由に関する公式なドキュメントは見当たらなかったが、後述するJRockitとの統合が原因となっていると思われる。
元々、JRockitVMではクラスやメソッドに関する情報はNativeメモリ上で保持していた。Nativeメモリ上に保持する情報をJRockitに合わせ、JRockitVMとの統合をスムーズに実施する方針があると思われる。

5.ガーベッジコレクションの違い

ガーベッジコレクションに変更点は無い。MetaspaceがNativeメモリ上に存在していたとしてもフルガーベッジ時のコレクション対象となる。

 

Permanent領域は何故無くなったのか?

HotSpotVMとJRockitVMの統合に向けた動きの一環だ。
OracleはBEA、およびSunの買収によって、HotSpotとJRockitという2つのVMを手中に収めた。OracleはHotSpotVMをベースとしてJRockitを統合する活動を進めている。この活動の一環としてJRockit側に存在しなかったPermanent領域をHotSpotVMから削除したという訳だ。
なお、HotSpotとJRockitを統合したVMの事を「HotRockit」という。HotRockitについてはこの資料が参考になるだろう。

 

JDK付属ツールへの影響

Permanent領域の削除とMetaspace領域の追加によって、JDK付属ツールにどういった影響が発生したのだろうか。 個々のツール別に変更点を見ていこう。

jstat

jstatでは、Permanent領域に関する表記が変更されている。

$ #Java7でのjstat表示
$ /usr/java/jdk1.7.0_55/bin/java Test > /dev/null &
[1] 9257

$ /usr/java/jdk1.7.0_55/bin/jstat -gc 9257 1s
 S0C    S1C    S0U    S1U      EC       EU        OC         OU       PC     PU    YGC     YGCT    FGC    FGCT     GCT   
320.0  320.0   0.0    0.0    2752.0   1542.9    6720.0     221.1    21248.0 2385.3    385    0.192   0      0.000    0.192
320.0  320.0   0.0    0.0    2752.0   165.4     6720.0     221.1    21248.0 2385.3    397    0.198   0      0.000    0.198

$ #Java8でのjstat表示
$ /usr/java/jdk1.8.0_05/bin/java Test > /dev/null &
[2] 10115

/usr/java/jdk1.8.0_05/bin/jstat -gc 10115 1s
 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT   
448.0  448.0   0.0    0.0    3648.0   1679.4    8960.0     253.7    4864.0 2408.8 512.0  258.6    1272    0.499   0      0.000    0.499
448.0  448.0   0.0    0.0    3648.0   2628.6    8960.0     253.7    4864.0 2408.8 512.0  258.6    1277    0.501   0      0.000    0.501

変更された項目

PCとPUがMCとMUに変更された。MCとMUの意味は従来のPC、PUと同じで、MCがMetaspaceのキャパシティであり、MUがMetaspaceの使用量を表している。
ちなみに、Java7版HotSpotVMで実行中のJavaコードに対してJava8版のjstatを実行するとMC欄とMU欄は空欄となる。(分析できない)

追加された項目

CCSCとCCSUが追加されている。これは「Compressed Class Space Capacity」と「Compressed Class Space Used」の略で、「Compressed Class」領域のキャパシティと利用量を表している。「Compressed Class」領域とはCompressedOopsのための領域であり、64bitOS上で32GByte未満のヒープを取り扱う際に、VMを高速化するために利用される領域のことだ。(Metaspaceとは別の領域である)

64bitOSの場合、利用できるメモリ範囲が非常に広大となるため、オブジェクト上に保持しているポインタのビット数が32bitOSと比べ大きくなる。実際問題として、この64bit用のポインタを有効に使えるほどのヒープ容量を利用することは希だ。そのため、オブジェクト上に持つポインタのbit数を減らし、オーバーヘッドを減らすことでVM動作を高速化するための仕組みがCompressedOopsだ。この仕組みに利用される領域が「Compressed Class」領域である。
この「Compressed Class」領域の容量はパラメータ「XX:CompressedClassSpaceSize」で指定できる。

jmap

jmapはヒープやNativeメモリ情報を調べることができるJDK付属ツールだ。
-heapオプションを設定し実行すること各種メモリの割り当て状況やヒープの利用状況を確認できる。
従来のPermanent領域はヒープ領域の一つとして取り扱われていたため、使用状況が取得できたが、Metaspace領域はNativeメモリ上に存在するため、利用状況の取得はできなくなった。 これは、Native領域を利用することによるデメリットの一つと言えるだろう。(従来取得できる情報が取得できなくなった)

$ /usr/java/jdk1.8.0_05/bin/java Test > /dev/null &
[1] 10560

$ #Java8環境でのjmap実行
$ /usr/java/jdk1.8.0_05/bin/jmap -heap 10560
Attaching to process ID 10560, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.5-b02

using thread-local object allocation.
Mark Sweep Compact GC

Heap Configuration:
   MinHeapFreeRatio         = 40
   MaxHeapFreeRatio         = 70
   MaxHeapSize              = 165675008 (158.0MB)
   NewSize                  = 1310720 (1.25MB)
   MaxNewSize               = 55181312 (52.625MB)
   OldSize                  = 9175040 (8.75MB)
   NewRatio                 = 2
   SurvivorRatio            = 8
   MetaspaceSize            = 21807104 (20.796875MB)
   CompressedClassSpaceSize = 1073741824 (1024.0MB)
   MaxMetaspaceSize         = 17592186044415 MB
   G1HeapRegionSize         = 0 (0.0MB)

Heap Usage:
New Generation (Eden + 1 Survivor Space):
   capacity = 4194304 (4.0MB)
   used     = 3097352 (2.9538650512695312MB)
   free     = 1096952 (1.0461349487304688MB)
   73.84662628173828% used
Eden Space:
   capacity = 3735552 (3.5625MB)
   used     = 3097352 (2.9538650512695312MB)
   free     = 638200 (0.6086349487304688MB)
   82.91551021107456% used
From Space:
   capacity = 458752 (0.4375MB)
   used     = 0 (0.0MB)
   free     = 458752 (0.4375MB)
   0.0% used
To Space:
   capacity = 458752 (0.4375MB)
   used     = 0 (0.0MB)
   free     = 458752 (0.4375MB)
   0.0% used
tenured generation:
   capacity = 9175040 (8.75MB)
   used     = 259800 (0.24776458740234375MB)
   free     = 8915240 (8.502235412597656MB)
   2.8315952845982144% used

753 interned Strings occupying 49816 bytes.

$ #Java7版のjmapでは54行目当たりにPermanent領域の利用状況が表示されていたが、Java8から削除された

Java7までのjmapコマンドでは、Heap Usage欄にPermanent領域の表記が行われていた。が、Nativeメモリに移動したことによって、この情報は表示されなくなった。 Java8でのMetaspaceに関する表記はHeap Configuration欄のMetasupace領域の表記のみとなっている。

jinfo

jinfoコマンドは実行中のVM情報を調べたり、動的にオプションを設定できるコマンドだ。
このコマンドからもMetaspace領域に関する設定を参照できるようになったが、Permanent領域の情報は取得不可に変更されている。

$ #Java8環境でのjinfoコマンドの実行
$ /usr/java/jdk1.8.0_05/bin/java Test > /dev/null &
[1] 10780

$ /usr/java/jdk1.8.0_05/bin/jinfo -flag MetaspaceSize 10780
-XX:MetaspaceSize=21807104

$ /usr/java/jdk1.8.0_05/bin/jinfo -flag MaxMetaspaceSize 10780
-XX:MaxMetaspaceSize=18446744073709547520

$ /usr/java/jdk1.8.0_05/bin/jinfo -flag PermSize 10780
no such flag 'PermSize'

$ /usr/java/jdk1.8.0_05/bin/jinfo -flag MaxPermSize 10780
no such flag 'MaxPermSize'

Metaspaceに関する情報は取得できるが、Permanent領域に関する情報は取得できていないことが分かる。(当然と言えば当然だが)

 

まとめ – Metaspaceは開発者にどういった恩恵をもたらすのか?

Permanent領域がMetaspace領域に置き換わることによって、開発者はどのような恩恵を得ることができるのだろうか。

近年はDIコンテナが発達してきており、DI対象となるクラス情報をサーバ起動時に一括してメモリ上に取り込むといった動作を行うコンテナも多い(JavaEEのCDIなど)。
こういった流れの中で、従来のクラス等のメタ情報をPermanent領域に配置するパターンでは、Permanent領域のOutOfMemoryErrorが発生しやすくなるといった状況となっていた。

Metaspace領域はNativeメモリとして取り扱われることからデフォルトのサイズ上限が無尽蔵にある。そのため、クラスやメソッドのメタ情報を大量に取り扱うDIコンテナとの相性が良く、開発者は頻発するPermanent領域のOutOfMemoryErrorから開放されるだろう。

ただし、上述した通り、クラス情報のメモリリークが疑われる場合はMetaspaceに対して上限値を設定することも重要だ。 Metaspaceはメモリリークを解消するための魔法の領域では無いという事を念頭に置き、Metaspaceの上限値設定を適宜実施する必要がある。

 

補足 – HotSpotVMのメモリ構造概説

当項ではHotSpotVMのメモリ構造の概要を記載しておこうと思う。HotSpotVMのメモリ構造に詳しくない方は、当項を読んだうえで記事本編を読むとスムーズに読めるだろう。

HotSpotVMとは?

HotSpotVMとは旧Sun Microsystems社が開発したJavaVMの事だ。Oracle社がSunを買収したことによって、現在はOracle社によって管理されている。 HotSpotVMの特徴として、コード内のHotSpotと呼ばれる”よく実行されるコード”を見つけ出し、このHotPointをネイティブ化することによって非常に高速な動作を実現している点が挙げられる。

HotSpotVMのメモリ構造と用途

HotSpotは以下のようなメモリ構造でJavaコードを実行する。

Java7HotSpotOverview

個々の領域の役割

メモリ上の個々の領域は以下の役割を持っている。

領域名役割
Eden生成されて間もないオブジェクト(インスタンス)を格納する。
newされたオブジェクトが最初に格納される領域である。
Survivor0/1From領域、To領域と呼ばれたりする。
インスタンス化されてから中程度の期間が経ったオブジェクトが保持される。Eden領域のオブジェクトが移動され、当領域に格納される。当領域のオブジェクトはOld領域に移動するまでの間、GCによってSurvivor0と1領域の間を行き来する。
Oldインスタンス化されてからある程度期間の経った、長命なオブジェクトを保持する。
例外を除き、Survivor領域上のオブジェクトがGCによって移動され、当領域に格納される。
Permanentクラスやメソッドの情報や、static変数、定数等の静的な情報を保持する。クラスローダによってロードされたクラス関連の情報が当領域に格納される。
保持する情報が大きく変動しない事からPermanent領域(永続領域)と呼ばれる。
CヒープJVMそのものが利用するメモリ空間である。JVM自身もプログラムであるから、JVM用にメモリを確保しなければならない。
ThreadStack実行中のJavaスレッド毎のスタック情報を保持する。
スタックとはメソッドの呼び出し階層情報の事だ。また、個々の呼出階層における変数の値も持っている。

ガーベッジコレクタはどのように振る舞うか?

メモリ構造とガーベッジコレクタの関係を説明する。

ガーベッジコレクタの種類

ガーベッジコレクタには「Scavenge GC」と「Full GC」の2種類がある(※)。ScavengeGCはローカルGCと呼ばれたりすることもある。それでは、個々のGCの役割を確認しよう。

※ これらとは別軸のGCの考え方としてシリアルGCやパラレルGC、コンカレントGC等があるが、今回の記事では単純のため割愛する。

GCの種別発生するきっかけ役割
ScavengeGCEden、Survivorが満杯Eden、Survivor領域内の不要オブジェクトをガーベッジする。
Eden⇒Survivor、Survivor⇒Oldのオブジェクト移動も行う。
頻繁に発生し、比較的短時間で終了する。
ローカルGCと呼ばれることもある。
FullGCOld、Permanentが満杯Old、Permanent領域内の不要オブジェクトをガーベッジする。
ScavengeGCと比べると発生する頻度は少ないが、実行に大きな時間を要する。
メモリリークが発生している場合、FullGCに時間を要するようになり、システムのボトルネックとなりやすい。

GC別の担当範囲を図にすると以下のようなイメージとなる。

gcimage

オブジェクトはメモリ内をどのように移動するのか?

長命なオブジェクトは以下のようなイメージで移動する。
以下のイメージはオブジェクトが途中でGC対象とならない(参照を失わない)前提の遷移である。 移動の途中でオブジェクトが参照を失い、GC対象のオブジェクトとなった場合、各GCによってメモリ領域は開放される。

hotspotObjectMoveImage

オブジェクト(インスタンス)の遷移

newされたオブジェクトは先ず、Eden領域に配置され、次のScavegeGCでSurvivor領域に移動する。
しばらくの間(-XX:MaxTenuringThreshouldパラメータに指定された回数)Survivor0と1の間を行き来し、その後、Old領域に移動する。
Old領域に配置されたオブジェクトが別の領域に移ることはない。

ちなみに、新たにオブジェクトをnewした際に、Eden領域に(ScavengeGCを実行したうえでなお)該当オブジェクトを格納する空きが無い場合は、いきなりOld領域にオブジェクトが格納される。同様の現象はEden領域⇒Survivor領域の遷移の際にも発生する。

クラス情報の遷移

こちらはオブジェクトに比べると単純だ。 クラスの情報はJava実行時に該当クラスが必要とされたタイミングでクラスローダーによってPermanent領域にロードされる。
一度ロードされた後はGC対象となるまでPermanent領域から移動することはない。

なぜオブジェクトはSurvivor領域を行き来するのか?

メモリの断片化を避けるためである。

GCの役割はオブジェクトによって占有されたメモリ空間を開放することだが、これを1つの領域でのみ実施すると次第に領域が断片化し、メモリ空間が中途半端なスキマだらけになってしまう。これを避けるために、ScavegeGCが発生する都度、Survivor領域の間でオブジェクトを移動させ、オブジェクトを再配置することによって断片化を避けているのだ。

Permanent領域でGC対象になる情報とは何か?

Permanent領域に格納される情報はクラスやメソッド、static変数等の情報である。
これらは静的な情報であり、オブジェクトと異なって不要となるタイミングは無いのではないか?と考える方も居るだろう。

しかし、自作クラスローダを経由してクラスをロードし、このクラスローダのインスタンスがヒープから消え、且つロードされたクラスの情報も利用されていない場合に限り、クラス情報をGC対象とすることができる。これをクラスアンロードと呼び、この仕組みを利用して実行中のJVM上のクラス情報を動的に差し替えることが可能だ。

ただし、ブートストラップクラスローダやシステムクラスローダなど、VM側で用意されるクラスローダを経由してロードされたクラス情報はGC対象とはならない。これらのクラスローダーのインスタンスは決して回収されることは無いため、上記条件を満たす事が無いからだ。

では、HotSpotVMを理解したところで、記事の冒頭に戻り、本編を読んでみよう!

関連記事

Java8のインタフェース実装から多重継承とMixinを考える

2014年3月18日、ついにJava8が正式にリリースを迎えた。 折角なので、今後、Java8の新

記事を読む

sshd再起動時にssh接続が継続する動作について

Linux/Unixサーバにsshしている際、sshdを再起動したとする。 sshdは一度終了する

記事を読む

ipsetを使ってスマートにiptablesを設定する

ギークな知人から「vpsでiptables設定していたらルール設定数の上限に引っかかって思い通りの設

記事を読む

Linuxプロセス起動時の環境変数ダンプの取得

UnixやLinux上で不具合の調査等々を行う際、特定のプロセス起動時の環境変数を知りたい場合がある

記事を読む

Ctrl+Cとkill -SIGINTの違いからLinuxプロセスグループを理解する

しばらくLinuxネタが続く・・。 近いうちに最近出たJava8ネタを書いてみようと思います。が、

記事を読む

「Systemd」を理解する ーシステム起動編ー

2014年6月10日、とうとうRHEL7が正式リリースを迎えた。RHEL7での変更点については、この

記事を読む

「Systemd」を理解する ーシステム管理編ー

前回の記事「Systemd」を理解するーシステム起動編ーでは、Systemdの概念とSystemdに

記事を読む

例示専用のIPアドレスとドメインを使いこなす

前回の記事ではネットワークに関する記事を投稿させていただいたが、今回も引き続きネットワーク関連のネタ

記事を読む

文字コードの考え方から理解するUnicodeとUTF-8の違い

UnicodeとUTF-8の違いを理解していない方が結構居るようなので、文字コードの考え方を元に解説

記事を読む

Comment

  1. かず より:

    はじめまして。
    JavaVMの勉強をしていて、こちらのサイトに出会いました。
    ぶしつけな質問で申し訳ないのですが、
    —————————————————————————–
            パーマネントエリア         メタスペース
    格納する情報   クラス/メソッド          クラス/メソッド
            static変数
    定数や文字列のintern表現
            (〜Java6まで)
    ——————————————————————————
    と掲載されておりますが、メタスペースに移行するにあたって、クラス/メソッド以外の部分はどこに格納されるようになったのでしょうか?

    • ブログ主 より:

      かず様

      コメントありがとうございます。ご質問の件、回答します。

      >メタスペースに移行するにあたって、クラス/メソッド以外の部分はどこに格納されるようになったのでしょうか?
      → 通常のヒープ領域に移動されています。
       ※ 記事中にも記載している通り、Eden〜Old領域(Xmx、Xmsなどでサイズ指定するあの領域)のことです

      <補足 – static変数の行き先について>
      また、一点補足させていただくとJEP122を読むと、以下のような記述(一部抜粋)があります。

      Success Metrics
      Class metadata, interned Strings and class static variables will be moved from the permanent generation to either the Java heap or native memory.

      <訳>クラスのメタデータ、interned Strings、およびクラスのstatic変数はPermenent領域からJavaヒープ、またはNativeメモリのどちらかに移動されます。

      とあり、元々Permanent領域に存在した項目の行き先を明記していません。(ただしinterned StringsについてはJava7でヒープ領域に移行済です。)
      クラスのメタデータについてはMetaspaceに移行されるものとして、残るはstatic変数の移行先ですが、これは同じくJEP122のDescription欄の記述が参考になります。一部抜粋します。

      The proposed implementation will allocate class meta-data in native memory and move interned Strings and class statics to the Java heap.

      <訳>本実装案は、クラスのメタデータをネイティブメモリに割り当て、interned Strings、およびstatic変数はJavaヒープに移動します。

      JEP122の実装案ではstatic変数はヒープ領域に移すこととなっています。しかし案と記載されている通り、実際のJVMの実装がこの通りとなっているか断言できない点にご注意いただきたいと思います。

      また、参考情報ですが、JavaVMについて深く学ぶ場合は書籍「Javaパフォーマンス」が非常に参考になるかと思います。

  2. 師子乃 より:

    初めまして、VMのメモリの構造、初めて詳しく拝見しました!
    とても勉強になりました。
    ありがとうございました!

Message

メールアドレスが公開されることはありません。

「Systemd」を理解する ーシステム管理編ー

前回の記事「Systemd」を理解するーシステム起動編ーでは、Syst

「Systemd」を理解する ーシステム起動編ー

2014年6月10日、とうとうRHEL7が正式リリースを迎えた。RHE

例示専用のIPアドレスとドメインを使いこなす

前回の記事ではネットワークに関する記事を投稿させていただいたが、今回も

ipsetを使ってスマートにiptablesを設定する

ギークな知人から「vpsでiptables設定していたらルール設定数の

Java8のHotSpotVMからPermanent領域が消えた理由とその影響

今回も前回の記事につづき、Java8による変更点で未だあまり紹介されて

→もっと見る

PAGE TOP ↑