Top Banner
gen-class とバイトコード @tnoda_ 3 gen-class 勉強会 [2015-05-12 Tue]
50

gen-class とバイトコード(第3回 gen-class 勉強会資料)

Aug 06, 2015

Download

Engineering

tnoda
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: gen-class とバイトコード(第3回 gen-class 勉強会資料)

gen-classとバイトコード

@tnoda_

第 3 回 gen-class 勉強会

[2015-05-12 Tue]

Page 2: gen-class とバイトコード(第3回 gen-class 勉強会資料)

Outline

gen-classのバイトコード

• メソッド

• クラスの初期化

Javaの classとの違い

• バイトコードの違い

• gen-class にしかできないこと

Page 3: gen-class とバイトコード(第3回 gen-class 勉強会資料)

単純なクラスの例 (Java)

Example (Foo.java)

1 class Foo {2 public long inc(long x) {3 return x + 1;4 }5 }

Page 4: gen-class とバイトコード(第3回 gen-class 勉強会資料)

javapの実行例 (1/2)

Example (javap Foo)

1 Compiled from "Foo.java"2 class Foo {3 Foo();4 public long inc(long);5 }

Page 5: gen-class とバイトコード(第3回 gen-class 勉強会資料)

javapの実行例 (2/2)

Example (javap -c Foo)

1 Compiled from "Foo.java"2 class Foo {3 Foo();4 Code:5 0: aload_06 1: invokespecial #1 // Method

java/lang/Object."<init >":()V7 4: return89 public long inc(long);

10 Code:11 0: lload_112 1: lconst_113 2: ladd14 3: lreturn15 }

Page 6: gen-class とバイトコード(第3回 gen-class 勉強会資料)

単純なクラスの例 (gen-class)

Example (bar.clj)

1 (gen-class2 :name Bar3 :methods [[inc [long] long ]])45 (defn- -inc ^long6 [^long x]7 (inc x))

Example (Foo.java)

1 class Foo {2 public long inc(long x) {3 return x + 1;4 }5 }

Page 7: gen-class とバイトコード(第3回 gen-class 勉強会資料)

javapの実行例

Example (javap Bar)

1 public class Bar {2 public static {};3 public Bar();4 public java.lang.Object

clone ();5 public int hashCode ();6 public java.lang.String

toString ();7 public boolean equals(java

.lang.Object );8 public long inc(long);9 }

Example (javap Foo)

1 Compiled from "Foo.java"2 class Foo {3 Foo();4 public long inc(long);5 }

Page 8: gen-class とバイトコード(第3回 gen-class 勉強会資料)

javapの実行例

Example (javap Bar)

1 public class Bar {2 public static {};3 public Bar();4 public java.lang.Object

clone ();5 public int hashCode ();6 public java.lang.String

toString ();7 public boolean equals(java

.lang.Object );8 public long inc(long);9 }

Example (javap Foo)

1 Compiled from "Foo.java"2 class Foo {3 Foo();4 public long inc(long);5 }

Page 9: gen-class とバイトコード(第3回 gen-class 勉強会資料)

身に覚えの無いメソッド (1/2)

_人人人人人人人人人人人人人人_

>  clone();  <

>  hashCode();  <

>  toString();  <

>  equals(java.lang.Object); < ̄YYYYYYYYYYYYYY ̄

Example (bar.clj)

1 (gen-class2 :name Bar3 :methods [[inc [long] long ]])

Page 10: gen-class とバイトコード(第3回 gen-class 勉強会資料)

身に覚えなの無いメソッド (2/2)

1 user > (.clone (Bar.))2 CloneNotSupportedException Bar java.lang.Object.clone (

Object.java:-2)34 user > (. hashCode (Bar.))5 133240721067 user > (. toString (Bar.))8 "Bar@4ce58390"9

10 user > (. equals (Bar.) (Bar.))11 false

Page 11: gen-class とバイトコード(第3回 gen-class 勉強会資料)

gen-classの仕様clone() がつくられるのは gen-class の仕様

docstring (:methods)

The generated class automatically defines all of thenon-private methods of its superclasses/interfaces.

生成クラスにはスーパークラスおよび実装インタフェースのプラ

イベードではないメソッドが自動的に定義される。

docstring (:extends)

Specifies the superclass, the non-private methods ofwhich will be overridden by the class. If not provided,defaults to Object.

スーパークラスが :extends で明示的に指定されない場合のデフォルトは Object.

Page 12: gen-class とバイトコード(第3回 gen-class 勉強会資料)

gen-classの仕様clone() がつくられるのは gen-class の仕様

docstring (:methods)

The generated class automatically defines all of thenon-private methods of its superclasses/interfaces.

生成クラスにはスーパークラスおよび実装インタフェースのプラ

イベードではないメソッドが自動的に定義される。

docstring (:extends)

Specifies the superclass, the non-private methods ofwhich will be overridden by the class. If not provided,defaults to Object.

スーパークラスが :extends で明示的に指定されない場合のデフォルトは Object.

Page 13: gen-class とバイトコード(第3回 gen-class 勉強会資料)

gen-classの仕様clone() がつくられるのは gen-class の仕様

docstring (:methods)

The generated class automatically defines all of thenon-private methods of its superclasses/interfaces.

生成クラスにはスーパークラスおよび実装インタフェースのプラ

イベードではないメソッドが自動的に定義される。

docstring (:extends)

Specifies the superclass, the non-private methods ofwhich will be overridden by the class. If not provided,defaults to Object.

スーパークラスが :extends で明示的に指定されない場合のデフォルトは Object.

Page 14: gen-class とバイトコード(第3回 gen-class 勉強会資料)

gen-classの仕様clone() がつくられるのは gen-class の仕様

docstring (:methods)

The generated class automatically defines all of thenon-private methods of its superclasses/interfaces.

生成クラスにはスーパークラスおよび実装インタフェースのプラ

イベードではないメソッドが自動的に定義される。

docstring (:extends)

Specifies the superclass, the non-private methods ofwhich will be overridden by the class. If not provided,defaults to Object.

スーパークラスが :extends で明示的に指定されない場合のデフォルトは Object.

Page 15: gen-class とバイトコード(第3回 gen-class 勉強会資料)

スーパークラス由来のメソッド

_人人人人人人人人人人人人人人_

>  clone();  <

>  hashCode();  <

>  toString();  <

>  equals(java.lang.Object); < ̄YYYYYYYYYYYYYY ̄

身に覚えの無いメソッドは Object 由来のもの

Page 16: gen-class とバイトコード(第3回 gen-class 勉強会資料)

clone()の実装 (1/2)

public java.lang.Object clone();Code:

0: getstatic #40 // Field clone__var:Lclojure/lang/Var;3: dup4: invokevirtual #66 // Method clojure/lang/Var.isBound:()Z7: ifeq 16

10: invokevirtual #69 // Method clojure/lang/Var.get:()Ljava/lang/Object;13: goto 1816: pop17: aconst_null18: dup19: ifnull 3422: checkcast #53 // class clojure/lang/IFn25: aload_026: invokeinterface #57, 2 // InterfaceMethod clojure/lang/IFn.invoke:(Ljava/lang/Object;)Ljava/lang/Object;31: goto 3934: pop35: aload_036: invokespecial #71 // Method java/lang/Object.clone:()Ljava/lang/Object;39: areturn

Page 17: gen-class とバイトコード(第3回 gen-class 勉強会資料)

clone()の実装 (2/2)

1 clone_var スタティックフィールドの Var を確認

2 バインドされていないか null ならば Object.clone() を呼び出し

3 バインドされていれば IFn にキャストして Clojure の関数を実行 (IFn.invoke())

継承メソッドの実装

1 対応する Clojure 関数があるかどうかを確認2 無ければスーパークラスのメソッドを呼び出す

3 対応する Clojure 関数があれば、その関数を実行

Page 18: gen-class とバイトコード(第3回 gen-class 勉強会資料)

clone()の実装 (2/2)

1 clone_var スタティックフィールドの Var を確認

2 バインドされていないか null ならば Object.clone() を呼び出し

3 バインドされていれば IFn にキャストして Clojure の関数を実行 (IFn.invoke())

継承メソッドの実装

1 対応する Clojure 関数があるかどうかを確認2 無ければスーパークラスのメソッドを呼び出す

3 対応する Clojure 関数があれば、その関数を実行

Page 19: gen-class とバイトコード(第3回 gen-class 勉強会資料)

inc()の実装 (1/2)public long inc(long);

Code:0: getstatic #24 // Field inc__var:Lclojure/lang/Var;3: dup4: invokevirtual #66 // Method clojure/lang/Var.isBound:()Z7: ifeq 16

10: invokevirtual #69 // Method clojure/lang/Var.get:()Ljava/lang/Object;13: goto 1816: pop17: aconst_null18: dup19: ifnull 4422: checkcast #53 // class clojure/lang/IFn25: aload_026: lload_127: invokestatic #106 // Method clojure/lang/Numbers.num:(J)Ljava/lang/Number;30: invokeinterface #91, 3 // InterfaceMethod clojure/lang/IFn.invoke:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;35: checkcast #75 // class java/lang/Number38: invokevirtual #110 // Method java/lang/Number.longValue:()J41: goto 5544: pop45: new #112 // class java/lang/UnsupportedOperationException48: dup49: ldc #114 // String inc (example/-inc not defined?)51: invokespecial #117 // Method java/lang/UnsupportedOperationException."<init>":(Ljava/lang/String;)V54: athrow55: lreturn

Page 20: gen-class とバイトコード(第3回 gen-class 勉強会資料)

inc()の実装 (2/2)

1 inc_var スタティックフィールドの Var を確認

2 バインドされていないか null ならばUnsupportedOperationException

3 バインドされていれば IFn にキャストして Clojure の関数を実行 (IFn.invoke())

実際の処理は Clojure の関数 -inc が実行するので、バイトコードには処理の内容が含まれていない!

非継承メソッドの実装

1 対応する Clojure 関数があるかどうかを確認2 無ければ UnsupportedOperationException

3 対応する Clojure 関数があれば、その関数を実行

Page 21: gen-class とバイトコード(第3回 gen-class 勉強会資料)

inc()の実装 (2/2)

1 inc_var スタティックフィールドの Var を確認

2 バインドされていないか null ならばUnsupportedOperationException

3 バインドされていれば IFn にキャストして Clojure の関数を実行 (IFn.invoke())

実際の処理は Clojure の関数 -inc が実行するので、バイトコードには処理の内容が含まれていない!

非継承メソッドの実装

1 対応する Clojure 関数があるかどうかを確認2 無ければ UnsupportedOperationException

3 対応する Clojure 関数があれば、その関数を実行

Page 22: gen-class とバイトコード(第3回 gen-class 勉強会資料)

inc()の実装 (2/2)

1 inc_var スタティックフィールドの Var を確認

2 バインドされていないか null ならばUnsupportedOperationException

3 バインドされていれば IFn にキャストして Clojure の関数を実行 (IFn.invoke())

実際の処理は Clojure の関数 -inc が実行するので、バイトコードには処理の内容が含まれていない!

非継承メソッドの実装

1 対応する Clojure 関数があるかどうかを確認2 無ければ UnsupportedOperationException

3 対応する Clojure 関数があれば、その関数を実行

Page 23: gen-class とバイトコード(第3回 gen-class 勉強会資料)

Checkpoint 1gen-class が生成するメソッド実装

継承メソッドのデフォルト実装

1 対応する Clojure 関数があるかどうかを確認

2 無ければスーパークラスのメソッドを呼び出す

3 対応する Clojure 関数があれば、その関数を実行

非継承メソッドの実装

1 対応する Clojure 関数があるかどうかを確認

2 無ければ UnsupportedOperationException

3 対応する Clojure 関数があれば、その関数を実行

Clojure 関数を呼び出すだけのプロキシ

Page 24: gen-class とバイトコード(第3回 gen-class 勉強会資料)

Checkpoint 1gen-class が生成するメソッド実装

継承メソッドのデフォルト実装

1 対応する Clojure 関数があるかどうかを確認

2 無ければスーパークラスのメソッドを呼び出す

3 対応する Clojure 関数があれば、その関数を実行

非継承メソッドの実装

1 対応する Clojure 関数があるかどうかを確認

2 無ければ UnsupportedOperationException

3 対応する Clojure 関数があれば、その関数を実行

Clojure 関数を呼び出すだけのプロキシ

Page 25: gen-class とバイトコード(第3回 gen-class 勉強会資料)

Checkpoint 1gen-class が生成するメソッド実装

継承メソッドのデフォルト実装

1 対応する Clojure 関数があるかどうかを確認

2 無ければスーパークラスのメソッドを呼び出す

3 対応する Clojure 関数があれば、その関数を実行

非継承メソッドの実装

1 対応する Clojure 関数があるかどうかを確認

2 無ければ UnsupportedOperationException

3 対応する Clojure 関数があれば、その関数を実行

Clojure 関数を呼び出すだけのプロキシ

Page 26: gen-class とバイトコード(第3回 gen-class 勉強会資料)

Checkpoint 1gen-class が生成するメソッド実装

継承メソッドのデフォルト実装

1 対応する Clojure 関数があるかどうかを確認

2 無ければスーパークラスのメソッドを呼び出す

3 対応する Clojure 関数があれば、その関数を実行

非継承メソッドの実装

1 対応する Clojure 関数があるかどうかを確認

2 無ければ UnsupportedOperationException

3 対応する Clojure 関数があれば、その関数を実行

Clojure 関数を呼び出すだけのプロキシ

Page 27: gen-class とバイトコード(第3回 gen-class 勉強会資料)

残された疑問

疑問 1

1 clone_var スタティックフィールドの Var を確認

疑問 2

1 inc_var スタティックフィールドの Var を確認

Page 28: gen-class とバイトコード(第3回 gen-class 勉強会資料)

残された疑問

疑問 1

1 clone_var スタティックフィールドの Var を確認

疑問 2

1 inc_var スタティックフィールドの Var を確認

Page 29: gen-class とバイトコード(第3回 gen-class 勉強会資料)

残された疑問

疑問 1

1 clone_var スタティックフィールドの Var を確認

疑問 2

1 inc_var スタティックフィールドの Var を確認

Page 30: gen-class とバイトコード(第3回 gen-class 勉強会資料)

Static Initializer (1/3)

Figure : Bar クラスの static initializer

Page 31: gen-class とバイトコード(第3回 gen-class 勉強会資料)

Static Initializer (2/3)

Example (Java)

1 private static final Var inc__var = Var.internPrivate("example", "-inc");

2 private static final Var equals__var = Var.internPrivate("example", "-equals");

3 private static final Var toString__var = Var.internPrivate("example", "-toString");

4 private static final Var hashCode__var = Var.internPrivate("example", "-hashCode");

5 private static final Var clone__var = Var.internPrivate("example", "-clone");

67 static {8 RT.var("clojure.core", "load"). invoke("/example");9 }

Page 32: gen-class とバイトコード(第3回 gen-class 勉強会資料)

Static Initializer (3/3)

Example (Java)

1 Var.internPrivate("example", "-inc");

Example (Clojure)

1 example /-inc

スタティックフィールドの中身

関数(メソッドの処理を担当)の Var をキャッシュ

Page 33: gen-class とバイトコード(第3回 gen-class 勉強会資料)

Static Initializer (3/3)

Example (Java)

1 Var.internPrivate("example", "-inc");

Example (Clojure)

1 example /-inc

スタティックフィールドの中身

関数(メソッドの処理を担当)の Var をキャッシュ

Page 34: gen-class とバイトコード(第3回 gen-class 勉強会資料)

Static Initializer (3/3)

Example (Java)

1 Var.internPrivate("example", "-inc");

Example (Clojure)

1 example /-inc

スタティックフィールドの中身

関数(メソッドの処理を担当)の Var をキャッシュ

Page 35: gen-class とバイトコード(第3回 gen-class 勉強会資料)

Checkpoit 2

!"#$%&"'' (&)*+#,

-.%//0"#

1#-0"2,3'2"2-%34"#

-.%5&).67

1+8&-%3&).6

Figure : 初期化前

Page 36: gen-class とバイトコード(第3回 gen-class 勉強会資料)

Checkpoit 2

!"#$%&"'' (&)*+#,

-.%//0"#

1#-0"2,3'2"2-%34"#

-.%5&).67

1+8&-%3&).6

,9":1&,;<-.%

Figure : スタティックフィールド初期化

Page 37: gen-class とバイトコード(第3回 gen-class 勉強会資料)

Checkpoit 2

!"#$%&"'' (&)*+#,

-.%//0"#

1#-0"2,3'2"2-%34"#

-.%5&).67

1+8&-%3&).6

,9":1&,;<-.%

!"

Figure : 名前空間読み込み

Page 38: gen-class とバイトコード(第3回 gen-class 勉強会資料)

Checkpoit 2

!"#$%&"'' (&)*+#,

-.%//0"#

1#-0"2,3'2"2-%34"#

-.%5&).67

1+8&-%3&).6

,9":1&,;<-.%

!"

Figure : メソッド呼び出し

Page 39: gen-class とバイトコード(第3回 gen-class 勉強会資料)

Javaのクラスとの違い

!"#$%&"'' (&)*+#,

-.%//0"#

1#-0"2,3'2"2-%34"#

-.%5&).67

1+8&-%3&).6

,9":1&,;<-.%

!"

Figure : gen-class のメソッド呼び出し

Page 40: gen-class とバイトコード(第3回 gen-class 勉強会資料)

システムの動的な変更 (Java)

!"#$%&

'()*## '()*##

'+*,*

'+*,*

'()*##

手順

1 Java ソースを変更する2 コンパイルする

3 Jar/class ファイルを置き換える

4 クラスローダでリロード/最悪再起動

Page 41: gen-class とバイトコード(第3回 gen-class 勉強会資料)

システムの動的な変更 (Java)

!"#$%&

'()*## '()*##

'+*,*

'+*,*

'()*##

手順

1 Java ソースを変更する2 コンパイルする

3 Jar/class ファイルを置き換える

4 クラスローダでリロード/最悪再起動

Page 42: gen-class とバイトコード(第3回 gen-class 勉強会資料)

システムの動的な変更 (gen-class)

!"#$%&"'' (&)*+#,

-.%//0"#

1#-0"2,3'2"2-%34"#

-.%5&).67

1+8&-%3&).6

,9":1&,;<-.%

!"

手順

1 fn を更新して eval

gen-class で生成した .class ファイルの変更なし

Page 43: gen-class とバイトコード(第3回 gen-class 勉強会資料)

システムの動的な変更 (gen-class)

!"#$%&"'' (&)*+#,

-.%//0"#

1#-0"2,3'2"2-%34"#

-.%5&).67

1+8&-%3&).6

,9":1&,;<-.%

!"

手順

1 fn を更新して eval

gen-class で生成した .class ファイルの変更なし

Page 44: gen-class とバイトコード(第3回 gen-class 勉強会資料)

デモ

Figure : Minecraft

Page 45: gen-class とバイトコード(第3回 gen-class 勉強会資料)

Checkpoint 3

Javaの classと Clojureの gen-classとの違い

• 動的 に変更できるかどうか

動的とは

システムを 動 かしたまま変更できるかどうか

• Java . . . 全身麻酔• Clojure . . . 意識のある状態で脳外科手術

Page 46: gen-class とバイトコード(第3回 gen-class 勉強会資料)

Checkpoint 3

Javaの classと Clojureの gen-classとの違い

• 動的 に変更できるかどうか

動的とは

システムを 動 かしたまま変更できるかどうか

• Java . . . 全身麻酔• Clojure . . . 意識のある状態で脳外科手術

Page 47: gen-class とバイトコード(第3回 gen-class 勉強会資料)

Wrap-up

gen-classが生成するクラスファイルの特徴

• 実際の処理を Clojure 関数に委譲するプロキシ• Var 経由でメソッドと Clojure 関数とをリンク

gen-classで Javaクラスをつくる利点

• システムを動的に変更できる

• gen-class 生成クラスファイルのコンパイル不要

Clojure の動的さを Java の世界に持ち込む魔法

Page 48: gen-class とバイトコード(第3回 gen-class 勉強会資料)

Wrap-up

gen-classが生成するクラスファイルの特徴

• 実際の処理を Clojure 関数に委譲するプロキシ• Var 経由でメソッドと Clojure 関数とをリンク

gen-classで Javaクラスをつくる利点

• システムを動的に変更できる

• gen-class 生成クラスファイルのコンパイル不要

Clojure の動的さを Java の世界に持ち込む魔法

Page 49: gen-class とバイトコード(第3回 gen-class 勉強会資料)

Wrap-up

gen-classが生成するクラスファイルの特徴

• 実際の処理を Clojure 関数に委譲するプロキシ• Var 経由でメソッドと Clojure 関数とをリンク

gen-classで Javaクラスをつくる利点

• システムを動的に変更できる

• gen-class 生成クラスファイルのコンパイル不要

Clojure の動的さを Java の世界に持ち込む魔法

Page 50: gen-class とバイトコード(第3回 gen-class 勉強会資料)

Wrap-up

gen-classが生成するクラスファイルの特徴

• 実際の処理を Clojure 関数に委譲するプロキシ• Var 経由でメソッドと Clojure 関数とをリンク

gen-classで Javaクラスをつくる利点

• システムを動的に変更できる

• gen-class 生成クラスファイルのコンパイル不要

Clojure の動的さを Java の世界に持ち込む魔法