[Java][イベント]JVM勉強会に行ってきました
ふむ、jojo勉強会以来…? あれ、java-ja温泉の事って書いてなかったっけか。書いてなかったのか……。
というわけで行ってまいりましたJVM勉強会。
VMの中の人まで意識した設計をしたことがなく、ClassLoaderをサンプルでちょこちょこって動かした程度のレベルですが。
参考資料
とりあえず、会場で持ってる人が割といた、もしくは発表内で話題にあがった本など。
- Java仮想マシン仕様
- ガベージコレクションのアルゴリズムと実装
- デコンパイリングJava
この辺りを読んでくると、より内容を楽しめた模様。
本編
- @ashigeruさん クラスローダについて
- クラスローダはfindClass()をオーバライドする
- loadClass()を実行すると委譲先クラスを探しにいく。親から見ていって、なかったら自分でロード
- 親から見ていくので、親が古いライブラリを持っているとそれをロードしてしまう!
- 某アプリケーションサーバは親を最後に検索する = PARENT_LAST
- その名のとおり自分のクラスローダを最初に検索するので、親のライブラリの影響を受けにくい
- 同じ名前のクラスでも定義ローダーが違えば別のもの。Class.getClassLoader()でどこから呼ばれたか確認できる。
- PARENT_LASTの問題点としてドッペルゲンガーという現象。などなど……
- @skrbさん Stack on JavaVM
- JVMとスタックについて
- スタックを使用した逆ポーランド法のアニメーション(わかりやすい!)
- JVMはスタック
- スタックはThreadひとつにつきひとつ
- 中にはプログラムカウンタがひとつ
- フレームの中にはローカル変数とオペランドスタック
- JVMの中ではBooleanはIntとして扱われている
- インスタンスはヒープにアロケーションされる
- スタックは二段構え(JavaStackとオペランドスタック)
- @kmizuさん わかる!Javaバイトコード-30分でわからない?Javaバイトコード入門
- Hello Worldの逆アセンブル
- byte,short,char,boolean -> すべてintとして扱われる
- ロード/ストア命令…定数をオペランドスタックにロードする命令
- ロード/ストア命令2…ローカル変数の値をオペランドスタックにロードする命令
- 型変換命令…キャストなどint ->longなど
- 配列関係の命令
- オブジェクトの生成・操作命令
- モニタ命令
- クラスファイルベリファイア
- classファイルのフォーマットがJava仮想マシン仕様に従っているかどうかを該当クラスの初期化より前にチェックする。未初期化ローカル変数へのアクセス、型エラー、jasmin……この辺よくわかりませんした><
- @cactusmanさん GCについて
- GC
- ルートを起点として参照できるオブジェクトは生きている
- ルートに到達できないものがGCされる
- GCを学ぶ意義としてメモリ領域の効率的な使い方を意識できる
- マーク&スイープ
- ルートオブジェクトからたどれるオブジェクトをマークしていく
- マークのないオブジェクトを回収
- メリット:実装は簡単
- デメリット:フラグメンテーション、アロケーション速度、停止時間が長い→マークしている期間
- 参照カウント
- 自信のオブジェクトが参照されているオブジェクトをカウント
- 0になった時点でGC
- メリット:参照が停止されたタイミングで開放、停止時間が短い、参照をたどる必要がない
- デメリット:循環参照を回収できない、カウンターの値の増減処理が重い、実装が難しい
- コピー
- メリット:スループットがいい、メモリ回収と同時にコンパクションを行える(フラグメンテーションが起きない)
- デメリット:ヒープ領域を余分に取る
- GCの種類 ScavengeGC - コピーGC
- GC
- @nekopさん クラスローダリークパターン なにそれおいしいの?
- ThreadLocalで設定した値はThreadから強参照される
- java.util.loggingのLevelを継承でリーク
- 既製ライブラリ commons-logging
- 日本オラクルたてのさん なれる!CL 5分間で分かる? (OC4J)クラスローダ入門
- OC4Jのおはなし。
- 人間クラスローダ養成講座 <- なにこれすごい受けたい!
- クラスローダは親子モデル、親からロードし子は最後。
- 基本は1JavaVM1アプリ1ライフサイクルなのだが、現在は多くのアプリ・多くのライブラリが乗っているので、依存やバージョン競合が起こりそう。
- 親子関係では足りなくなるのでloadClassの上書きという修羅の道を通った人もいる。
- ポリシーを組み合わせる -> テンプレートで設定。
- OC4JはWebLogicServerへ…そして伝説へ…
GCの仕組みなど普段は中の人にやってもらっていたところが、どんな仕組みになっていたのかなんとなくイメージできたかな…。
@skrbさんの逆ポーランド方を図示したスライドは超わかりやすかった! 逆ポーランドとスタックは絡めて説明すると感覚的にすごく頭に入ってきやすいと思いました。
最後に、主催者の@yuroyoroさん、二次会を取りまとめてくださった@yamashiroさん、会場を提供してくださった日本Oracle社さんに感謝。
最後の最後に
Hello Worldをjavapしてみましょう。
public class HelloClassLoader {
public static void main(String args[]) {
System.out.println("HelloWorld !!");
}
}
MacBook:java kk_Ataka$ javap -c HelloClassLoader
Compiled from "HelloClassLoader.java"
public class HelloClassLoader extends java.lang.Object{
public HelloClassLoader();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #3; //String HelloWorld !!
5: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
}