Metaspace

6,593 views
6,136 views

Published on

JJUG CCC 2014 Spring資料

Published in: Technology
0 Comments
29 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
6,593
On SlideShare
0
From Embeds
0
Number of Embeds
611
Actions
Shares
0
Downloads
64
Comments
0
Likes
29
Embeds 0
No embeds

No notes for slide

Metaspace

  1. 1. 末永 恭正 @YaSuenag #ccc_r25
  2. 2. おことわり  この資料は2014/05/17時点の JDK8u/jdk8u-dev/hotspot(changeset 382a82b0a3e7:jdk8u20-b14)の内容を 基に記載しています。 OracleとJavaは、Oracle Corporation及びその子会社、関連会社の米国及びその他の国における登録商標です。 文中の社名、商品名等は各社の商標または登録商標である場合があります。
  3. 3. 自己紹介  末永 恭正(すえなが やすまさ) @YaSuenag  某SIerでJavaやってるサンデープログラマー  OpenJDK Author(jdk9)  IcedTea Committer  HeapStats作ってます http://icedtea.classpath.org/wiki/HeapStats/jp
  4. 4. Metaspace  Permanent世代の代わりに導入されたメタ データ管理の仕組み  JEP 122: Remove the Permanent Generation http://openjdk.java.net/jeps/122 “HotRockit”の一環 Perm世代をネイティブ メモリに追い出す
  5. 5. 扱うデータ  JVM実装でMetaspaceObjクラスを継承して いるものがMetaspaceで扱われる  ClassType ○ 純粋なクラス情報  NonClassType ○ ClassType以外の情報 ○ シンボル情報やメソッドの最適化に必要な情報など
  6. 6. MetaspaceObjの一覧
  7. 7. Metaspaceの種類 StandardMetaspaceType 通常のMetaspace BootMetaspaceType ブートストラップクラスローダ 専用 ROMetaspaceType クラス情報ダンプ時に使用され るMetaspace (-XX:+DumpSharedSpaces) ReadWriteMetaspaceType AnonymousMetaspaceType 匿名クラス専用 (InvokeDynamic) ReflectionMetaspaceType defineClass専用 (リフレクションなどの動的定義クラス)
  8. 8. ClassLoaderとVirtualSpace Class Loader 仮想メモリ空間VirtualSpaceList VirtualSpace VirtualSpace : VirtualSpace VirtualSpace : Class Loader メタデータ用の バラバラの空間を 仮想的に1つに =Metaspace VirtualSpace Compressed ClassSpace !?
  9. 9. CompressedClassSpace  圧縮Oopが利用可能な状況でのみ使用できる、 クラス情報に特化したメモリ空間  UseCompressedOopsが有効であることが必須 ○ 最大Javaヒープサイズが32GB以下であること  UseCompressedClassPointersでコントロー ル可能
  10. 10. 圧縮Oop?  LP64向けHotSpotでのみ利用可能なメモリ使 用量削減の仕組み  64bitポインタを、ベースアドレスからのオフ セットを用いてムリヤリ32bitで表現
  11. 11. どういうこと?  LP64のメモリアライメントは8byte  ObjectAlignmentInBytesでコントロール ○ デフォルト:8  つまり、下位3bitはゼロで埋められている  3bit右シフトしても情報欠損が起きない!  JavaヒープやCompressedClassSpaceは連続 空間  そこの上にアロケートされるメモリは、すべて開始 アドレスからのオフセットで表現可能!
  12. 12. プログラム的に表すと… http://www.oracle.com/technetwork/jp/articles/java/compressedoops-427542-ja.html 圧縮Oop(narrowOop)は符号なし32bitで表現されるので uint_max(4GB)<< 3 = 4GB×23 = 32GB 圧縮できる上限
  13. 13. Metaspaceの成長 = VirtualSpaceListの成長 =VirtualSpaceの追加  成長度合い  チャンクサイズで決まります
  14. 14. Metaspaceとチャンクサイズ
  15. 15. チャンクサイズはイジれません … HotSpotの1ワード:LP64なら8バイト、それ以外なら4バイト 対数(log)です
  16. 16. ここまでのまとめ  Metaspaceは1クラスローダにつき1つ割り当 てられる  Metaspaceは連続したメモリ空間ではない  Metaspaceで扱われる情報は大きく2種類  クラス情報  それ以外  Metaspaceには6つの種類が存在する  LP64環境でJavaヒープサイズが32GB以下の 場合はCompressedClassSpaceが作られる
  17. 17. Metaspaceでも OutOfMemoryErrorは起きます!
  18. 18. 実証コード 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; } }); } } }
  19. 19. OOMEを起こしてみる $ /usr/local/jdk1.8.0_05/bin/java -XX:CompressedClassSpaceSize=1m MetaFlood : java.lang.OutOfMemoryError: Compressed class space Exception in thread "main“ : $ /usr/local/jdk1.8.0_05/bin/java -XX:-UseCompressedClassPointers -XX:MaxMetaspaceSize=5m MetaFlood : java.lang.OutOfMemoryError: Metaspace Exception in thread "main“ : その1:CompressedClassSpace溢れ その2:Metaspace溢れ
  20. 20. Permanentとの違い  MetaspaceがGCされることはありません  クラスローダが破棄されると、関連する Metaspaceが削除されます  FullGC後にMetaspace容量の調整を行います  拡張 or 削減  ここでは閾値の変更のみを行い、実際のメモリ伸 縮は行いません
  21. 21. MetaspaceGC
  22. 22. Metaspace起因のGCが起こるま で 1. Metaspaceからメモリを取ろうとする i. 今あるメモリから取ろうとする ii. Metaspaceを拡張して取ろうとする 2. GCを起こす i. 使われていないクラスローダをGCで回収し、 できるだけ空きMetaspaceを増やす ii. Metaspaceを拡張して取ろうとする ~通常はここまででMetaspaceがとれる~ →OutOfMemoryError
  23. 23. 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しても まだ足りないため 最後の悪あがき
  24. 24. 「最後の悪あがき」とは?  ソフト参照も回収対象にし、できる限りクラス ローダを回収しようとします
  25. 25. 5つの手段 1. ツール  jstat  jcmd  jconsole  VisualVM 2. JMX 3. GCログ 4. NMT 5. HeapStats
  26. 26. jstat  -gcなどが使えます(単位は全部KB)  MC:Metaspace Capacity  MU:Metaspace Used  CCSC: 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 …
  27. 27. jcmd  PerfCounter.printで細かく見れます  sun.gc.metaspace  sun.gc.compressedclassspace $ /usr/local/jdk1.8.0_05/bin/jcmd 7831 PerfCounter.print : sun.gc.compressedclassspace.capacity=524288 sun.gc.compressedclassspace.maxCapacity=1073741824 sun.gc.compressedclassspace.minCapacity=0 sun.gc.compressedclassspace.used=264208 : sun.gc.metaspace.capacity=4980736 sun.gc.metaspace.maxCapacity=1082130432 sun.gc.metaspace.minCapacity=0 sun.gc.metaspace.used=2434808 :
  28. 28. jconsole  各メモリプールから確認できます
  29. 29. VisualVM  Metaspace全体の確認ができます
  30. 30. JMX  各メモリプールがあります
  31. 31. 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] : ※見やすく改行しています
  32. 32. Native Memory Tracking (NMT)  細かい情報を簡単に知りたいときに最適  -XX:NativeMemoryTracking=[summary|detail]  取り方は2種類  -XX:+UnlockDiagnosticVMOptions と -XX:+PrintNMTStatistics でjava終了時に取得  jcmd <PID> VM.native_memoryで外側から取得  Metaspaceは”Class”の部分です
  33. 33. jcmd VM.native_memory $ /usr/local/jdk1.8.0_05/bin/jcmd 8858 VM.native_memory 8858: Native Memory Tracking: Total: reserved=2330153KB, committed=135365KB : - Class (reserved=1062006KB, committed=10102KB) (classes #374) (malloc=5238KB, #153) (mmap: reserved=1056768KB, committed=4864KB) : インスタンス クラス数
  34. 34. HeapStats  1.1系を使ってください  閾値監視(SNMP Trap送信)もできます ココ
  35. 35. 注意  Metaspaceの値はCompressedClassSpaceの 値も含む、全体的な値です。  CompressedClassSpace⊆Metaspace  NonClassTypeなMetaspaceを見たい場合は、 MetaspaceからCompressedClassSpace分を 引いてください。
  36. 36. Metaspace関連オプション(- XX)オプション 意味 デフォルト MinMetaspaceExpansion Metaspaceの最小拡張単 位 256KB MinMetaspaceFreeRatio GC後の最小フリー量の パーセンテージ 40 MaxMetaspaceFreeRatio GC後の最大フリー量の パーセンテージ 70 MaxMetaspaceExpansion Metaspaceの最大拡張単 位 4MB
  37. 37. Metaspace関連オプション(- XX)オプション 意味 デフォルト UseLargePagesInMetaspace Metaspaceにラージペー ジを使うか? (UseLargePages必須) false TraceMetadataHumongousAllocation 大きなオブジェクトを Metaspaceにアロケート するのをトレースする false InitialBootClassLoaderMetaspaceSize ブートクラスローダ用 Metaspaceの初期値 LP64:4MB それ以外: 2200KB MetaspaceSize Metaspaceをリサイズさ せるための閾値 環境依存 MaxMetaspaceSize 最大Metaspaceサイズ unsigned long 最大値 CompressedClassSpaceSize CompressedClassSpace のサイズ 1GB
  38. 38. -XX:MetaspaceSizeでは Metaspaceの初期サイズを 指定できません!
  39. 39. 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
  40. 40. オプションをつける前に…  Metaspaceは連続空間ではない  1クラスローダ1メタスペース  ブートストラップ以外のクラスローダの初期サイズは 変更できない ○ InitialBootClassLoaderMetaspaceSize(デフォルト4MB)  CompressedClassSpaceはクラス情報「だけ」  シンボルやメソッドプロファイル情報などは別領域  長時間動作させていれば、Metaspace使用量はあ る程度安定してくる(はず)  動的ロードをガンガン行う場合はワカラナイ…
  41. 41. 一番注意すべきオプション CompressedClassSpaceSize JDK7u55: VmSize: 2153520 kB JDK8u5: VmSize: 3390320 kB 約1GBの差! オプションを何もつけずに起動したときの仮想 メモリ使用量(VSZ)
  42. 42. なぜ1GBも差が?  AMD64なJDK7ではMaxPermSizeの初期値が 64MB(jdk7u-devのHotSpotの場合)  Perm目的で64MBしかリザーブしない ○ MaxPermSizeはプラットフォームやHotSpot VMの種 類によりデフォルト値が異なります  CompressedClassSpaceのデフォルトは1GB  1GBリザーブしてしまう!! デフォルトのまま使うときは オーバーコミットに注意しましょう!
  43. 43. MaxMetaspaceSize 青天井! OSに殺されるかも…
  44. 44. 古の情報 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クラスはロードできるよ!という話
  45. 45. 1クラスあたりの占有サイズ  フィールド数、メソッド数によって異なります  一概に「だいたいxxバイト」と表現できません 実測一番!
  46. 46. と、いうわけで… -XX:MaxMetaspaceSize=そこそこ -XX:CompressedClassSpaceSize=100m ※責任はもちません -XX:MaxMetaspaceSize=そこそこ ①-Xmx32g以下の場合 ②-Xmx32g超えの場合 ③もう何も気にしたくない場合 -XX:-UseCompressedClassPointers

×