metaspace

56
Metaspace を OpenJDK ををををををををを末末 末末 @YaSuenag #ccc_r25

Upload: yasumasa-suenaga

Post on 28-May-2015

3.230 views

Category:

Technology


0 download

DESCRIPTION

JJUG CCC 2014 Spring資料

TRANSCRIPT

Page 1: Metaspace

MetaspaceをOpenJDK実装から見てみよ

う!末永 恭正  @YaSuenag

#ccc_r25

Page 2: Metaspace

おことわり この資料は 2014/05/17 時点の JDK8u/

jdk8u-dev/hotspot ( changeset 382a82b0a3e7 : jdk8u20-b14 )の内容を基に記載しています。

Oracle と Java は、 Oracle Corporation 及びその子会社、関連会社の米国及びその他の国における登録商標です。文中の社名、商品名等は各社の商標または登録商標である場合があります。

Page 3: Metaspace

自己紹介 末永 恭正(すえなが やすまさ) @YaSuenag

某 SIer で Java やってるサンデープログラマー

OpenJDK Author ( jdk9 ) IcedTea Committer

HeapStats 作ってますhttp://icedtea.classpath.org/wiki/HeapStats/jp

Page 4: Metaspace

Metaspaceって、何?

Page 5: Metaspace

Metaspace

Permanent 世代の代わりに導入されたメタデータ管理の仕組みJEP 122: Remove the Permanent Generation

http://openjdk.java.net/jeps/122

“HotRockit” の一環

Perm 世代をネイティブメモリに追い出す

Page 6: Metaspace

扱うデータ JVM 実装で MetaspaceObj クラスを継承して

いるものが Metaspace で扱われるClassType

○ 純粋なクラス情報NonClassType

○ ClassType 以外の情報○ シンボル情報やメソッドの最適化に必要な情報など

Page 7: Metaspace

MetaspaceObj の一覧

Page 8: Metaspace

Metaspace の種類StandardMetaspaceType 通常の Metaspace

BootMetaspaceType ブートストラップクラスローダ専用

ROMetaspaceType クラス情報ダンプ時に使用される Metaspace( -XX:+DumpSharedSpaces )

ReadWriteMetaspaceType

AnonymousMetaspaceType 匿名クラス専用( InvokeDynamic )

ReflectionMetaspaceType defineClass 専用(リフレクションなどの動的定義クラス)

Page 9: Metaspace

メモリレイアウト

Page 10: Metaspace
Page 11: Metaspace

ClassLoader とVirtualSpace

ClassLoader

仮想メモリ空間VirtualSpaceList

VirtualSpace

VirtualSpace

:VirtualSpace

VirtualSpace

ClassLoader

メタデータ用のバラバラの空間を仮想的に 1 つに=Metaspace

VirtualSpaceCompressedClassSpace !?

Page 12: Metaspace

CompressedClassSpace

圧縮 Oop が利用可能な状況でのみ使用できる、クラス情報に特化したメモリ空間UseCompressedOops が有効であることが必須

○ 最大 Java ヒープサイズが 32GB 以下であること UseCompressedClassPointers でコントロー

ル可能

Page 13: Metaspace

圧縮 Oop ? LP64 向け HotSpot でのみ利用可能なメモリ

使用量削減の仕組み 64bit ポインタを、ベースアドレスからのオ

フセットを用いてムリヤリ 32bit で表現

Page 14: Metaspace

どういうこと? LP64 のメモリアライメントは 8byte

ObjectAlignmentInBytes でコントロール○ デフォルト: 8

つまり、下位 3bit はゼロで埋められている3bit 右シフトしても情報欠損が起きない!

Java ヒープや CompressedClassSpace は連続空間そこの上にアロケートされるメモリは、すべて開始

アドレスからのオフセットで表現可能!

Page 15: Metaspace

プログラム的に表すと…http://www.oracle.com/technetwork/jp/articles/java/compressedoops-427542-ja.html

圧縮 Oop ( narrowOop )は符号なし 32bit で表現されるのでuint_max ( 4GB ) << 3 = 4GB×23 = 32GB

圧縮できる上限

Page 16: Metaspace

Metaspaceの成長

Page 17: Metaspace

Metaspace の成長= VirtualSpaceList の成長

=VirtualSpace の追加 成長度合い

チャンクサイズで決まります

Page 18: Metaspace

Metaspace とチャンクサイズ

Page 19: Metaspace

チャンクサイズはイジれません…

HotSpot の 1 ワード: LP64 なら 8 バイト、それ以外なら 4 バイト

対数( log )です

Page 20: Metaspace

ここまでのまとめ Metaspace は 1 クラスローダにつき 1 つ割り

当てられる Metaspace は連続したメモリ空間ではない Metaspace で扱われる情報は大きく 2 種類

クラス情報それ以外

Metaspace には 6 つの種類が存在する LP64 環境で Java ヒープサイズが 32GB 以下

の場合は CompressedClassSpace が作られる

Page 21: Metaspace

都市伝説(?):MetaspaceではOutOfMemoryErrorは起きない?

Page 22: Metaspace

Metaspace でもOutOfMemoryError は起きます!

Page 23: Metaspace

実証コードimport java.nio.file.*;import java.util.jar.*;

public class MetaFlood{

public static void main(String[] args) throws Exception{ Path rtjar_path = FileSystems.getDefault().getPath( System.getProperty("java.home"), "lib", "rt.jar");

try(JarFile rtjar = new JarFile(rtjar_path.toFile())){ rtjar.stream().filter(e -> !e.isDirectory()) .map(e -> e.getName()) .filter(n -> n.endsWith(".class")) .map(n -> n.substring(0, n.length() - 6).replace('/', '.')) .forEach(n -> { System.out.println(n); try{ ClassLoader.getSystemClassLoader().loadClass(n); } catch(ClassNotFoundException ex){} catch(OutOfMemoryError oome){ System.out.println(oome.toString()); throw oome; } }); }

}

}

Page 24: Metaspace

OOME を起こしてみる

$ /usr/local/jdk1.8.0_05/bin/java -XX:CompressedClassSpaceSize=1m MetaFlood :java.lang.OutOfMemoryError: Compressed class spaceException in thread "main“ :

$ /usr/local/jdk1.8.0_05/bin/java -XX:-UseCompressedClassPointers \ -XX:MaxMetaspaceSize=5m MetaFlood :java.lang.OutOfMemoryError: MetaspaceException in thread "main“ :

その1: CompressedClassSpace 溢れ

その2: Metaspace 溢れ

Page 25: Metaspace

MetaspaceとGC

Page 26: Metaspace

Permanent との違い Metaspace が GC されることはありません

クラスローダが破棄されると、関連するMetaspace が削除されます

FullGC 後に Metaspace 容量の調整を行います拡張 or 削減ここでは閾値の変更のみを行い、実際のメモリ伸

縮は行いません

Page 27: Metaspace

MetaspaceGC

Page 28: Metaspace

Metaspace 起因の GC が起こるまで

1. Metaspace からメモリを取ろうとするi. 今あるメモリから取ろうとするii. Metaspace を拡張して取ろうとする

2. GC を起こすi. 使われていないクラスローダを GC で回収し、

できるだけ空き Metaspace を増やすii. Metaspace を拡張して取ろうとする

~通常はここまでで Metaspace がとれる~

→OutOfMemoryError

Page 29: Metaspace

GC ログの例[Full GC (Metadata GC Threshold) [PSYoungGen: 496K->0K(2560K)] [ParOldGen: 388K->836K(6656K)] 884K->836K(9216K), [Metaspace: 7292K->7292K(9216K)], 0.0123187 secs] [Times: user=0.02 sys=0.00, real=0.01 secs]

[Full GC (Last ditch collection) [PSYoungGen: 0K->0K(2560K)] [ParOldGen: 836K->792K(6656K)] 836K->792K(9216K), [Metaspace: 7292K->7292K(9216K)], 0.0134180 secs] [Times: user=0.04 sys=0.00, real=0.02 secs]

※見やすく改行しています

Metaspace が足りなくてGC が発生

GC してもまだ足りないため

最後の悪あがき

Page 30: Metaspace

「最後の悪あがき」とは? ソフト参照も回収対象にし、できる限りクラス

ローダを回収しようとします

Page 31: Metaspace

どうチェックする?Metaspace使用量

Page 32: Metaspace

5 つの手段1. ツール

jstatjcmdjconsoleVisualVM

2. JMX

3. GC ログ4. NMT

5. HeapStats

Page 33: Metaspace

jstat

-gc などが使えます(単位は全部 KB )MC : Metaspace CapacityMU : Metaspace UsedCCSC: Compressed Class Space Capacity CCSU: Compressed Class Space Used

-gcmetacapacity というオプションもありますメタスペースサイズと GC回数・時間の取得用

$ /usr/local/jdk1.8.0_05/bin/jstat -gc 7831… MC MU CCSC CCSU …… 4864.0 2377.7 512.0 258.0 …

Page 34: Metaspace

jcmd

PerfCounter.print で細かく見れますsun.gc.metaspacesun.gc.compressedclassspace

$ /usr/local/jdk1.8.0_05/bin/jcmd 7831 PerfCounter.print :sun.gc.compressedclassspace.capacity=524288sun.gc.compressedclassspace.maxCapacity=1073741824sun.gc.compressedclassspace.minCapacity=0sun.gc.compressedclassspace.used=264208 :sun.gc.metaspace.capacity=4980736sun.gc.metaspace.maxCapacity=1082130432sun.gc.metaspace.minCapacity=0sun.gc.metaspace.used=2434808 :

Page 35: Metaspace

jconsole

各メモリプールから確認できます

Page 36: Metaspace

VisualVM

Metaspace全体の確認ができます

Page 37: Metaspace

JMX

各メモリプールがあります

Page 38: Metaspace

GC ログ Permだったところが Metaspace に変わって

います$ /usr/local/jdk1.8.0_05/bin/java -XX:+PrintGCDetails SystemGC :[Full GC (System.gc()) [PSYoungGen: 368K->0K(1024K)] [ParOldGen: 8K->251K(59904K)] 376K->251K(60928K), [Metaspace: 2377K->2377K(1056768K)], 0.0047055 secs][Times: user=0.01 sys=0.00, real=0.00 secs] : ※見やすく改行しています

Page 39: Metaspace

Native Memory Tracking (NMT)

細かい情報を簡単に知りたいときに最適 -XX:NativeMemoryTracking=[summary|detail] 取り方は 2 種類

-XX:+UnlockDiagnosticVMOptions と-XX:+PrintNMTStatistics で java終了時に取得

jcmd <PID> VM.native_memory で外側から取得 Metaspace は” Class” の部分です

Page 40: Metaspace

jcmd VM.native_memory

$ /usr/local/jdk1.8.0_05/bin/jcmd 8858 VM.native_memory8858:

Native Memory Tracking:

Total: reserved=2330153KB, committed=135365KB       :- Class (reserved=1062006KB, committed=10102KB) (classes #374) (malloc=5238KB, #153) (mmap: reserved=1056768KB, committed=4864KB)       :

インスタンスクラス数

Page 41: Metaspace

HeapStats

1.1系を使ってください 閾値監視( SNMP Trap送信)もできます

ココ

Page 42: Metaspace

注意 Metaspace の値は CompressedClassSpace

の値も含む、全体的な値です。CompressedClassSpace Metaspace⊆

NonClassType な Metaspace を見たい場合は、Metaspace から CompressedClassSpace分を引いてください。

Page 43: Metaspace

Metaspace関連オプション

Page 44: Metaspace

Metaspace 関連オプション( -XX )オプション 意味 デフォルトMinMetaspaceExpansion Metaspace の最小拡張単

位256KB

MinMetaspaceFreeRatio GC 後の最小フリー量のパーセンテージ

40

MaxMetaspaceFreeRatio GC 後の最大フリー量のパーセンテージ

70

MaxMetaspaceExpansion Metaspace の最大拡張単位

4MB

Page 45: Metaspace

Metaspace 関連オプション( -XX )オプション 意味 デフォルトUseLargePagesInMetaspace Metaspace にラージペー

ジを使うか?( UseLargePages 必須)

false

TraceMetadataHumongousAllocation 大きなオブジェクトをMetaspace にアロケートするのをトレースする

false

InitialBootClassLoaderMetaspaceSize ブートクラスローダ用Metaspace の初期値

LP64 : 4MB

それ以外:2200KB

MetaspaceSize Metaspace をリサイズさせるための閾値

環境依存

MaxMetaspaceSize 最大 Metaspace サイズ unsigned long最大値

CompressedClassSpaceSize CompressedClassSpaceのサイズ

1GB

Page 46: Metaspace

-XX:MetaspaceSize ではMetaspace の初期サイズを

指定できません!

Page 47: Metaspace

hotspot-gc-dev に質問してみたhttp://mail.openjdk.java.net/pipermail/hotspot-gc-dev/2014-April/009853.html

JIRA にも登録しました:  JDK-8039867: Incorrect description: -XX:MetaspaceSize  https://bugs.openjdk.java.net/browse/JDK-8039867

Page 48: Metaspace

チューニング(?)

Page 49: Metaspace

オプションをつける前に… Metaspace は連続空間ではない 1 クラスローダ 1 メタスペース

ブートストラップ以外のクラスローダの初期サイズは変更できない○ InitialBootClassLoaderMetaspaceSize (デフォルト

4MB ) CompressedClassSpace はクラス情報「だけ」

シンボルやメソッドプロファイル情報などは別領域 長時間動作させていれば、 Metaspace 使用量はあ

る程度安定してくる(はず)動的ロードをガンガン行う場合はワカラナイ…

Page 50: Metaspace

一番注意すべきオプションCompressedClassSpaceSize

JDK7u55 :  VmSize: 2153520 kB

JDK8u5 :  VmSize: 3390320 kB

約 1GB の差!

オプションを何もつけずに起動したときの仮想メモリ使用量( VSZ )

Page 51: Metaspace

なぜ 1GB も差が? AMD64 な JDK7 では MaxPermSize の初期値

が 64MB ( jdk7u-dev の HotSpot の場合)Perm目的で 64MB しかリザーブしない

○ MaxPermSize はプラットフォームや HotSpot VM の種類によりデフォルト値が異なります

CompressedClassSpace のデフォルトは 1GB1GB リザーブしてしまう!!

デフォルトのまま使うときはオーバーコミットに注意しましょう!

Page 52: Metaspace

MaxMetaspaceSize

青天井!OS に殺されるかも

Page 53: Metaspace

古の情報http://hg.openjdk.java.net/hsx/hotspot-rt/hotspot/diff/740e263c80c6/src/share/vm/runtime/arguments.cpp#l1.83

昔は 1 クラス情報= 1KB とみなしていました CompressedClassSpace をデフォルトで 100MB

に昔は ClassMetaspaceSize というオプションでした100,000 クラスはロードできるよ!という話

Page 54: Metaspace

1 クラスあたりの占有サイズ フィールド数、メソッド数によって異なります 一概に「だいたい xx バイト」と表現できません

実測一番!

Page 55: Metaspace

と、いうわけで…

-XX:MaxMetaspaceSize= そこそこ-XX:CompressedClassSpaceSize=100m

※責任はもちません

-XX:MaxMetaspaceSize= そこそこ

①-Xmx32g 以下の場合

②-Xmx32g超えの場合

③もう何も気にしたくない場合

-XX:-UseCompressedClassPointers

Page 56: Metaspace