上記のとおりです。
ツイートが下記の通りまとめられています。
そのうちさくらばさんが資料をあげてくれると思います。
【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
なんか、残業たくさんしているけど、まだまだ生きていそうなので、元気のあるうちに残業ない所に行きま(無責任)
なお、ぜろゆ嬢が「定時退社したぜ!ドヤァ!」で両手の親指をあげて╭( ・ㅂ・)و ̑̑ グッ !ポーズして、ちょっと、こころがときめきました。
あ、おっさんの妄想ですので、気にしないでください(セクハラ)