Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Java仮想マシンの実装技術

10,493 views

Published on

PPLサマースクール2016「商用Java処理系の研究開発」のパート2です.
http://ppl.jssst.or.jp/index.php?ss2016

Java言語処理系の実装について詳説する.まずJava仮想マシンの概要について述べ,その主要な構成要素として,クラス管理とインタープリタ,ヒープ管理とガベージコレクション,スレッド管理と同期機構,JITコンパイラとの連携,などについて説明する.性能改善のために行った各種手法についても触れる.

他のパート
1 Javaの登場と発展
http://www.slideshare.net/Tamiya_Onodera/java-66081108
2 Java仮想マシンの実装技術
http://www.slideshare.net/KiyokuniKawachiya/java-66003903
3 Java Just-In-Timeコンパイラの実装技術
http://www.slideshare.net/ishizaki/20160906-pplss-ishizaki-public
4 まとめと展望
http://www.slideshare.net/Tamiya_Onodera/ss-66081142

Published in: Software
  • Hi there! I just wanted to share a list of sites that helped me a lot during my studies: .................................................................................................................................... www.EssayWrite.best - Write an essay .................................................................................................................................... www.LitReview.xyz - Summary of books .................................................................................................................................... www.Coursework.best - Online coursework .................................................................................................................................... www.Dissertations.me - proquest dissertations .................................................................................................................................... www.ReMovie.club - Movies reviews .................................................................................................................................... www.WebSlides.vip - Best powerpoint presentations .................................................................................................................................... www.WritePaper.info - Write a research paper .................................................................................................................................... www.EddyHelp.com - Homework help online .................................................................................................................................... www.MyResumeHelp.net - Professional resume writing service .................................................................................................................................. www.HelpWriting.net - Help with writing any papers ......................................................................................................................................... Save so as not to lose
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Dating for everyone is here: ❤❤❤ http://bit.ly/2Q98JRS ❤❤❤
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Dating direct: ❶❶❶ http://bit.ly/2Q98JRS ❶❶❶
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • DOWNLOAD THIS BOOKS INTO AVAILABLE FORMAT (Unlimited) ......................................................................................................................... ......................................................................................................................... Download Full PDF EBOOK here { http://bit.ly/2m77EgH } ......................................................................................................................... Download Full EPUB Ebook here { http://bit.ly/2m77EgH } ......................................................................................................................... ACCESS WEBSITE for All Ebooks ......................................................................................................................... Download Full PDF EBOOK here { http://bit.ly/2m77EgH } ......................................................................................................................... Download EPUB Ebook here { http://bit.ly/2m77EgH } ......................................................................................................................... Download doc Ebook here { http://bit.ly/2m77EgH } ......................................................................................................................... ......................................................................................................................... ......................................................................................................................... .............. Browse by Genre Available eBooks ......................................................................................................................... Art, Biography, Business, Chick Lit, Children's, Christian, Classics, Comics, Contemporary, Cookbooks, Crime, Ebooks, Fantasy, Fiction, Graphic Novels, Historical Fiction, History, Horror, Humor And Comedy, Manga, Memoir, Music, Mystery, Non Fiction, Paranormal, Philosophy, Poetry, Psychology, Religion, Romance, Science, Science Fiction, Self Help, Suspense, Spirituality, Sports, Thriller, Travel, Young Adult,
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • DOWNLOAD THIS BOOKS INTO AVAILABLE FORMAT (Unlimited) ......................................................................................................................... ......................................................................................................................... Download Full PDF EBOOK here { https://tinyurl.com/yyxo9sk7 } ......................................................................................................................... Download Full EPUB Ebook here { https://tinyurl.com/yyxo9sk7 } ......................................................................................................................... ACCESS WEBSITE for All Ebooks ......................................................................................................................... Download Full PDF EBOOK here { https://tinyurl.com/yyxo9sk7 } ......................................................................................................................... Download EPUB Ebook here { https://tinyurl.com/yyxo9sk7 } ......................................................................................................................... Download doc Ebook here { https://tinyurl.com/yyxo9sk7 } ......................................................................................................................... ......................................................................................................................... ......................................................................................................................... .............. Browse by Genre Available eBooks ......................................................................................................................... Art, Biography, Business, Chick Lit, Children's, Christian, Classics, Comics, Contemporary, Cookbooks, Crime, Ebooks, Fantasy, Fiction, Graphic Novels, Historical Fiction, History, Horror, Humor And Comedy, Manga, Memoir, Music, Mystery, Non Fiction, Paranormal, Philosophy, Poetry, Psychology, Religion, Romance, Science, Science Fiction, Self Help, Suspense, Spirituality, Sports, Thriller, Travel, Young Adult,
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

Java仮想マシンの実装技術

  1. 1. 2016年年9⽉月6⽇日 河内⾕谷清久仁 http://ibm.biz/kawatiya ⽇日本アイ・ビー・エム(株) 東京基礎研究所 (資料料作成協⼒力力:緒⽅方⼀一則,⼩小笠笠原武史,仲池卓也) PPLサマースクール2016「商⽤用Java処理理系の研究開発」 Java仮想マシンの実装技術 2016/09/061 Java仮想マシンの実装技術 / 河内⾕谷清久仁 JavaTMおよびすべてのJava関連の 商標およびロゴはOracleやその関連 会社の米国およびその他の国にお ける商標または登録商標です.
  2. 2. ©  2016  IBM  Corporation 概要:⽇日本アイ・ビー・エム(株)東京基礎研究所はJava⾔言語の黎黎明期からその処理理系に関する研究開発を リードし,IBM開発部⾨門と協業して業務アプリケーションの基盤として使われるJava処理理系を世に送り出して きた.特に,Just-­‐In-­‐TimeコンパイラとJava仮想マシンの主要構成要素については各種の先進的技術を考案し, 世界トップクラスの性能を達成するとともに,多数の学会発表も⾏行行ってきている.本セミナーでは,この商 ⽤用Java処理理系の研究開発に関する経験をもとに,以下の内容について述べる. 1  Javaの登場と発展(30分,講師:⼩小野寺⺠民也) 1995年年のJavaの登場とその後の受容の過程を概観し,Java登場時にどのような性能上の課題があったかを述 べ,続く2つのセッションへの導⼊入とする.また,性能向上の研究開発における標準ベンチマークの重要さ についても⾔言及する. 2  Java仮想マシンの実装技術(2時間,講師:河内⾕谷清久仁) Java⾔言語処理理系の実装について詳説する.まずJava仮想マシンの概要について述べ,その主要な構成要素と して,クラス管理理とインタープリタ,ヒープ管理理とガベージコレクション,スレッド管理理と同期機構,JIT コンパイラとの連携,などについて説明する.性能改善のために⾏行行った各種⼿手法についても触れる. 3  Java  Just-­‐In-­‐Timeコンパイラの実装技術(2時間,講師:⽯石崎⼀一明) Javaの動的コンパイラの実装について詳説する.まず構成の概要について述べ,主な最適化,動的コンパ イラ特有の最適化,Java⾔言語特有の最適化,について説明する.また,Java⾔言語からSIMDやGPUなどのハー ドウェア機構を使う試みについても述べる.商⽤用コンパイラの実装に関する経験談についても触れる. 4  まとめと展望(1時間,講師:⼩小野寺⺠民也) まとめとして,プログラミング⾔言語の実装技術の歴史を概観し,Javaの誕⽣生と発展に果たした役割につい て考えてみたい(内容は予告なく変更更することがありますw). 2016/09/062 商⽤用Java処理理系の研究開発 Java仮想マシンの実装技術 / 河内⾕谷清久仁
  3. 3. ©  2016  IBM  Corporation2016/09/063 講師紹介 ⼩小野寺 ⺠民也(おのでら たみや) http://ibm.biz/onodera ⽇日本アイ・ビー・エム(株)技術理理事,東京基礎研究所 サービス型コンピューティング 部⻑⾧長.1988年年東京 ⼤大学⼤大学院理理学系研究科情報科学専⾨門課程博⼠士課程修了了.同年年⽇日本アイ・ビー・エム(株)⼊入社.以来, 同社東京基礎研究所にて,プログラミング⾔言語およびミドルウェアおよびシステムソフトウェアの研究開 発に従事. 情報処理理学会第41回(平成2年年後期)全国⼤大会学術奨励賞,同平成7年年度度⼭山下記念念研究賞,同平 成16年年度度論論⽂文賞,同平成16年年度度業績賞,各受賞.理理学博⼠士.⽇日本ソフトウェア科学会会員(元・理理事), 情報処理理学会シニア会員,ACM  Distinguished  Scientist. 河内⾕谷 清久仁(かわちや きよくに) http://ibm.biz/kawatiya ⽇日本アイ・ビー・エム(株)シニア・テクニカル・スタッフ・メンバー,東京基礎研究所 ディープ・コン ピューティング&アナリティクス 部⻑⾧長.1987年年東京⼤大学⼤大学院理理学系研究科情報科学専攻修⼠士課程修了了. 同年年⽇日本アイ・ビー・エム(株)⼊入社.以来,同社東京基礎研究所にてOSやプログラミング⾔言語処理理系な どの研究に従事.最近は,Javaの性能問題分析などにも携わる.博⼠士(政策・メディア).1994年年情報処 理理学会⼤大会奨励賞,2005年年同・論論⽂文賞,2008年年⽇日本ソフトウェア科学会⾼高橋奨励賞,各受賞.⽇日本ソフト ウェア科学会編集副委員⻑⾧長(元・理理事),情報処理理学会シニア会員,ACM  Distinguished  Engineer. ⽯石崎 ⼀一明(いしざき かずあき) http://ibm.biz/ishizaki ⽇日本アイ・ビー・エム(株)東京基礎研究所 リサーチ・スタッフ・メンバー.1992年年早稲⽥田⼤大学理理⼯工学研 究科修⼠士課程修了了.同年年⽇日本アイ・ビー・エム(株)⼊入社.以来,同社東京基礎研究所にて,Fortran⾔言語 の並列列化コンパイラ,Java⾔言語の動的コンパイラ,Python⾔言語の動的コンパイラ,などのプログラミング ⾔言語処理理系の研究に従事.最近は,JavaやApache  Sparkからの,GPUその他アクセラレータ活⽤用⽅方法に興味 を持つ.情報処理理学会平成16年年度度業績賞受賞.博⼠士(情報科学).⽇日本ソフトウェア科学会理理事,情報処 理理学会会員,ACM  Senior  Member. Java仮想マシンの実装技術 / 河内⾕谷清久仁
  4. 4. ©  2016  IBM  Corporation 概要:Java⾔言語処理理系の実装について詳説する.まずJava仮想マシンの概要について述べ,その 主要な構成要素として,クラス管理理とインタープリタ,ヒープ管理理とガベージコレクション, スレッド管理理と同期機構,JITコンパイラとの連携,などについて説明する.性能改善のため に⾏行行った各種⼿手法についても触れる. § カバーする内容 – クラス管理理 – メソッド呼び出しとJIT連携 – バイトコードとインタープリタ – オブジェクト管理理とGC – スレッド管理理と同期機構 – 例例外処理理 – (JITコンパイラ超⼊入⾨門) 無記名アンケートへのご協⼒力力をお願いします (⼀一部だけの回答も可能です) 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁4 Java仮想マシンの実装技術 クラス管理 オブジェクト 管理 インタープリタ JIT コンパイラ JITコンパイラ 生成コード 実行時 プロファイラ クラスデータ (Java  バイト コード) Javaヒープ (Java  オブ ジェクト) Javaスタック (ローカル変数, オペランドスタック) Java仮想マシン(Java  VM) Java同期 ランタイム Java例外処理 ランタイム JVM ランタイム
  5. 5. ©  2016  IBM  Corporation § この講演では,⻘青で囲ったもの について説明する – JITコンパイラとプロファイラ については,次の講演で詳説 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁5 Java  VMの主要コンポーネントとデータ構造 クラス管理 オブジェクト 管理 インタープリタ JIT コンパイラ JITコンパイラ 生成コード 実行時 プロファイラ クラスデータ (Java  バイト コード) Javaヒープ (Java  オブ ジェクト) Javaスタック (ローカル変数, オペランドスタック) OS  /  標準ライブラリ Java仮想マシン(Java  VM) Java同期 ランタイム Java例外処理 ランタイム JVM ランタイム Java ソースコード (.javaファイル) javac クラスファイル (.classファイル, .jarファイル) プログラム作成時に 行う処理
  6. 6. ©  2016  IBM  Corporation Javaクラスファイルの作成と実⾏行行 6 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁 Java ソースコード (.javaファイル) javac クラスファイル (.classファイル, .jarファイル) プログラム作成時に 行う処理 class  Hello  { public  static  void  main(String[  ]  args)  { System.out.println("Hello  Java");; } } Hello.java $  javac Hello.java $  ls Hello.class Hello.java $ java Hello Hello Java $  
  7. 7. ©  2016  IBM  Corporation § クラスごとに作られる,構造を持ったバイナリファイル 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁7 クラスファイル 0xCAFEBABE major_versionは,「javac -­target」のJRE バージョンによって変わる(45~52) 定数表(リテラル,識別子など) このクラスで定義しているメソッドの 情報(継承したものは含まない) クラスのアクセス権や 親クラスなどのメタ情報 Implements  している インターフェースの一覧 クラス内のフィールドの一覧 バイトコード,デバッグ情報など. Attributeセクションは何個あってもよい “The  Java  Virtual  Machine Specification”  より
  8. 8. クラス管理理
  9. 9. ©  2016  IBM  Corporation § クラスファイルを読み込み, そのライフサイクルを管理理 するコンポーネント § サブコンポーネント – クラスローダ § クラスファイルを検索索 し,メモリ(クラス データ領領域)に展開 – ベリファイア § ロードしたクラスファ イルにエラーがないこ とを確認 – Constant  pool(定数表) § リテラルやシンボル情報を保持 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁9 クラス管理理 クラス管理 オブジェクト 管理 インタープリタ JIT コンパイラ JITコンパイラ 生成コード 実行時 プロファイラ クラスデータ (Java  バイト コード) Javaヒープ (Java  オブ ジェクト) Javaスタック (ローカル変数, オペランドスタック) Java仮想マシン(Java  VM) Java同期 ランタイム Java例外処理 ランタイム JVM ランタイム Java ソースコード (.javaファイル) javac クラスファイル (.classファイル, .jarファイル) プログラム作成時に 行う処理
  10. 10. ©  2016  IBM  Corporation § メモリ上に読み込んだクラスファイルをJava  VMに渡して,クラスとして登録する – クラスパスに従ってクラスファイルを探し,クラスデータ領領域に読み込む – クラスファイルの構造をメモリ上に 直接⽣生成してもよい § クラスローダ⾃自体もJavaオブジェクト – java.lang.ClassLoaderクラス(のサブ クラス)のインスタンス – Java  VMがデフォルトで⽣生成するもの が3個ある – ユーザが⽣生成することも可能 § クラスアンロード – 参照されなくなったクラスは, クラスローダ単位でアンロード可能 – 動的置き換え可能なモジュールの 実装に利利⽤用されている § EclipseなどのプラグインやEJB 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁10 クラスローダ クラスデータ領域 ユーザプログラムの クラス群 System class  loader 標準クラス群 Bootstrap   class    loader jre/lib/ext にある JARファイルから ロードされたクラス 群 Extension   class  loader Helloクラス constant_pool Field定義 Method定義 バイトコード, デバッグ情報など java.lang.Object java.lang.String Hello.class読み込み後のクラスデータ構造
  11. 11. ©  2016  IBM  Corporation クラスデータ領域 ロードされたクラス(イメージ) 11 Java仮想マシンの実装技術2016/09/06 クラスS constant_pool フィールド定義 S.m1の バイトコード S.m2の バイトコード 管理情報 S.m1の メソッド情報 vtable S.m2の メソッド情報 クラスA constant_pool フィールド定義 管理情報 vtable クラスB constant_pool フィールド定義 管理情報 vtable A.m2の メソッド情報 A.m3の メソッド情報 B.m3の メソッド情報 B.m3の バイトコード itable A.m2の バイトコード A.m3の バイトコード itable itable class  S  { int val =  1234;; void  m1()  {  …  } void  m2()  {  …  } } interface  I  {  void  m3();;  } class  A  extends  S implements  I  { void  m2()  {  …  } void  m3()  {  …  } } class  B  implements  I,J  { void  m3()  {  …  } }
  12. 12. ©  2016  IBM  Corporation クラスデータ領域 § オブジェクトのクラスに よって,呼ばれるメソッ ドが変わる § JITされたコードがあれば, そちらが呼ばれる 2016/09/06 Java仮想マシンの実装技術12 メソッド管理理:仮想メソッドの呼び出し class  S  { int val =  1234;; void  m1()  {  …  } void  m2()  {  …  } } interface  I  {  void  m3();;  } class  A  extends  S implements  I  { void  m2()  {  …  } void  m3()  {  …  } } class  B  implements  I,J  { void  m3()  {  …  } } クラスS constant_pool フィールド定義 S.m1の バイトコード S.m2の バイトコード 管理情報 S.m1の メソッド情報 vtable [1]  (m1) [2]  (m2) クラスA constant_pool フィールド定義 A.m2の バイトコード 管理情報 vtable [1]  (m1) [2]  (m2) [3]  (m3) S.m2の メソッド情報 A.m2の メソッド情報 A.m3の メソッド情報 S  p  =  new  S();; p.m2();;  //  à S.m2 S  q  =  new  A();; q.m2();;  //  à A.m2 p q A.m2の JITされた コード interface  I m3àvtable[3] A.m3の バイトコード
  13. 13. ©  2016  IBM  Corporation クラスデータ領域 § インタフェース関数の呼 び出しは,同じ名前でも 同じvtableオフセットに ならない § クラスデータのitableを スキャンして対応するイ ンタフェースを探し,メ ソッドに対応するvtable エントリを得る 2016/09/06 Java仮想マシンの実装技術13 メソッド管理理:インタフェースメソッドの呼び出し class  S  { int val =  1234;; void  m1()  {  …  } void  m2()  {  …  } } interface  I  {  void  m3();;  } class  A  extends  S implements  I  { void  m2()  {  …  } void  m3()  {  …  } } class  B  implements  I,J  { void  m3()  {  …  } } クラスA constant_pool フィールド定義 管理情報 vtable [1]  (m1) [2]  (m2) [3]  (m3) クラスB constant_pool フィールド定義 管理情報 vtable [1]  (m3) A.m2の メソッド情報 A.m3の メソッド情報 B.m3の メソッド情報 B.m3の バイトコード I  p  =  new  A();; p.m3();;  //  à A.m3 I  q  =  new  B();; q.m3();;  //  à B.m3 interface  “I” m3àvtable[3] A.m2の バイトコード A.m3の バイトコード interface  “I” m3àvtable[1] interface  “J” … …
  14. 14. ©  2016  IBM  Corporation2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁14 Javaバイトコード class  Hello  { static  int val =  1234567;; private  void  Hello() { super();; } public  static  void  main(…) { System.out. println("Hello  Java");; System.out. println(val);; } } Hello.java class  Hello  extends  java.lang.Object { static  {} 0:      ldc #7;;    //int 1234567 2:      putstatic #5;;    //Field  val 5:      return private  void  <init>();; 0:    aload_0 1:    invokespecial #1 4:    return public  static  void  main(java.lang.String[]);; 0:      getstatic #2;;    //Field      java.lang.System.out 3:      ldc #3;;    //String    "Hello  Java" 5:      invokevirtual #4;;    //Method  println(String) 8:      getstatic #2;;    //Field      java.lang.System.out 11:      getstatic #5;;    //Field      val 14:      invokevirtual #6;;    //Method  println(int) 17:      return } Hello.classのバイトコード javac § Javacが暗黙に⽣生成するメソッドがある § 多くの命令令が「定数表」を参照
  15. 15. ©  2016  IBM  Corporation2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁15 定数表(Constant  Pool) class  Hello  extends  java.lang.Object { static  {} 0:      ldc #7;;    //int 1234567 2:      putstatic #5;;    //Field  val 5:      return private  void  <init>();; 0:    aload_0 1:    invokespecial #1 4:    return public  static  void  main(java.lang.String[]);; 0:      getstatic #2;;    //Field      java.lang.System.out 3:      ldc #3;;    //String    "Hello  Java" 5:      invokevirtual #4;;    //Method  println(String) 8:      getstatic #2;;    //Field      java.lang.System.out 11:      getstatic #5;;    //Field      val 14:      invokevirtual #6;;    //Method  println(int) 17:      return } Hello.classのバイトコード String  "Hello  Java" 1234567 System.out java.lang.System "out" PrintStrem.println(String) java.io.PrintStream "println" "(Ljava/lang/String;;)V" Fieldref Methodref Name&Type UTF8 UTF8 UTF8 String Type val Int Object.<init>() PrintStrem.println(int) Index 0 1 2 3 4 5 6 7 9 11 12 14 15 16 Class Methodref println(String) 8 Class Fieldref Methodref "Hello  Java"UTF8 "Ljava/io/PrintStream;;"UTF8 13 "Ljava/lang/System;;"UTF8 10 Constant_pool
  16. 16. ©  2016  IBM  Corporation § Constant  poolは,クラスごとに作成されるデータ構造で,以下の内容を保持 – プログラム中のリテラル値 – フィールドやメソッドへの参照 § シンボル名(クラス名,メソッド名など) § Resolve後の状態 § Resolve – フィールドやメソッドへの参照を解決する処理理 § その参照への,初回のアクセス時に⾏行行われる § 参照先クラスがロードされていなければロードする § アクセス権のチェックが⾏行行われる – Resolve時に,参照情報のデータ形式を最適化することが多い § クラスロード直後は,参照対象は⽂文字列列形式で保持される § Resolve後は,参照対象へのポインタを保持するように書き換えられる – ⼀一旦Resolveされればその後は⾼高速に参照可能 § インタープリタでResolveしてしまい,JITedコードではResolve後の値を使うのがよい 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁16 シンボル参照の解決(Resolve) Stringオブジェクトへの参照 1234567 &System.out &PrintStrem.println(String) Fieldref Methodref String &val Int &Object.<init>() &PrintStrem.println(int) 0 1 2 3 4 5 6 7 Methodref Fieldref Methodref Resolve後のconstant pool
  17. 17. インタープリタ
  18. 18. ©  2016  IBM  Corporation § インタープリタとJust-­‐in-­‐Time(JIT)コンパイラ を組み合わせる処理理系が多い – インタープリタだけを使う処理理系や, JITコンパイラだけの処理理系(Jikes RVMなど) もある § Ahead-­‐of-­‐Time(AOT)コンパイラを使う処理理系 もある – Real-­‐time  Javaや,巨⼤大アプリの起動時間 短縮に有効 § 実⾏行行時プロファイラを⽤用いて,JITコンパイラ による最適化に有益な情報を収集することも ある 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁18 バイトコードの実⾏行行(インタープリタ) クラス管理 オブジェクト 管理 インタープリタ JIT コンパイラ JITコンパイラ 生成コード 実行時 プロファイラ クラスデータ (Java  バイト コード) Javaヒープ (Java  オブ ジェクト) Javaスタック (ローカル変数, オペランドスタック) Java仮想マシン(Java  VM) Java同期 ランタイム Java例外処理 ランタイム JVM ランタイム
  19. 19. ©  2016  IBM  Corporation § スタック・アーキテクチャの命令令セット – 操作対象のスタックを「オペランド・スタック」と呼ぶ – 基本的に型付きの命令令(スタック要素も型付き) § 1〜~3バイトの可変⻑⾧長(⼀一部例例外あり) 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁19 Javaバイトコード 0x60 opcode   (0x60) 1  byte iadd 0xb4getfield   0x01 opcode (0xb4) 1  byte 0x23 0x1234 0x5678 0x68AC Field  valObj  ref SP SP SPSP バイトコード オペランドスタックの操作 operand (0x0123)
  20. 20. ©  2016  IBM  Corporation § 実⾏行行中のメソッドの「フレーム」が保持される領領域 § フレームに格納されるデータ – カレントクラスなどのリンク情報 – メソッド呼び出しチェーン情報 – ローカル変数 § メソッド呼び出し時は,callerとcalleeのフレームの ⼀一部が重なる 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁20 Javaスタック SP ローカル 変数領域 SP ローカル 変数領域 0x1234 obj1 0x1234 ローカル 変数領域 obj1.foo(2) の呼び出し 2 Frame   data Frame   data Frame   data Callerの フレーム Callerの フレーム Calleeの フレーム Callee の引数 Callerの スタック Callerの スタック obj1 2
  21. 21. ©  2016  IBM  Corporation § Mixed-­‐mode  Execution – インタープリタとJITコンパイラを併⽤用する実⾏行行⽅方式 – 実⾏行行頻度度の⾼高いところだけ,実⾏行行中にコンパイルしてネイティブコードに変換 – この講演では,インタープリタにフォーカス(JITについては次の講演で) § バイトコード・インタープリタの基本構造 – デコード・ループ § 1命令令読み込んで,対応するハンドラを呼び出し,ハンドラから戻ってきたら次の命 令令を読み込むループ – ハンドラ(群) § バイトコード命令令で定義された処理理を⾏行行うサブルーチン 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁21 バイトコードの実⾏行行 デコード・ ループ ハンドラ1 ハンドラ2 バイトコード
  22. 22. ©  2016  IBM  Corporation § 基本構造をC⾔言語で実装するなら,ハンドラごとに関数を作る 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁22 バイトコード・インタープリタの基本的な実装例例 char  *pc  =  getBytecodeAddr(); int *sp =  getStackBottom(); void (*decodeTbl[])(char**,int**)={ &op00_handler,   /*0x00*/ ... &op04_handler,   /*0x04*/ ... &op60_handler,   /*0x60*/ ...  }; while(TRUE)   { (*decodeTbl[*pc++])(&pc,&sp); } デコード・ループ 0x1234 0x5678 0x68ACiadd SP SP op00_handler(char   **pc,int **sp){ /*  0x00:  nop */ return;  } op60_handler(char   **pc,int **sp){   /*  0x60:  iadd */ (*sp)[1]   +=  (*sp)[0];   ++*sp; return;  } op04_handler(char   **pc,int **sp){   /*  0x04:  iconst_1   */ (-­‐-­‐*sp)[0]  =  1; return;  }
  23. 23. ©  2016  IBM  Corporation インタープリタの⾼高速化 23 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁
  24. 24. ©  2016  IBM  Corporation § プログラム起動時は,JITコンパイルしない⽅方が速い [Suganuma’01] – その場合,インタープリタの⾼高速化により起動時間を短縮できる § また,JITコンパイルするメソッドを減らせば,JITではなくプログラム実⾏行行に時間を使える 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁24 インタープリタ⾼高速化の必要性 [Suganuma ‘01]  T.  Suganuma et  al.    A  Dynamic  Optimization Framework  for  a  Java  Just-­In-­ Time  Compiler.    OOPSLA  ’01 遅い←→速い スタートアップの性能⽐比較 全部full-­‐JITす るととても遅い JITしない⽅方が アプリ起動は速い Java:  IBM  JDK  1.3.0 HW:  Pentium  III  600  MHz,  512MB  Memory OS:  Windows  2000  SP1
  25. 25. ©  2016  IBM  Corporation § 頻繁に分岐命令令を実⾏行行するので,コードが分断される – デコード・ループもハンドラも,短く,並列列度度の低いコード § ループであっても,命令令読み込みとデコードを繰り返す 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁25 バイトコード・インタープリタのオーバーヘッド TOS: Top of Stack i2s ハンドラ ineg ハンドラ ifgt ハンドラ iload_3 ハンドラ 例:「while(  (short)(-­x)  >  0  );;」のデコード操作 xをpush 符号反転 short型に変換 TOS>0なら ジャンプ デコード・ ループ ff faバイトコード 9d93741d
  26. 26. ©  2016  IBM  Corporation § デコード・ループを全てのハンドラにコピーして間接分岐の実⾏行行回数を減らす – 各ハンドラの最後で次のバイトコードをデコードし,そのハンドラへ直接ジャンプする § アドレス計算の⾼高速化⼿手法もいろいろある – ハンドラを固定サイズにしてバイトコード順に並べれば,算術演算でアドレス取得も可能 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁26 解決法の例例:Threaded  Code  [Bell’73,  Ritter’80] iload_3 ハンドラ ineg ハンドラ バイト コード &iload_3 &i2s &ineg ハンドラ アドレス 表 デコード& ジャンプ デコード& ジャンプ デコード&ジャンプ 1d 74 93
  27. 27. ©  2016  IBM  Corporation § スタック・アーキテクチャの仮想マシンでは, スタック・トップ(Top  of  Stack=TOS)近辺の値を頻繁にアクセスする § 同じメモリを何度度もアクセスする場合がある 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁27 スタック・アーキテクチャ仮想マシンのボトルネック SP 0xFFFF SP 0x0001 i2s ハンドラ ineg ハンドラ ifgt ハンドラ iload_3 ハンドラ 例:「while(  (short)(-­x)  >  0  );;」のスタック操作 xをpush 符号反転 short型に変換 TOS>0なら ジャンプ 0x0001 SP SP SP
  28. 28. ©  2016  IBM  Corporation § スタック・トップ(TOS)近辺の値をレジスタにキャッシュする – Write-­‐through  cacheかwrite-­‐backにするかは,実装依存 § 問題点 – 常にTOSをキャッシュすると,無駄な読み込みが発⽣生する – TOSが無効な状況を認めると,実⾏行行時チェックが必要になる 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁28 解決法の例例:Stack  Caching 0x1234 0x5678 0x68AC SP SP iadd ハンドラ 0x1234 0x5678 0x68AC SP SP iadd ハンドラ 0x1234 TOSレジスタ 0x68AC TOSレジスタ Stack  Cachingなし Stack  Cachingあり
  29. 29. ©  2016  IBM  Corporation § 効率率率よく,キャッシュ要素数を可変にする技術 § Step-­‐1:キャッシュしている要素数ごとに 別々のハンドラを⽤用意する 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁29 改良良:Dynamic  Stack  Caching  [Ertl’95] 0x5678 SP SP iadd (c1àc1) 0x1234 TOSレジスタ 0x68AC TOSレジスタ キャッシュ要素数=1 のハンドラの動作 SP SP iadd (c2àc1) 0x1234 TOSレジスタ 0x68AC TOSレジスタ 0x5678 NOSレジスタ キャッシュ 要素数=2 NOS: Next of Stack 0x1234 0x5678 SP SP iadd (c0àc1) 0x68AC TOSレジスタ キャッシュ要素数=0 のハンドラの動作 キャッシュ 要素数の変化
  30. 30. ©  2016  IBM  Corporation § Step-­‐2:キャッシュしている要素数ごとに⽤用意したハンドラでステートマシンを構成して, キャッシュしている要素数を管理理 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁30 改良良:Dynamic  Stack  Caching  [Ertl’95] iadd (c0àc1) iadd (c1àc1) iadd (c2àc1) iconst_1 (c0àc1) iconst_1 (c1àc2) iconst_1 (c2àc2) ifeq (c0àc0) ifeq (c1àc0) ifeq (c2àc1) iload_3 (c0àc1) iload_3 (c1àc2) iload_3 (c2àc2) 例:「if (  x+1  ==  0  )」のハンドラ呼び出しフロー xをpush 1をpush 加算 TOS==0なら ジャンプ キャッシュ要素数=2 キャッシュ要素数=1 キャッシュ要素数=0
  31. 31. ©  2016  IBM  Corporation § プロセッサ内部では,メモリの読み書きは常にワード境界に合わせた動作をする – ワード単位でない場合は,適宜エミュレートする § バイトコードの読み込みでは,同じワードを何度度も読込む 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁31 バイトコード読み込みのメモリアクセスの⾮非効率率率性 ff fa ??バイトコード 9d93741d 74 93 9d ff fa ワード境界 オペコード0x74を読込み オペコード0x93を読込み オペコード0x9dを読込み オペランド0xfffaを読込み 例:「while(  (short)(-­x)  >  0  );;」のデコード操作
  32. 32. ©  2016  IBM  Corporation § しかし,バイトコード列列をワード単位でレジスタにキャッシュすると, バイトコードのワード内オフセットのチェックが必要になる 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁32 解決法の例例:バイトコードをワード単位でキャッシュ 例:「while(  (short)(-­x)  >  0  );;」のデコード操作 ff fa 1cバイトコード 9d93741d 74 93 9d ff fa ワード境界 オペコード0x74を読込み オペコード0x93を読込み オペコード0x9dを読込み オペランド0xfffaを読込み レジスタにキャッシュ ff fa 1c9d9374
  33. 33. ©  2016  IBM  Corporation § オペコードのワード内位置ごとに,別々のバイトコード・ハンドラを⽤用意し, ステートマシンで現在のワード内位置を追跡する 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁33 改良良:Position-­‐based  handler  customization  [Ogata’02] ff fa 1cバイトコード 9d93741d ワード境界 レジスタにキャッシュ (Bytecode  Prefetch  Register) ff fa 1c9d9374 ineg (b0àb1) next  opcode =  BPR0[1] ineg (b1àb2) next  opcode =  BPR0[2] ineg (b2àb3) next  opcode =  BPR0[3] ineg (b3àb0) next  opcode =  BPR1[0] BPR0  =  BPR1 Load  BPR1 BPR0 BPR1 9374 BPR0 9374 BPR0 9374 BPR0 9374 BPR0 BPR1 例:ineg(0x74)ハンドラの4つのバリエーション
  34. 34. ©  2016  IBM  Corporation SPECjvm 98 jBYTEmark JavaGrande 相対性能 § ベース・インタープリタ(Threaded  code)からの速度度変化 – DS=Dynamic  Stack  Caching,WT=Write-­‐throughで常に1個キャッシュ – PHC=ワード単位でバイトコードをキャッシュ,PSD=投機的にデコード 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁34 パフォーマンス⽐比較遅い←→速い ※ このグラフはゼロ始まりでないので注意 Java:  IBM  JDK  1.3.0 HW:  POWER3  400MHz,  768MB  Memory OS:  AIX  4.3.3 ※どの最適化がよく効くかは, プロセッサの特性によっても異異なる
  35. 35. オブジェクト管理理
  36. 36. ©  2016  IBM  Corporation § Javaヒープ – Javaオブジェクトを格納する領領域 § オブジェクト管理理 – Javaでは,不不要になったオブジェクトは ガベージコレクタ(GC)が⾃自動回収する § オブジェクト管理理に関するトピック – オブジェクトの構造 – オブジェクトの⽣生成 – オブジェクトの回収(GC) – 関連する話題など 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁36 オブジェクト管理理 クラス管理 オブジェクト 管理 インタープリタ JIT コンパイラ JITコンパイラ 生成コード 実行時 プロファイラ クラスデータ (Java  バイト コード) Javaヒープ (Java  オブ ジェクト) Javaスタック (ローカル変数, オペランドスタック) Java仮想マシン(Java  VM) Java同期 ランタイム Java例外処理 ランタイム JVM ランタイム
  37. 37. ©  2016  IBM  Corporation § オブジェクト指向⾔言語では,オブジェクトを⽣生成しメソッドを呼び出すことで処理理が⾏行行われる – オブジェクトはnewした時に「ヒープ」内に作られるが,ライブラリ内などで暗黙のうち に⽣生成されるオブジェクトもたくさんある § ⾮非常に単純なプログラムの例例 – ⼀一⾒見見オブジェクトなど使っていないようでも,オブジェクトが使⽤用されている 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁37 オブジェクトを⽤用いた処理理 1  class  SayHello { 2          static  String  str =  "Hello  ";; 3 4   public  static  void  main(String[  ]  args)  { 5     String  msg =  str +  args[0];; 6     System.out.println(msg);; 7         msg =  null;; 8  } } $  javac SayHello.java $  java  SayHello world Hello  world StringBuilder tmp =  new  StringBuilder();; tmp.append(str);; tmp.append(args[0]);; String  msg =  tmp.toString();; § ⾚赤字部分でオブジェクトが⽣生成される § オブジェクトの構造 – メタ情報が⼊入るヘッダ – フィールド値が⼊入るボディ String value offset=0 count=5
  38. 38. ©  2016  IBM  Corporation § オブジェクトは,クラスで定義されたフィールドを持つ – 親クラスのフィールドも持つので,親クラスのインスタンスのふりができる § フィールドを保持する「ボディ」の他に,メタ情報を持つ「ヘッダ」がある – ヘッダには,クラスへのポインタ,配列列のサイズ,ロックやGCのための情報などがある § オブジェクトを指すには,直接指す⽅方法と,ハンドルを介す⽅方法がある – ハンドルを介すとオブジェクトの移動がしやすいが,性能とメモリ消費に影響がある – 現在の主流流は直接指す⽅方法 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁38 オブジェクトの構造 class  A  { char  c;; int i;; short  s;; } i s j a c s ヘッダ i s c ヘッダ Aのインスタンス Bのインスタンス ハンドルテーブル class  B  extends  A  { int j;; short  s;; A  a;; } 32bit
  39. 39. ©  2016  IBM  Corporation § ハンドルの削除 – 最初はハンドルあり(低性能)+容易易なコンパクション – →  ハンドルなし+保守的GCによる限定的コンパクション – →  ハンドルなし+マップを⽤用意したtype  accurate  GC § ロックのためのデータ構造の⼯工夫 – 現在の同期機構では,ロックのためにヘッダ内の1ワード弱を使⽤用 [Bacon’98] – あまり同期に使⽤用されないクラスはロックワードを持たない [Bacon’02] § 同期に使⽤用された場合は外部に追加データを⽤用意して対処 è 現在のIBM  Javaでは,ヘッダは最少1ワード(クラスポインタ+フラグのみ) – 配列列の場合は,サイズを保持するために+1ワード – 「頻繁に同期に使⽤用される」クラスの場合は+1ワード § Compressed  References – 64bitマシンでも,ポインタを32bitに圧縮して保持 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁39 オブジェクト使⽤用メモリの削減 i s j a c s ヘッダ i s c ヘッダ Aのインスタンス Bのインスタンス ハンドルテーブル 32bit
  40. 40. ©  2016  IBM  Corporation § オブジェクトを作る場所は,ヒープとしてメモリ空間上 に確保されている – ヒープ上の,オブジェクトに割り当てていない場所を フリーエリアやフリーリストとして管理理 – newが呼ばれると,フリーエリアからメモリを確保し オブジェクトを作る § マルチスレッド環境への対処 – 複数のスレッドが同時にnewを呼ぶことがあるため, ヒープからのオブジェクト領領域確保は排他的に⾏行行う必 要がある – しかしそれだと遅くなるので,スレッドごとにヒープ の⼀一部を割り当て(スレッドローカルヒープ),そこ からオブジェクトを割り当てるのが⼀一般的 – スレッドローカルヒープがなくなった場合,新しいも のをヒープから割り当てる(ここは排他制御が必要) 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁40 オブジェクトの⽣生成 Javaヒープ For Th1 For Th2 For Th1
  41. 41. ©  2016  IBM  Corporation § SayHelloクラスの初期化 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁41 オブジェクトを⽤用いた処理理 ‘H’ ‘e’ ‘l’ ‘l’ ‘o’ ‘ ’ char[6]String value offset=0 count=6 str class  SayHello Javaヒープ 1  class  SayHello { 2      static  String  str =  "Hello  ";; 3 4      public  static  void  main(String[  ]  args)  { 5          String  msg =  str +  args[0];; 6          System.out.println(msg);; 7          msg =  null;; 8  }  } Stringオブジェクトの 内部構造は処理理系依存 であり,ここで⽰示して いるのは⼀一例例です.
  42. 42. ©  2016  IBM  Corporation2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁42 オブジェクトを⽤用いた処理理 ‘w’ ‘o’ ‘r’ ‘l’ ‘d’ char[5] [0] String[1] String value offset=0 count=5 ‘H’ ‘e’ ‘l’ ‘l’ ‘o’ ‘ ’ char[6]String value offset=0 count=6 str args class  SayHello Thread  stack Javaヒープ 1  class  SayHello { 2      static  String  str =  "Hello  ";; 3 4      public  static  void  main(String[  ]  args)  { 5          String  msg =  str +  args[0];; 6          System.out.println(msg);; 7          msg =  null;; 8  }  } § スレッドスタックと引数argの⽤用意 Stringオブジェクトの 内部構造は処理理系依存 であり,ここで⽰示して いるのは⼀一例例です.
  43. 43. ©  2016  IBM  Corporation § tmp =  new  StringBuilder(); 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁43 オブジェクトを⽤用いた処理理 ‘w’ ‘o’ ‘r’ ‘l’ ‘d’ char[5] [0] String[1] String value offset=0 count=5 ‘H’ ‘e’ ‘l’ ‘l’ ‘o’ ‘ ’ char[6]String value offset=0 count=6 ‘H’ ‘e’ ‘l’ ‘l’ ‘o’ ‘ ’ char[16] ‘w’ ‘o’ ‘r’ ‘l’ ‘d’ StringBuilder value count=0 str msg args tmp class  SayHello Thread  stack Javaヒープ 1  class  SayHello { 2      static  String  str =  "Hello  ";; 3 4      public  static  void  main(String[  ]  args)  { 5          String  msg =  str +  args[0];; 6          System.out.println(msg);; 7          msg =  null;; 8  }  } Stringオブジェクトの 内部構造は処理理系依存 であり,ここで⽰示して いるのは⼀一例例です.
  44. 44. ©  2016  IBM  Corporation ‘H’ ‘e’ ‘l’ ‘l’ ‘o’ ‘ ’ char[16] ‘w’ ‘o’ ‘r’ ‘l’ ‘d’ 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁44 オブジェクトを⽤用いた処理理 ‘w’ ‘o’ ‘r’ ‘l’ ‘d’ char[5] [0] String[1] String value offset=0 count=5 ‘H’ ‘e’ ‘l’ ‘l’ ‘o’ ‘ ’ char[6]String value offset=0 count=6 ‘H’ ‘e’ ‘l’ ‘l’ ‘o’ ‘ ’ char[16] ‘w’ ‘o’ ‘r’ ‘l’ ‘d’ StringBuilder value count=11 str msg args tmp class  SayHello Thread  stack Javaヒープ 1  class  SayHello { 2      static  String  str =  "Hello  ";; 3 4      public  static  void  main(String[  ]  args)  { 5          String  msg =  str +  args[0];; 6          System.out.println(msg);; 7          msg =  null;; 8  }  } § tmp.append(str);  tmp.append(args[0]); Stringオブジェクトの 内部構造は処理理系依存 であり,ここで⽰示して いるのは⼀一例例です.
  45. 45. ©  2016  IBM  Corporation § msg =  tmp.toString(); 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁45 オブジェクトを⽤用いた処理理 ‘w’ ‘o’ ‘r’ ‘l’ ‘d’ char[5] [0] String[1] String value offset=0 count=5 ‘H’ ‘e’ ‘l’ ‘l’ ‘o’ ‘ ’ char[6]String value offset=0 count=6 ‘H’ ‘e’ ‘l’ ‘l’ ‘o’ ‘ ’ char[16] ‘w’ ‘o’ ‘r’ ‘l’ ‘d’ String value offset=0 count=11 StringBuilder value count=11 str msg args tmp class  SayHello Thread  stack Javaヒープ 1  class  SayHello { 2      static  String  str =  "Hello  ";; 3 4      public  static  void  main(String[  ]  args)  { 5          String  msg =  str +  args[0];; 6          System.out.println(msg);; 7          msg =  null;; 8  }  } Stringオブジェクトの 内部構造は処理理系依存 であり,ここで⽰示して いるのは⼀一例例です.
  46. 46. ©  2016  IBM  Corporation § msg =  null; 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁46 オブジェクトを⽤用いた処理理 ‘w’ ‘o’ ‘r’ ‘l’ ‘d’ char[5] [0] String[1] String value offset=0 count=5 ‘H’ ‘e’ ‘l’ ‘l’ ‘o’ ‘ ’ char[6]String value offset=0 count=6 ‘H’ ‘e’ ‘l’ ‘l’ ‘o’ ‘ ’ char[16] ‘w’ ‘o’ ‘r’ ‘l’ ‘d’ String value offset=0 count=11 StringBuilder value count=11 str msg args tmp class  SayHello Thread  stack Javaヒープ 1  class  SayHello { 2      static  String  str =  "Hello  ";; 3 4      public  static  void  main(String[  ]  args)  { 5          String  msg =  str +  args[0];; 6          System.out.println(msg);; 7          msg =  null;; 8  }  } Stringオブジェクトの 内部構造は処理理系依存 であり,ここで⽰示して いるのは⼀一例例です.
  47. 47. ©  2016  IBM  Corporation § オブジェクトは使われなくなってもヒープに残る! 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁47 オブジェクトを⽤用いた処理理 ‘w’ ‘o’ ‘r’ ‘l’ ‘d’ char[5] [0] String[1] String value offset=0 count=5 ‘H’ ‘e’ ‘l’ ‘l’ ‘o’ ‘ ’ char[6]String value offset=0 count=6 ‘H’ ‘e’ ‘l’ ‘l’ ‘o’ ‘ ’ char[16] ‘w’ ‘o’ ‘r’ ‘l’ ‘d’ String value offset=0 count=11 StringBuilder value count=11 str msg args tmp class  SayHello Thread  stack Javaヒープ 1  class  SayHello { 2      static  String  str =  "Hello  ";; 3 4      public  static  void  main(String[  ]  args)  { 5          String  msg =  str +  args[0];; 6          System.out.println(msg);; 7          msg =  null;; 8  }  } Stringオブジェクトの 内部構造は処理理系依存 であり,ここで⽰示して いるのは⼀一例例です.
  48. 48. ©  2016  IBM  Corporation § ⽣生成したオブジェクトは,不不要になったら消去しなければならない – そうしないと,ヒープがいっぱいになって処理理が続けられなくなる § C++では(デフォルトでは),deleteによりアプリが明⽰示的に消去する – 消去し忘れや,不不要でないのに消去してしまうなどの危険性がある – セキュリティーホールにもなりえる § Javaでは,ガベージコレクタ(GC)が標準装備されており, 不不要なオブジェクト(=ガベージ)は⾃自動的に回収(=コレクト)される 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁48 オブジェクトの回収
  49. 49. ©  2016  IBM  Corporation2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁49 不不要なオブジェクトとは? ‘w’ ‘o’ ‘r’ ‘l’ ‘d’ char[5] [0] String[1] String value offset=0 count=5 ‘H’ ‘e’ ‘l’ ‘l’ ‘o’ ‘ ’ char[6]String value offset=0 count=6 str msg args tmp class  SayHello Thread  stack Javaヒープ ‘H’ ‘e’ ‘l’ ‘l’ ‘o’ ‘ ’ char[16] ‘w’ ‘o’ ‘r’ ‘l’ ‘d’ String value offset=0 count=11 StringBuilder value count=11 1  class  SayHello { 2      static  String  str =  "Hello  ";; 3 4      public  static  void  main(String[  ]  args)  { 5          String  msg =  str +  args[0];; 6          System.out.println(msg);; 7          msg =  null;; 8  }  } § GCルートからたどり着けないオブジェクトは不不要 7行目終了時点で 「死んで」いるオブジェクト GCルートの例例 – スレッドの実⾏行行スタック (ローカル変数) – クラスのスタティック変数 (グローバル変数) – などなど
  50. 50. ©  2016  IBM  Corporation § ガベージコレクションの基本アルゴリズム(の⼀一つ) 1.  Stop  the  world – すべてのスレッド(Mutator)を⼀一時停⽌止させる(Stop-­‐the-­‐world) – GC中にオブジェクトの変更更を⾏行行わせないため 2.  Mark – GCルートからたどれるオブジェクト に「マーク」を付ける – マークが付いたオブジェクトは 「⽣生きて」いる(=回収できない) 3.  Sweep – マークが付いていないオブジェクト の領領域をフリーリストにつなぐ 4.  後処理理 – 停⽌止したスレッドの実⾏行行を再開 § 利利点:仕組みが単純 § ⽋欠点:GC中,アプリケーションが停⽌止 してしまう,停⽌止時間も⻑⾧長め 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁50 ガベージコレクションの基本:Mark  &  Sweep class SayHello Thread stack JavaヒープGCルート M M M M M
  51. 51. ©  2016  IBM  Corporation § どのデータがオブジェクトを指しているの か? – たとえば,0x12345678というデータが ⼊入っていた場合,それはオブジェクト を指しているのか,単なる⼤大きなint値 なのか? § 処理理系は,オブジェクトやクラスがどうい う構造をしているのか知っている (Javaでは) – そのためGCは,オブジェクトを指す フィールドだけをたどることができる § スレッドスタックの処理理が問題 – どのエントリがオブジェクトを指して いるかがわからないといけない – スレッド停⽌止地点によっても変わる 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁51 Mark処理理とその注意点 class SayHello Thread stack JavaヒープGCルート M M M M M Mark処理 for (各GC Rootについて) GC Root内のオブジェクト参照の場所を「処理リスト」に足す while (処理リストに参照場所がある間) { 処理リストから参照場所を取り出す 参照先のオブジェクトがマーク済みなら次へ オブジェクトをマークする オブジェクト内の参照場所を処理リストに足す }
  52. 52. ©  2016  IBM  Corporation § スタックフレームのどこに「オブジェクトへの参照」が⼊入っているか? – インタープリタ実⾏行行の場合は,Javaスタックのどのエントリがオブ ジェクト参照であるかは(基本的に)わかるのでそれを使う – JITコンパイルされたメソッドを実⾏行行している場合,ネイティブス タックを使うので,簡単にわからないことがある. § さらに,CPUレジスタからオブジェクトを指している場合もある § スレッドを⼀一時停⽌止させる時,上の情報がわかるポイント (GC  Safe  Point)でのみ停⽌止させる – この時同時にCPUのレジスタの内容もメモリに書き出す – 停⽌止した場所(プログラムカウンタ)から,スタックフレームのど の場所にオブジェクト参照があるかの「マップ」を引き,マーク処 理理を⾏行行う § そのようなマップを⽤用意するのは処理理系(JITコンパイラ)の責任 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁52 スレッドスタックのスキャン main のスタック フレーム methodX のスタック フレーム methodY のスタック フレーム msg args tmp ret o obj arg ret a b tmp ret p i i ある時点での スタックの例
  53. 53. ©  2016  IBM  Corporation § GC  Safe  Pointの⽤用意 – 他のメソッドを呼び出す(新しいスタックフレームができる)地点は GC  Safe  Pointにしないといけない – ループしている部分は,その中にGC  Safe  Pointがないといけない § 通常,ループのバックエッジ部分をGC  Safe  Pointにする § GC  Safe  Pointでスレッドを停⽌止するには? – スレッド外から強制的に(pthread_killなどで)停⽌止させると,どこで停まるかわからない – 協調的なスレッド停⽌止機構が必要 § インタープリタやJITコンパイルされたコードは,GC  Safe  Pointの通過時にフラグを チェックして,停⽌止を要求されている場合は⾃自主的に停まる § この時同時にCPUのレジスタの内容もメモリに書き出し,動作再開時にCPUのレジス タに書き戻す 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁53 GC  Safe  Pointでのスレッド停⽌止
  54. 54. ©  2016  IBM  Corporation § GC  Safe  Pointやマップが作れない場合の⽅方法 – ⾔言語処理理系の「助け」が不不要なGC⼿手法 – オブジェクトぽい値はオブジェクトを指していると考えて保守的にマークする § 「オブジェクトぽい」とは? =値が,割り当て中のオブジェクトの(先頭)アドレスと⼀一致している § ヒープのアドレスや,各オブジェクトの先頭アドレスはわかるという前提 – 初期のJava処理理系はこれ(Conservative  GC)を使っていた § 逆に,型情報が完全にわかる最近のGCは「Type-­‐Accurate  GC」とも呼ばれる § 利利点: – GC  Safe  Pointやマップを⽤用意しなくてもマーク処理理が⾏行行える § ⽋欠点: – 不不要であるはずのオブジェクトまでマークしてしまう危険性がある – 特に,使い終わったローカル変数などを積極的にクリアする必要がある – 保守的にマークされたオブジェクトは動かすことができない 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁54 Conservative(保守的) Marking
  55. 55. ©  2016  IBM  Corporation § マークが付かなかったオブジェクトの領領域を フリーリストにつなぐ – 同時に,次のGCのためにマークをクリアする – 前後にフリー領領域がある場合は結合する(Coalescing) § マークをどこに置くか? ⽅方法1.  オブジェクトのヘッダに⼊入れる ⽅方法2.  別の場所にビット列列を⽤用意する § オブジェクトは8バイト単位でアラインされている ことなどを利利⽤用して圧縮可能 § ヒープ全体にアクセスが起こらないので,この⼿手法 が⼀一般的 § Sweep処理理を繰り返すうちに,フリー領領域が細切切れになっ てしまう危険性がある(Fragmentation) àオブジェクトをヒープ内で詰めなおして ⼤大きな連続フリー領領域を作るCompactionが必要 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁55 Sweep処理理とその注意点 Javaヒープ Sweep処理 for (割り当て中の各オブジェクト領域について) { if (マークが付いている) マークをクリアして次へ else { 領域をフリーリストにつなぐ(オブジェクトの回収) その際,前後にフリー領域がある場合は結合する } }
  56. 56. ©  2016  IBM  Corporation § そのオブジェクトを指している参照をすべて移動先に書き換える必要がある – Conservativeに指されているオブジェクトは動かせないので注意が必要 § 参照元が本当にそのオブジェクトを指しているのか,ただの数値なのか判別がつかな いため § Compactionの⼀一⼿手法(Forwarding  Pointer法) 1. まず,⽣生きているオブジェクトの「移動先」 を決め,各オブジェクトのForwarding  Pointer に記録 2. 参照を「移動先」に書き換える 3. ⽣生きているオブジェクトを移動先に移動する § 利利点:Fragmentationの解消,使⽤用ヒープエリアの縮⼩小 § ⽋欠点:複数回の追加ヒープスキャンが必要 – そのため,Compactionは毎回のGCでは⾏行行わないことが多い – スキャンの少ないReverse  Pointer法などもある 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁56 Compaction処理理とその注意点 Compaction処理(Forwarding Pointer法) for (生きている各オブジェクトについて) 移動先を決め,オブジェクトのForwarding Pointerに記録 for (GC Root内と生きている各オブジェクト内の参照について) 参照を「移動先」に書き換える for (生きている各オブジェクトについて) オブジェクトを移動先に移動する
  57. 57. ©  2016  IBM  Corporation § 多くのオブジェクトの寿命は短い – ⽣生成された後しばらく使われ, すぐに不不要になる à ヒープを「新世代オブジェクト⽤用の 領領域(nursery)」と「旧世代⽤用の領領域 (tenured)」に分ける – 新世代領領域はCopying  GC, 旧世代領領域はMark  &  Sweep  GC – Copying  GCを何回か⽣生き延びると,その オブジェクトは旧世代領領域に移される (Tenuring,殿堂⼊入り) § 旧世代から新世代を指す場合は, Remembered  Setに追加する § 利利点:GCによる停⽌止時間が短い(頻繁に⾏行行われる新世代領領域のGCについて) § ⽋欠点:Write  Barrier処理理(旧世代から新世代を指してないかのチェック) – スループットだけを考えるなら,単純なMark  &  Sweepの⽅方が⾼高い 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁57 その他のGC⼿手法:Generational  +  Copying  GC class SayHello Thread stack Javaヒープ(nursery1) GCルート Javaヒープ(tenured)Remem- bered Set Javaヒープ(nursery2)
  58. 58. ©  2016  IBM  Corporation § ヒープをたくさんの「リージョン」に分割して管理理 – 各リージョンを,nurseryやtenured領領域として割り当てることができる 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁58 その他のGC⼿手法:Region  Based  GC Javaヒープ 未使用 Nursery (新規割当用) Nursery (生き残った オブジェクト) Tenured Nursery (生き残った オブジェクト) Tenured (巨大なオブ ジェクト用) Tenured 未使用 Tenured 未使用 未使用 未使用
  59. 59. ©  2016  IBM  Corporation § 各オブジェクトについて,何箇所から指されているかのカウンタを管理理する – カウンタがゼロになったら回収する § オブジェクト参照を変更更する処理理で,カウンタのアップダウン処理理が必要 – たとえば,x.a =  y  という処理理では,オブジェクトyのカウンタを+1し,x.aが元々指していた オブジェクトzのカウンタを-­‐1する – zのカウンタが0になったら回収し,zが 指しているオブジェクトのカウンタも-­‐1 § 利利点:GCによる停⽌止時間がない – 死んだオブジェクトはすぐ回収可能 § ⽋欠点: – カウンタ操作が重い – すべてのオブジェクト書き込み ポイントにカウンタ処理理が必要 § 抜けがあるとヒープが壊れる – 循環参照が回収できない § そのため通常,Mark  &  Sweep と組み合わせて⽤用いられる 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁59 その他のGC⼿手法:Reference  Counting  GC class SayHello Thread stack Java heapGC Root 1 1 1 0 0 1 1 01 1 12
  60. 60. ©  2016  IBM  Corporation § Incremental  GC  (Concurrent  GC) – Mutator(アプリの動作)と並⾏行行して,少しずつMark処理理を⾏行行う – オブジェクトを3⾊色に塗る(Tri-­‐coloring) § ⽩白:まだチェックしていないオブジェクト § 灰:チェック途中のオブジェクト,⽩白を指してもよい § ⿊黒:チェック済みのオブジェクト,⽩白を指してはいけない – 基本動作 § まずすべてを⽩白にし,GCルートからたどれるものを灰⾊色にする § 灰⾊色の先を灰⾊色にする,全部灰⾊色になったらそのオブジェクトは⿊黒にできる ここの処理理を「少しずつ」⾏行行える § 灰⾊色がなくなったら,⽩白のままのオブジェクトを回収して終わり – ⿊黒から⽩白を参照するのを防ぐためにWrite  Barrierが必要 § それが起きたら⿊黒オブジェクト(か⽩白)を灰⾊色にする – 利利点:GCによる⼀一回の停⽌止時間を減らせる § Parallel   GC – GC処理理(MarkやSweep)を,複数スレッドを⽤用いて並列列に⾏行行う – 利利点:GC処理理の⾼高速化 … などなど 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁60 その他のGC⼿手法
  61. 61. ©  2016  IBM  Corporation § IBM  Java – Generational  +  Copying   +  Concurrent  +  Parallel  (default) – Parallel  Mark  &  Sweep (-­‐Xgcpolicy:optthruput) § HotSpot VM  /  OpenJDK – Parallel  +  Generational – “G1  Collector” § Region-­‐Based  GC 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁61 各⾔言語実装のGC § C++  (Boehm  GCライブラリ) – Conservative  Mark  &  Sweep § Ruby – Conservative  Mark  &  Sweep – “Restricted”  Generational  /   Incremental  GC § C-­‐Python – Reference  counting § PHP  (Zend) – Reference  counting § Swift – Reference  counting
  62. 62. ©  2016  IBM  Corporation GC関連の話題いろいろ 62 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁
  63. 63. ©  2016  IBM  Corporation § ⼀一般に,⾔言語がその⾔言語以外で書かれた(ネイティブな)処理理を実⾏行行できる場合,オブジェ クトを勝⼿手に操作されると正しいGCが困難になる – たとえば,ネイティブコードでオブジェクトを変更更するとWrite  Barrierの処理理が⾏行行えない – そもそも,ネイティブコードが使⽤用中のオブジェクトがわからないと回収してよいかも決 められない § Javaの場合,JNIインタフェースを使っていれば⼤大きな問題は⽣生じない – オブジェクトに対する操作は,すべてJNIインタフェースを通じて⾏行行われる § GetObjectField(env,  obj,  fid),SetObjectField(env,  obj,  fid,  obj)  など – オブジェクトのアドレスはネイティブコードには渡らない,「ハンドル」が渡される § そのようなオブジェクトは「表」に登録される,この表がGCルートとして扱われる – 配列列や⽂文字列列の⾼高速操作のために,アドレスを直接渡す場合だけ注意が必要 § GetPrimitiveArrayCritical(env,  array,  &isCopy)  は,Java配列列のアドレスをそのまま返せる が,ReleaseするまではGC  unsafeになる § JITコンパイルされたネイティブコードの扱い – JITコンパイラが,コンパイルしたコードにGC  Safe  Pointとマップを⽤用意する – 同時に,スレッドをGC  Safe  Pointで停⽌止させる仕組みも必要 § これらがない場合は,Conservative  GCになる 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁63 GC関連の話題:ネイティブコードへの対応
  64. 64. ©  2016  IBM  Corporation § JavaにはString.intern()という処理理があり,同じ内容の⽂文字列列を⼀一つのオブジェクトにまとめる ことができる(インターン処理理) – 特に,リテラル⽂文字列列("Hello"  のようにプログラム中に直接書かれている⽂文字列列)は, 使⽤用時に⾃自動的にインターンされる § インターンされた⽂文字列列オブジェクトは,処理理系内部の「Intern  Table」に登録されている – 同じ⽂文字列列に対してString.intern()が呼ばれた場合に,既存のインターン済みオブジェクト にまとめるため § Intern  TableはGCルートではないが・・・ – インターンされた⽂文字列列オブジェクトが回収される場合,Intern  Tableから削除する処理理を 忘れず⾏行行わなければならない 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁64 GC関連の話題:String  Intern  Tableへの対応
  65. 65. ©  2016  IBM  Corporation § Javaでは,オブジェクトが回収される時にfinalizeというメソッドを呼び出すことができる § GCではたとえば以下の処理理が必要 – Mark時に,finalizeメソッドを持つオブジェクトの先についてもMark処理理し, – Sweep時に,finalizeメソッドを持つオブジェクトは解放せず,「Finalizationキュー」につ なぐ § システム内の「Finalizerスレッド」が,キュー内のオブジェクトのfinalizeメソッドを順 に呼び出していく § finalize処理理により,オブジェクトが「⽣生き返る」こともある ※ finalizeメソッドが呼ばれるタイミングはすごく後になることもあるので, あまり使うべきではない(メモリリークの原因にもなりえる) 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁65 GC関連の話題:Finalizerへの対応
  66. 66. ©  2016  IBM  Corporation § Javaでは,オブジェクトを「弱く参照(Weak  Reference)」することができる – 弱参照しかされていないオブジェクトはGCの対象になる – WeakHashMapなどで利利⽤用 § キーを弱参照で保持,キーが回収されるとHashMapからも消される – 弱参照は,WeakReferenceという特別なオブジェクトを通じて⾏行行う § 弱参照先が回収されると,ReferenceQueueに⼊入れられる § GCでは,GC後にWeakReferenceオブジェクトだけを再チェックし, 弱参照先が回収されていたらキューにつなぐ,などの⽅方式で実装できる – もしくは,マークに「⾊色」をつける(StrongなマークとWeakなマーク)など 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁66 GC関連の話題:Weak  Referenceへの対応
  67. 67. ©  2016  IBM  Corporation § 特定の条件を満たすオブジェクトは,ヒープでなく スタック上に作ることも可能 – newしたメソッド内(以下)でしか使われない – 他のオブジェクトなどに代⼊入されない – これらの条件を満たすオブジェクトは メソッドから「Escapeしていない」と⾔言う § JITコンパイラが「Escape  Analysis」を⾏行行い, スタック上にオブジェクトを⽣生成するコードを出すことも可能 – スタックアロケートされたオブジェクトは,メソッド終了了時(スタックフレーム解放時) に⾃自動的に回収できる – ただしGC側でも,スタック上のオブジェクトを移動しないようにするなどの対応が必要 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁67 GC関連の話題:スタック上へのオブジェクト配置 String  concat(String  a,  String  b)  { StringBuilder  sb  =  new  StringBuilder();; sb.append(a);;  sb.append(b);; return  sb.toString();; } 上のStringBuilderオブジェクトはconcatメソッ ドからEscapeしていないので,(処理系がが んばれば)スタック上に配置することが可能
  68. 68. ©  2016  IBM  Corporation § Javaアプリの性能が出ない場合,GCログをチェックするのが分析の第⼀一歩 § GC頻発の様々な要因(oはGC発⽣生地点) 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁68 GCログからの問題分析 (a)  健全な状態 (b)  長期オブジェクトが多すぎる (c)  メモリー・リーク (d)  短期オブジェクトができすぎる GC後のヒープ使用量 時間経過 最大ヒープ・サイズ GC発生ポイント
  69. 69. ©  2016  IBM  Corporation § GCログを可視化し分析すると,たとえば以下のようなことがわかる – ヒープサイズは◯GBぐらい,Nurseryは◯GBぐらい – Minor  GCは◯秒に1回ぐらいのペースで起きている.つまり◯秒で◯GBぐらいアロケート している,毎分◯GBのペース – Minor  GCごとにちょっとずつオブジェクトがTenured領領域に逃げて⾏行行き,Major  GCを引き 起こしている – Major  GCが起きても回収できないものが少しずつ積みあがっていく(要するに何かがメモ リリークしている) – ヒープ使⽤用量量が少し下がるところ(最初以外)はcompactionが起きている,この compactionに◯秒ぐらいかかったあげく回収できるのがたった◯MBぐらい – Major  GCの頻度度はヒープが狭くなるとどんどん上がり,最終的には◯分に1回ぐらいに なっている 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁69 GCログからの問題分析:実例例
  70. 70. ©  2016  IBM  Corporation Java:  IBM  J9  Java  VM  6.0  SR7  32bit HW:  Dual-­‐core  Opteron  2.4GHz  x2,  4GB  Memory OS:  SUSE  Linux  Enterprise  Server  10.0 § Java処理理系は,ヒープ以外にも意外とメモリを消費している 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁70 メモリの話題:ヒープ以外のメモリ消費 [Ogata’10] 0 50 100 150 200 250MB Malloc-­then-­freed   area=37MB Non-­Java   memory   size  by   category M.M.  overhead=6MB DLL=8MB JVM  work  area=42MB Class  area=87MB JITed  code=10MB JIT  work  area=18  MB Stack=4MB Java  heap 253MB +
  71. 71. ©  2016  IBM  Corporation § Javaアプリでは,⽣生成されるオブジェクトの⼤大部分がStringオブジェクト – Stringオブジェクト内に,GCでは回収できないメモリの無駄がある § ライブヒープの40%は⽂文字列列保持のために⽤用いられているが,そのうち50%は無駄な領領域 – 25%  は重複した⽂文字列列 – 1%  はchar配列列内の使⽤用されない領領域 – 24%  は使⽤用されないリテラルデータ § これらはオブジェクト内の無駄なので従来のGCでは除去できない 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁71 メモリの話題:String⽤用メモリの無駄 [Kawachiya’08] 0 5 10 15 20 25 30 Trade6 MB dup unused literals String char[ ] other objects String memory inefficiencies (~20% of live heap) Live  heap   breakdown of  Trade6 Java:  IBM  J9  Java  VM  5.0  for  Linux App:  Trade6  benchmark  on  IBM  WAS  6.1 HW:  Xeon  3.06GHz  x2,  4GB  Memory OS:  Red  Hat  Enterprise  Linux  3  AS
  72. 72. スレッドと同期
  73. 73. ©  2016  IBM  Corporation § Javaは,⾔言語⾃自体がスレッドによる並列列処理理を サポートしている § Java処理理系には,スレッド管理理のための仕組み に加え,スレッド間の排他制御を⾏行行うための 同期機構が必要 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁73 スレッドと同期 クラス管理 オブジェクト 管理 インタープリタ JIT コンパイラ JITコンパイラ 生成コード 実行時 プロファイラ クラスデータ (Java  バイト コード) Javaヒープ (Java  オブ ジェクト) Javaスタック (ローカル変数, オペランドスタック) Java仮想マシン(Java  VM) Java同期 ランタイム Java例外処理 ランタイム JVM ランタイム
  74. 74. ©  2016  IBM  Corporation § Javaは⾔言語としてスレッドによる並列列処理理をサポートしている – java.lang.Thread – スレッドを作成する標準クラス – java.lang.Runnable – スレッドの処理理内容を記述するインタフェース § 商⽤用Java処理理系では,JavaスレッドはOSが提供するスレッド(たとえばpthread) にマッピングされ,OS⾃自⾝身によってスケジュールされることが多い – ネイティブメソッドからCコードやシステムコールを呼ぶ場合の親和性のため 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁74 スレッド処理理 class  MyRunnable implements  Runnable  { static  MyCounter c  =  new  MyCounter();; public  void  run()  { System.out.println("Hello  "  +  c.add(1));; } } Thread  t  =  new  Thread(new  MyRunnable());; t.start();;  // スレッドを実行開始 Java  thread JVM  thread (C/C++) pthread
  75. 75. ©  2016  IBM  Corporation Javaは,⾔言語⾃自体がスレッドによる並列列処理理をサポートしている § スレッド間の同期はsynchronizedメソッドなどで指定される § モニタ⽅方式の排他制御 – たかだか1つのスレッドだけが当該オブジェクトのsynchronizedメソッドを実⾏行行できる – オブジェクトのロックが実⾏行行前に獲得され,実⾏行行後に解放される – ロックの再帰獲得や,イベント待ち合わせ(wait)と通知(notify)も可能 § Javaでは,以下の理理由によりロック処理理が頻繁に⾏行行われる – ライブラリは「スレッドセーフ」に作らなければならない – プログラマが容易易にロック処理理を指定できる (「synchronized」をつけるだけ) 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁75 Javaロック:スレッド間の同期機構 class  MyCounter { int value  =  0;; synchronized int add(int i)  { value  =  value  +  i;; return  value;; }      } MyCounter c1 add(1) add(1) add(1) value:10 MyCounter c2 value:5 Thread A Thread B Thread C
  76. 76. ©  2016  IBM  Corporation § 背景:Java⾔言語の浸透 – 現在ではC,C++とならぶポピュラーな⾔言語 – サーバー環境では,ウェブサービス構築の必須⾔言語 – クライアント環境でも,Eclipseなどで不不可⽋欠 § 初期のJava⾔言語は処理理が⾮非常に遅かった・・・ – 機種独⽴立立なバイトコードを,Java仮想マシン(JVM)が実⾏行行する形式 à JITコンパイル技術の進歩により改善 – ランタイムシステムのオーバーヘッド à こちらは,JITによる⾼高速化が難しい § 初期の処理理系では,実⾏行行時間の2割近くを スレッド同期(ロック処理理)が占めていた à Javaアプリケーションの⾼高速実⾏行行に, ロック処理理の⾼高速化は不不可⽋欠 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁76 Javaロック⾼高速化の必要性 From  http://www.javaworld.com/jw-­03-­1998/jw-­03-­hotspot.html
  77. 77. ©  2016  IBM  Corporation § Javaでは,ロックはオブジェクトを指定して⾏行行われる à 各オブジェクトヘッダにモニタ構造体を⽤用意する § 当然のことながら,メモリ使⽤用効率率率が悪い 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁77 Javaロックの超ナイーブな実装 Object 1 Header Body Monitor structure Object 2 Header Body Monitor structure Object 3 Header Body Monitor structure Object 4 Header Body Monitor structure Object 5 Header Body Monitor structure typedef struct object  { monitor_tmon;;   : }  Object;; int Java_lock_acquire(Object  *obj) {  return  monitor_enter(&obj-­>mon);;  } int Java_lock_release(Object  *obj) {  return  monitor_exit(&obj-­>mon);;  } int Java_lock_wait(Object  *obj) {  return  monitor_wait(&obj-­>mon);;  } int Java_lock_notify(Object  *obj) {  return  monitor_notify(&obj-­>mon);;  } int Java_lock_notify_all(Object  *obj){  return  monitor_notify_all(&obj-­>mon);;  } Javaロックの実装とは, これらのデータ構造と 関数を用意すること
  78. 78. ©  2016  IBM  Corporation § 実際には,⼀一部のオブジェクト(せいぜい1割)しかロック処理理に⽤用いられないことを利利⽤用 à オブジェクトとモニタ構造体の関連付けをグローバルな表で管理理 § メモリ使⽤用効率率率は改善されたが, モニタ表の更更新・参照のためにグローバルロックが必要,スケーラビリティ低下 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁78 「モニタ表」を⽤用いたJavaロック実装 Object 1 Header Body Monitor table Object 2 Header Body Monitor structure Object 3 Header Body(no field for lock) Object 4 Header Body Object 5 Object 3 Monitor structure Object 5 Header Body Object 2 Monitor structure int Java_lock_acquire(Object  *obj)  { monitor_t*mon  =  lookup_monitor(obj);; return  monitor_enter(mon);; } int Java_lock_release(Object  *obj)  { monitor_t*mon  =  lookup_monitor(obj);; return  monitor_exit(mon);; }
  79. 79. ©  2016  IBM  Corporation § オブジェクトヘッダ内の,あまり使⽤用されないフィールドの利利⽤用 à ロックに使⽤用された場合,そのフィールドから直接モニタ構造体を指す § 元々あったデータは,モニタ構造体の中に移動する § スケーラビリティは改善されたが, OSのモニタ機構をそのまま使っているため,依然として⾼高オーバーヘッド 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁79 Direct  Pointing⽅方式 [Onodera’98] Object 2 Header Body Object 4 Header Body rarely-used info 0 Object 1 Header Body rarely-used info 0 Monitor structure Object 3 Header Body 1 rarely-used info Monitor structure rarely-used info OBJFLAG_MON _ASSOCIATED Displaced info Object 5 Header Body 1 rarely-used info Monitor structure 1
  80. 80. ©  2016  IBM  Corporation § Javaでは,多くのロックは衝突(contention)していないことを発⾒見見し活⽤用 à オブジェクトヘッダ内のロックワードを2つのモードで使⽤用する,bi-­‐modalロック § ロックが衝突するまでは,compare_and_swapでロック処理理を⾏行行う(Flatモード) § ロック衝突時にモニタ構造体を⽤用意し,以後はそれで処理理を⾏行行う(Inflatedモード) – 2つのモードは,ロックワード内のShapeビットにより区別される § 多くのロック処理理で重いモニタ機構が不不要になり, Javaアプリケーションの処理理性能が劇的に向上(元論論⽂文によれば「最⼤大1.7倍」) 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁80 Thinロック [Bacon’98  (Best  of  PLDI)] Object 2 Header Body Object 3 Header Body Object 4 Header Body Object 1 Header Body Lockword 0 1 0 0 T 0 0 Monitor structure Shape bit Object 5 Header Body 1 Monitor structure int Java_lock_acquire(Object  *obj)  { if  (compare_and_swap(&obj-­>lockword,   0,  thread_id())  ==  SUCCESS) return  SUCCESS;; :
  81. 81. ©  2016  IBM  Corporation Javaロックのさらなる⾼高速化 81 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁
  82. 82. ©  2016  IBM  Corporation § Thinロックにおけるロックワードの状態遷移 – compare_and_swap命令令1つでロック獲得,単純なストア命令令でロック解放が可能 § モード遷移に関する2つの(潜在的な)問題 – インフレーション(FlatモードからInflatedモードへの遷移)にビジーウェイトを使⽤用 – デフレーションが無い.⼀一旦衝突が起きたロックは,以後Inflatedモードで処理理される 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁82 Thinロックの(潜在的な)問題点 Object 1 Header Body Lockword 0 0 T0 1 00 releaseacquire Shape bit Monitor structure inflate Flat mode (Shape bit=0) Inflated mode (Shape bit=1) Object creation (pointer) Acquired by T Not acquired acquire / release
  83. 83. ©  2016  IBM  Corporation § 各オブジェクトのロック衝突状況を,以下の指標を⽤用いて調査する – Flatセクション―  ロックが衝突していない状態 – Fatセクション ―  ロック獲得(もしくはイベント通知)を待っているスレッドがいる状態 § 結果:イベント待ち合わせに使われていないオブジェクトでは,衝突は⼀一時的な現象である – Javaロックの「衝突の⼀一時性」,要するにObject  3のようなケースが多い 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁83 Javaロックの衝突に関する挙動調査 Created Garbage collected Object 1 Created Garbage collected Object 2 Created Garbage collected Object 3 Flatセクション(ロックが衝突していない) Fatセクション (ロック獲得またはイベント通知を待っているスレッドがいる) Time
  84. 84. ©  2016  IBM  Corporation § たすきロックにおけるロックワードの状態遷移 § デフレーションのサポート( 「衝突の⼀一時性」の活⽤用) – 衝突が解消すると,ロックワードをFlatモードに戻す § インフレーション制御のために,オブジェクトヘッダに1ビットのフラグを追加 – FLC(Flat  Lock  Contention)ビット ―  Flatモードでのロック衝突を⽰示す – ビジーウェイトを排除 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁84 たすきロック [Onodera’99] T0 1 00 releaseacquire Shape bit Monitor structure Flat mode (Shape bit=0) Inflated mode (Shape bit=1) Object creation (pointer) Acquired by T Not acquired acquire / release deflate & release inflate Object Body Shape bit FLC bit Header 0 T 0
  85. 85. ©  2016  IBM  Corporation 1 2 3 4 5 6 7 8 9 10 # Terminals 0 5 10 15 Throughput (x1000 tpm) IBM116 Ours +11.4% +8.29% +13.1% +8.27% § Ibenchベンチマーク – トランザクション処理理をエミュレート,ターミナル数 m  を変えて測定する § たすきロックにより最⼤大13.1%の性能向上を確認 – さらに,マルチスレッド環境での性能低下を抑制 – ロック処理理の98%以上がFlatモードで⾏行行えている(Thinロックでは74%) Thin  lock Tasuki 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁85 実アプリでの性能⽐比較 遅い←                                →  速い IBM  JDK  1.1.6(Thinロックが採 用されている)に,たすきロックを 実装して測定した結果 たすきロック Thinロック Java  IBM  JDK  1.1.6 App:  Ibench benchmark HW:  PowerPC  604ev  166MHz,  128MB  Memory OS:  AIX  4.1.5
  86. 86. ©  2016  IBM  Corporation § たすきロックにより,衝突がない状況ではわずか数命令令でロック処理理が可能になった § しかし,compare_and_swapなどの不不可分命令令が依然として必要 – 他者のJavaロック⼿手法でも同様の状況 – 不不可分命令令は⾮非常に重い命令令である à ロックのfastest  pathから,不不可分命令令をなくせないか? § たとえば・・・ オブジェクトが特定のスレッドによってのみ頻繁にロックされているなら, そのスレッドのロック処理理に限り不不可分命令令を無くせないか? ―  Javaロックの「スレッド局所性」 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁86 さらなる⾼高速化の可能性は? オブジェクト ヘッダ部 ボディ部 0 tid rcnt ロックワード compare_and_swapで スレッドIDを書き込む ことで,ロックを獲得 生成 消滅C C C C C BC CC スレッドCがロック スレッドCが頻繁にロックしている オブジェ クト
  87. 87. ©  2016  IBM  Corporation § Javaロックの「スレッド局所性」を活⽤用 – オブジェクトを最初にロックしたスレッドが,ロックを「予約」できる à そのスレッドが引き続きロックを⾏行行った場合のコストを下げられる § 予約ロックにおけるロック獲得処理理 1. そのスレッドが予約を持っていた場合,不不可分命令令なしの⾼高速処理理を⾏行行う 2. 他のスレッドが予約を持っていた場合,まずその予約を「解除」する 3. 予約がすでに解除されていた場合,従来の⽅方式(たとえば たすきロック)で処理理を⾏行行う 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁87 予約ロック [Kawachiya’02] 1. この部分が高速化される 生成 消滅 オブジェ クト C C C C C BC CC 0. スレッドCに予約が与えられる 2. 予約が解除される 3. この部分は従来方式で処理される
  88. 88. ©  2016  IBM  Corporation 1T 0 Reserved for Thread T 0 0 Anonymously reserved Acquired by T unreserve acquire release acquire release 1 Object creation 1T 1 1T 2 unreserve unreserve 0 0 0 : : Base lock algorithm Recursively acquired : : Reserve mode (LRV=1) Base mode (LRV=0) xxxxxx yyyyyy zzzzzz acquire (initial synchronization) LRV bit § ロックワードの状態遷移 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁88 予約ロックの動作 tid rcnt LRVビット 1 再帰カウンタ スレッドID § 予約スレッドは,rcntフィー ルドを単純に増減することで ロックの獲得と解放が⾏行行える (不不可分命令令は不不要) § 別のスレッドがロック獲得 を試みた時点で,予約は 「解除」される § 解除後は,従来⼿手法により 処理理が⾏行行われる – 複雑なケースはすべて 従来⼿手法に任せられる
  89. 89. ©  2016  IBM  Corporation § 予約ロックでは,予約解除のコストが⾼高かった – 予約を保持しているスレッドを外部から強制停⽌止させる必要があるため – さらに,停⽌止した地点がロック処理理中(unsafe  region)であった場合,再開地点を移動す る必要もあった à 協調的スレッドスケジューリングを利利⽤用した改善 – スレッドを「GC  Safe  Point」で停⽌止させる仕組みを,予約解除時のスレッド停⽌止にも利利⽤用 メリット1. 予約解除の際の予約スレッド停⽌止にシステムコールが不不要であるため軽い メリット2. unsafe  regionで停⽌止することがないので停⽌止後コンテクストをチェックする 必要がない メリット3. 予約解除のコストが低いので,予約解除の頻度度等に応じて再予約も⾏行行える メリット4. synchronizedセクション内にGC  safe  pointがない場合は,予約時のロック処理理 から再帰カウンタの上げ下げすら省省略略できる § IBM  Javaでは,-­‐XlockReservation オプションで使⽤用可能 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁89 改良良版予約ロック [Grcevski’07]
  90. 90. ©  2016  IBM  Corporation § Apache  Sparkでの性能改善 – TPC-­‐Hを実⾏行行した場合,22のうち7つのQueryで10%以上の改善(最⼤大18%) 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁90 予約ロック(改良良版)の効果 出典: http://www.spark.tc/reserve-­locks-­spark-­performance Java:  IBM  J9  Java  VM  Version  8  SR1  FP10 App:  TPC-­‐H  with  Spark  SQL  on  Spark  1.4.1,  with  100GB  dataset HW:  POWER8  3.3GHz  x2  (total  24cores),  1TB  Memory OS:  Ubuntu  Linux  14.10
  91. 91. ©  2016  IBM  Corporation § Escape Analysisの活⽤用 [Whaley’99など] – あるスレッドで⽣生成したオブジェクトが,そのスレッド以外には⾒見見えないことを解析する – Escapeしていないオブジェクトは,スタック上に配置したり,ロック処理理を省省略略できる § Transactional  Memory的⼿手法の活⽤用 [Nakaike’10][Odaira’14] – スレッドは全員synchronizedセクションを投機的に実⾏行行できる – synchronizedセクションを抜けるときに,変更更内容をメモリに書き戻す § ただし,競合があった場合はやりなおしになる § いずれも,JITコンパイラなどによるコード解析が必要 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁91 その他の改善⼿手法:ロック除去
  92. 92. 例例外処理理
  93. 93. ©  2016  IBM  Corporation § 例例外の処理理 § 例例外処理理のコスト 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁93 例例外処理理 クラス管理 オブジェクト 管理 インタープリタ JIT コンパイラ JITコンパイラ 生成コード 実行時 プロファイラ クラスデータ (Java  バイト コード) Javaヒープ (Java  オブ ジェクト) Javaスタック (ローカル変数, オペランドスタック) Java仮想マシン(Java  VM) Java同期 ランタイム Java例外処理 ランタイム JVM ランタイム
  94. 94. ©  2016  IBM  Corporation § try-­‐catch – tryブロックのコード範囲でthrowされた例例外に対し,catchブロック(例例外ハンドラ)を 定義する構⽂文 – 各catchブロックは、指定する例例外クラス(およびその⼦子クラス)の例例外を処理理する – finallyは,tryブロックの終了了時に必ず実⾏行行される 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁94 例例外の基本動作 try { canThrowE1();;  //  例外E1を投げるかもしれないメソッド }  catch (E1  e)  { //  例外E1が起きた時のハンドラ }  catch (E2  e)  { //  例外E2が起きた時のハンドラ }  finally { //  tryブロック終了時に(例外の有無にかかわらず)実行するコード }
  95. 95. ©  2016  IBM  Corporation § バイトコードに「例例外表」がついている – 「 [0,3)の範囲で例例外E1が起きた場合, 6へ⾶飛ぶ 」 à § 例例外が発⽣生すると, – 例例外表をチェックし,ハンドラがあればそこへジャンプ – ハンドラがなければ,スタックを⼀一段巻き戻し,同様の処理理を⾏行行う § synchronizedブロックでロックを取得している場合,javacがfinally節相当のエントリを⽣生成し その中でアンロック(monitorexit)処理理を⾏行行うので,ランタイムでは特別な対処は不不要 – synchronizedメソッドの場合は,スタック巻き戻し時にランタイムがアンロックを⾏行行う 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁95 例例外の処理理 try { canThrowE1();; }  catch (E1  e)  { //例外E1が起きた時のハンドラ } Code: 0:  invokestatic #4  //  Method  canThrowE1 3:  goto 7 6:  astore_0 7:  return Exception  table: from        to    target   type 0          3          6       Class  E1
  96. 96. ©  2016  IBM  Corporation § 例例外表を内側からチェックする 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁96 ネストしたtry-­‐catch try  { m1();; try  { m2();; try  { m3();; }  catch  (E3  e)  { _m3();; } }  catch  (E2  e)  { _m2();; } }  catch  (E1  e)  { _m1();; } Exception  table: from        to    target type 6          9       12 Class  E3 3        16        19 Class  E2 0        23        26 Class  E1
  97. 97. ©  2016  IBM  Corporation 1. 例例外オブジェクトのnew 2. 例例外オブジェクトの<init>の呼出し – コールスタックの記録オブジェクトのnew – コールスタックのトレース 3. 例例外をthrow 4. 例例外ハンドラのサーチ – コールスタックの巻き戻し – 各フレームから例例外表を取得 – 例例外表で,プログラムカウンタに該当するtryを識識別 – tryにひもづいた例例外ハンドラの各候補に対し、現在の例例外クラスを扱えるかテスト (instanceofと同等の処理理) 5. 例例外ハンドラから実⾏行行を再開 à改善策:プロファイリングでthrowとcatchのペアを⾒見見つけ, JITコンパイル時に処理理してしまう [Ogasawara’01] 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁97 例例外処理理のコストと改良良
  98. 98. JITコンパイラ
  99. 99. ©  2016  IBM  Corporation § バイトコードを実⾏行行時(Just-­‐In-­‐Time)にコン パイルし,⾼高速実⾏行行する – 実⾏行行時プロファイラを⽤用いて,JITコンパイ ラによる最適化に有益な情報を収集するこ とも可能 § インタープリタの役割 – どのメソッドをJITをコンパイルするか決定 – JIT前にシンボルの解決(Resolve)などを なるべく済ませる – プロファイリング,統計情報収集など § 詳細はこの次の講演にて 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁99 JITコンパイラ(さわりだけ) クラス管理 オブジェクト 管理 インタープリタ JIT コンパイラ JITコンパイラ 生成コード 実行時 プロファイラ クラスデータ (Java  バイト コード) Javaヒープ (Java  オブ ジェクト) Javaスタック (ローカル変数, オペランドスタック) Java仮想マシン(Java  VM) Java同期 ランタイム Java例外処理 ランタイム JVM ランタイム
  100. 100. ©  2016  IBM  Corporation § Javaバイトコードが実⾏行行される時に,そのバイトコードをコンパイルするコンパイラ – ⼀一般的には,メソッド単位(+インライニング)でコンパイルを⾏行行う 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁100 Java  Just-­‐in-­‐Time  (JIT)コンパイラ public  class  Hello  { public  static  void  main(String[]  args)  { System.out.println("Hello");; … Hello.java (ソースコード) public  static  void  main(java.lang.String[]);; Code: 0:  getstatic 3:  ldc … Hello.class (バイトコード) javac Hello.java(実⾏行行前に⾏行行う) main: ld st … ネイティブコード (マシンコード) JITコンパイル(実⾏行行中に⾏行行う) これはJITでは ないので注意 Java仮想マシン の守備範囲
  101. 101. ©  2016  IBM  Corporation § バイトコードのポータビリティ(Write  Once  Run  Anywhere)維持のため – 実⾏行行時に各プラットフォーム向けのバイナリを⽣生成 § 実⾏行行時(プロファイル)情報を最適化に使うため – メソッドの呼び出し頻度度等 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁101 なぜJIT(実⾏行行中に)コンパイルするのか? public  class  A  { public  void foo()  {…} } public  class  B  extends  A  { public  void  foo()  {…} } public  class  C  extends  A  { public  void  foo()  {…} } public  void  bar  (A  a)  { … a.foo();; … } クラスA,  B,  Cの3つのfooメソッドが呼び 出される可能性があるが,頻繁に呼び出 されるメソッドをインラインしたい
  102. 102. ©  2016  IBM  Corporation JITコンパイルの⼿手順 102 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁 public void foo() Code: 0: getstatic 3: ldc … public void bar() Code: 0: getstatic 3: ldc … public void zoo() Code: 0: getstatic 3: ldc … インタープリタ 1.  最初はバイトコードをインタープリタ実⾏行行 JITコンパイラ foo: ld st … bar: ld st … zoo: ld st … 2.  呼び出し回数が閾値を越えたメソッド に対してJITコンパイルリクエスト 3.  バイナリコードを⽣生成しプロセッサ上で直接実⾏行行
  103. 103. ©  2016  IBM  Corporation § 各メソッドの性能に与える影響(=全実⾏行行時間に占める割合,method  hotness)に応じて 最適化レベルを変更更 – よく使われるメソッドは,より時間をかけて⾼高度度に最適化する 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁103 適応的コンパイル(Adaptive  Compilation) インタープリタ実行 低最適化レベルでのコンパイル 実行時間のプロファイル 高最適化レベルでのコンパイル § IBM  Java  JITコンパイラは6段の最適化 レベルを使⽤用 scorching veryHot hot warm  (最初の最適化レベル) cold noOpt 高 低
  104. 104. ©  2016  IBM  Corporation § メソッドを定期的にサンプリング – サンプリングスレッドが定期的にアプリケーションスレッドの「フラグ」をセット – アプリケーションスレッドは,フラグがセットされたときに実⾏行行していたメソッドを サンプリング § フラグチェックは,GC  Safe  Pointで⾏行行う – メソッドの⼊入り⼝口,メソッドの出⼝口,ループの最後など – もともとGCのために⽤用意されているため,オーバヘッドにならない 2016/09/06 Java仮想マシンの実装技術 / 河内⾕谷清久仁104 メソッドの実⾏行行時間のプロファイル サンプリングスレッド サンプリングインターバル(e.g.  10ms) アプリケーションスレッド1 アプリケーションスレッド2 フラグセット メソッドAを実行 samples(A)++ メソッドBを実行 samples(B)++ public  void  foo()  { check();; for  (…)  { s  +=  a[i];; check();; } check();; }
  105. 105. まとめ

×