上記のとおりです。
ツイートが下記の通りまとめられています。
そのうちさくらばさんが資料をあげてくれると思います。
【2015/04/25 22:41 追記】さくらばさんが公開してくれました
JVM編の資料
www.slideshare.net
GC編の資料
www.slideshare.net
前半 JVMの話
javapを使ったことのある人が意外と少なかったです。まあ普段使うことないですね。
僕はバイトコード、バイトコード言ってるけど実際どうなってるのという興味程度でつかったことがある程度です。
ちょうど家に帰ってから、また試しにやってみました。
public class Sample { private final int number; public Sample(int number) { this.number = number; } public int add(int other) { int result = number + other; return result; } public void print(String prefix) { System.out.println(prefix + number); } }
このコードをjavac
して、できたクラスファイルをjavap -c -l -v Sample.class
とやるとこんなのが表示されます。
Classfile /C:/Users/mike/groovy/java/ReturnSample/Sample.class Last modified 2015/04/24; size 696 bytes MD5 checksum bfa4961178d1d535c570a22e45c348c8 Compiled from "Sample.java" public class Sample SourceFile: "Sample.java" minor version: 0 major version: 52 flags: ACC_PUBLIC, ACC_SUPER Constant pool: #1 = Methodref #11.#24 // java/lang/Object."<init>":()V #2 = Fieldref #10.#25 // Sample.number:I #3 = Fieldref #26.#27 // java/lang/System.out:Ljava/io/PrintStream; #4 = Class #28 // java/lang/StringBuilder #5 = Methodref #4.#24 // java/lang/StringBuilder."<init>":()V #6 = Methodref #4.#29 // java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; #7 = Methodref #4.#30 // java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder; #8 = Methodref #4.#31 // java/lang/StringBuilder.toString:()Ljava/lang/String; #9 = Methodref #32.#33 // java/io/PrintStream.println:(Ljava/lang/String;)V #10 = Class #34 // Sample #11 = Class #35 // java/lang/Object #12 = Utf8 number #13 = Utf8 I #14 = Utf8 <init> #15 = Utf8 (I)V #16 = Utf8 Code #17 = Utf8 LineNumberTable #18 = Utf8 add #19 = Utf8 (I)I #20 = Utf8 print #21 = Utf8 (Ljava/lang/String;)V #22 = Utf8 SourceFile #23 = Utf8 Sample.java #24 = NameAndType #14:#36 // "<init>":()V #25 = NameAndType #12:#13 // number:I #26 = Class #37 // java/lang/System #27 = NameAndType #38:#39 // out:Ljava/io/PrintStream; #28 = Utf8 java/lang/StringBuilder #29 = NameAndType #40:#41 // append:(Ljava/lang/String;)Ljava/lang/StringBuilder; #30 = NameAndType #40:#42 // append:(I)Ljava/lang/StringBuilder; #31 = NameAndType #43:#44 // toString:()Ljava/lang/String; #32 = Class #45 // java/io/PrintStream #33 = NameAndType #46:#21 // println:(Ljava/lang/String;)V #34 = Utf8 Sample #35 = Utf8 java/lang/Object #36 = Utf8 ()V #37 = Utf8 java/lang/System #38 = Utf8 out #39 = Utf8 Ljava/io/PrintStream; #40 = Utf8 append #41 = Utf8 (Ljava/lang/String;)Ljava/lang/StringBuilder; #42 = Utf8 (I)Ljava/lang/StringBuilder; #43 = Utf8 toString #44 = Utf8 ()Ljava/lang/String; #45 = Utf8 java/io/PrintStream #46 = Utf8 println { private final int number; descriptor: I flags: ACC_PRIVATE, ACC_FINAL public Sample(int); descriptor: (I)V flags: ACC_PUBLIC Code: stack=2, locals=2, args_size=2 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: aload_0 5: iload_1 6: putfield #2 // Field number:I 9: return LineNumberTable: line 3: 0 line 4: 4 line 5: 9 public int add(int); descriptor: (I)I flags: ACC_PUBLIC Code: stack=2, locals=3, args_size=2 0: aload_0 1: getfield #2 // Field number:I 4: iload_1 5: iadd 6: istore_2 7: iload_2 8: ireturn LineNumberTable: line 7: 0 line 8: 7 public void print(java.lang.String); descriptor: (Ljava/lang/String;)V flags: ACC_PUBLIC Code: stack=3, locals=2, args_size=2 0: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream; 3: new #4 // class java/lang/StringBuilder 6: dup 7: invokespecial #5 // Method java/lang/StringBuilder."<init>":()V 10: aload_1 11: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 14: aload_0 15: getfield #2 // Field number:I 18: invokevirtual #7 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder; 21: invokevirtual #8 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 24: invokevirtual #9 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 27: return LineNumberTable: line 11: 0 line 12: 27 }
あとは、これをThe Java Virtual Machine Specification, Java SE 8 Editionと照らしあわせて読んでいくだけです。
iload_1
とかの1
は引数、aloat_0
はthis
のロードなどを表します。
では、まず簡単なadd
メソッドに注目すると…
public int add(int); descriptor: (I)I flags: ACC_PUBLIC Code: stack=2, locals=3, args_size=2 0: aload_0 1: getfield #2 // Field number:I 4: iload_1 5: iadd 6: istore_2 7: iload_2 8: ireturn LineNumberTable: line 7: 0 line 8: 7
最初のaload_0
でスタックは次のようになります。
stack |
---|
this |
次のgetfield #2
でスタックは次のようになります。
stack |
---|
this.number |
次のiload_1
でスタックは次のようになります。
stack |
---|
int(argument) |
this.number |
次のiadd
でスタックは次のようになります。
stack |
---|
result(this.number + argument) |
次のistore_2
でスタックからlocal variableの2番地に値が移されます。
次のiload_2
でlocal variableの2番地のデータがスタックに戻されます。
stack |
---|
result(this.number + argument) |
最後のireturn
でスタックの値が呼び出し元に返されます。
もちろん、これ僕の雑な理解なので、マサカリ大歓迎です。
javapをすると自然とThe Java Virtual Machine Specification, Java SE 8 Editionと仲良くなれるので、簡単なオブジェクトで構わないからやってみるといいかもしれません。
データ構造の話
ここで紹介されていたQueue
とかDeque
とか、Stack
とか、LinkedList
とかは自分で実装すると面白いので、是非実装するといいと思います。
スタックにこだわってた理由
マカロンスタックを言いたいがためにマカロンがスライドのあちこちにありました。
マサカリたち
僕の前に座っていたおじさんが、声が小さいながら、各JVMベンダーとの互換性についてよい質問をしていました。
質問「Oracleのコンパイラーで作ったバイトコードをIBMのマシンで動かしたら不具合が発生するとかあります?」
さくらばさん「IBMも今はOpenJDKに参加しているので、おそらく不具合はないと思いますが、実装依存なところがある」 #jjug
— 持田真哉 (@mike_neck) April 24, 2015
JVM仕様にのっとって作っていたVMだと、実装依存と書いてあるところがあったりして、VMによって動作が異なることがあるので注意 #jjug
— 持田真哉 (@mike_neck) April 24, 2015
僕が知っている限りではecjでは通るけど、javacでは駄目なコードの例として、アノテーションの配列くらいでしょうか…まあ、コンパイルエラーしているコードを実行したらどうなるか、ちょっと不安がありますが…
これは後で試してみたいけど、ecj使ったことないし、使い方わからん(´・ω・`)
後半 GCの話
これはJJUG CCC 2014 FallであったセッションConcurrent Mark-Sweep Garbage Collection 再入門の話とほとんど同じ話でした。
www.slideshare.net
以上、雑なまとめでした。
なお、僕の隣の島にすわったのがぜろゆ嬢でした。
はじめて定時退社した…
— ぜろゆ (@zer0_u) April 24, 2015
なんか、残業たくさんしているけど、まだまだ生きていそうなので、元気のあるうちに残業ない所に行きま(無責任)
なお、ぜろゆ嬢が「定時退社したぜ!ドヤァ!」で両手の親指をあげて╭( ・ㅂ・)و ̑̑ グッ !ポーズして、ちょっと、こころがときめきました。
あ、おっさんの妄想ですので、気にしないでください(セクハラ)