Download free for 30 days
Sign in
Upload
Language (EN)
Support
Business
Mobile
Social Media
Marketing
Technology
Art & Photos
Career
Design
Education
Presentations & Public Speaking
Government & Nonprofit
Healthcare
Internet
Law
Leadership & Management
Automotive
Engineering
Software
Recruiting & HR
Retail
Sales
Services
Science
Small Business & Entrepreneurship
Food
Environment
Economy & Finance
Data & Analytics
Investor Relations
Sports
Spiritual
News & Politics
Travel
Self Improvement
Real Estate
Entertainment & Humor
Health & Medicine
Devices & Hardware
Lifestyle
Change Language
Language
English
Español
Português
Français
Deutsche
Cancel
Save
Submit search
EN
TM
Uploaded by
Taku Miyakawa
11,337 views
ラムダと invokedynamic の蜜月
Read more
33
Save
Share
Embed
Embed presentation
Download
Downloaded 45 times
1
/ 51
2
/ 51
3
/ 51
4
/ 51
5
/ 51
6
/ 51
7
/ 51
8
/ 51
9
/ 51
10
/ 51
11
/ 51
12
/ 51
13
/ 51
14
/ 51
15
/ 51
16
/ 51
17
/ 51
18
/ 51
19
/ 51
20
/ 51
21
/ 51
22
/ 51
23
/ 51
24
/ 51
25
/ 51
26
/ 51
27
/ 51
28
/ 51
29
/ 51
30
/ 51
31
/ 51
32
/ 51
33
/ 51
34
/ 51
35
/ 51
36
/ 51
37
/ 51
38
/ 51
39
/ 51
40
/ 51
41
/ 51
42
/ 51
43
/ 51
44
/ 51
45
/ 51
46
/ 51
47
/ 51
48
/ 51
49
/ 51
50
/ 51
51
/ 51
More Related Content
PDF
オブジェクト指向できていますか?
by
Moriharu Ohzu
PDF
C++ マルチスレッドプログラミング
by
Kohsuke Yuasa
PDF
20分でわかるgVisor入門
by
Shuji Yamada
PDF
WASM(WebAssembly)入門 ペアリング演算やってみた
by
MITSUNARI Shigeo
PPTX
9/14にリリースされたばかりの新LTS版Java 17、ここ3年間のJavaの変化を知ろう!(Open Source Conference 2021 O...
by
NTT DATA Technology & Innovation
PDF
AngularとSpring Bootで作るSPA + RESTful Web Serviceアプリケーション
by
ssuser070fa9
PDF
何となく勉強した気分になれるパーサ入門
by
masayoshi takahashi
PDF
Introduction httpClient on Java11 / Java11時代のHTTPアクセス再入門
by
tamtam180
オブジェクト指向できていますか?
by
Moriharu Ohzu
C++ マルチスレッドプログラミング
by
Kohsuke Yuasa
20分でわかるgVisor入門
by
Shuji Yamada
WASM(WebAssembly)入門 ペアリング演算やってみた
by
MITSUNARI Shigeo
9/14にリリースされたばかりの新LTS版Java 17、ここ3年間のJavaの変化を知ろう!(Open Source Conference 2021 O...
by
NTT DATA Technology & Innovation
AngularとSpring Bootで作るSPA + RESTful Web Serviceアプリケーション
by
ssuser070fa9
何となく勉強した気分になれるパーサ入門
by
masayoshi takahashi
Introduction httpClient on Java11 / Java11時代のHTTPアクセス再入門
by
tamtam180
What's hot
PDF
Javaコードが速く実⾏される秘密 - JITコンパイラ⼊⾨(JJUG CCC 2020 Fall講演資料)
by
NTT DATA Technology & Innovation
PDF
導入から 10 年、PHP の trait は滅びるべきなのか その適切な使いどころと弱点、将来について
by
shinjiigarashi
PDF
できる!並列・並行プログラミング
by
Preferred Networks
PPTX
JAVA_HOME/binにあるコマンド、いくつ使っていますか?[JVM関連ツール編](JJUGナイトセミナー「Java解析ツール特集」 発表資料)
by
NTT DATA Technology & Innovation
PDF
プログラムの処方箋~健康なコードと病んだコード
by
Shigenori Sagawa
PPTX
このPHP QAツールがすごい!2019
by
sasezaki
PPTX
イベント駆動プログラミングとI/O多重化
by
Gosuke Miyashita
PDF
コスト最適化概論
by
RikiMakita
PPTX
PostgreSQLモニタリングの基本とNTTデータが追加したモニタリング新機能(Open Source Conference 2021 Online F...
by
NTT DATA Technology & Innovation
PDF
RESTful Web アプリの設計レビューの話
by
Takuto Wada
PDF
Test Yourself - テストを書くと何がどう変わるか
by
Takuto Wada
PPTX
Metaspace
by
Yasumasa Suenaga
PDF
デキるプログラマだけが知っているコードレビュー7つの秘訣
by
Masahiro Nishimi
PPTX
トランザクションの設計と進化
by
Kumazaki Hiroki
PPTX
Java でつくる低レイテンシ実装の技巧
by
Ryosuke Yamazaki
PDF
10GbE時代のネットワークI/O高速化
by
Takuya ASADA
PDF
WebSocket / WebRTCの技術紹介
by
Yasuhiro Mawarimichi
PDF
ウェーブレット木の世界
by
Preferred Networks
PPTX
java.lang.OutOfMemoryError #渋谷java
by
Yuji Kubota
PPT
Glibc malloc internal
by
Motohiro KOSAKI
Javaコードが速く実⾏される秘密 - JITコンパイラ⼊⾨(JJUG CCC 2020 Fall講演資料)
by
NTT DATA Technology & Innovation
導入から 10 年、PHP の trait は滅びるべきなのか その適切な使いどころと弱点、将来について
by
shinjiigarashi
できる!並列・並行プログラミング
by
Preferred Networks
JAVA_HOME/binにあるコマンド、いくつ使っていますか?[JVM関連ツール編](JJUGナイトセミナー「Java解析ツール特集」 発表資料)
by
NTT DATA Technology & Innovation
プログラムの処方箋~健康なコードと病んだコード
by
Shigenori Sagawa
このPHP QAツールがすごい!2019
by
sasezaki
イベント駆動プログラミングとI/O多重化
by
Gosuke Miyashita
コスト最適化概論
by
RikiMakita
PostgreSQLモニタリングの基本とNTTデータが追加したモニタリング新機能(Open Source Conference 2021 Online F...
by
NTT DATA Technology & Innovation
RESTful Web アプリの設計レビューの話
by
Takuto Wada
Test Yourself - テストを書くと何がどう変わるか
by
Takuto Wada
Metaspace
by
Yasumasa Suenaga
デキるプログラマだけが知っているコードレビュー7つの秘訣
by
Masahiro Nishimi
トランザクションの設計と進化
by
Kumazaki Hiroki
Java でつくる低レイテンシ実装の技巧
by
Ryosuke Yamazaki
10GbE時代のネットワークI/O高速化
by
Takuya ASADA
WebSocket / WebRTCの技術紹介
by
Yasuhiro Mawarimichi
ウェーブレット木の世界
by
Preferred Networks
java.lang.OutOfMemoryError #渋谷java
by
Yuji Kubota
Glibc malloc internal
by
Motohiro KOSAKI
Viewers also liked
PDF
JSR 352 “Batch Applications for the Java Platform”
by
Norito Agetsuma
PDF
JSFとJAX-RSで作る Thin Server Architecture #glassfishjp
by
Toshiaki Maki
PDF
Java 7 invokedynamic の概要
by
Taku Miyakawa
PDF
Lambda: A Peek Under The Hood - Brian Goetz
by
JAX London
PDF
Project Lambdaの基礎
by
Yuichi Sakuraba
PDF
Java Batch 仕様 (Public Review時点)
by
Norito Agetsuma
JSR 352 “Batch Applications for the Java Platform”
by
Norito Agetsuma
JSFとJAX-RSで作る Thin Server Architecture #glassfishjp
by
Toshiaki Maki
Java 7 invokedynamic の概要
by
Taku Miyakawa
Lambda: A Peek Under The Hood - Brian Goetz
by
JAX London
Project Lambdaの基礎
by
Yuichi Sakuraba
Java Batch 仕様 (Public Review時点)
by
Norito Agetsuma
Similar to ラムダと invokedynamic の蜜月
PDF
社内Java8勉強会 ラムダ式とストリームAPI
by
Akihiro Ikezoe
PPTX
C# 式木 (Expression Tree) ~ LINQをより深く理解するために ~
by
Fujio Kojima
PPTX
Java8勉強会
by
賢太郎 前多
PDF
静かに変わってきたクラスファイルを詳細に調べて楽しむ(JJUG CCC 2024 Fall講演資料)
by
NTT DATA Technology & Innovation
PPTX
jvmlang.daitokai 1.0.0 MinCamlJを作ってみた
by
Kazuyoshi Kamitsukasa
PPTX
【java8 勉強会】 怖くない!ラムダ式, Stream API
by
dcomsolution
PDF
Java8 lambdas chapter1_2
by
yo0824
PDF
InvokeDynamic at #shikadriven 2012
by
Go Tanaka
PDF
Lambda: A Peek Under The Hood [Java Day Tokyo 2015 6-3]
by
David Buck
PPTX
Java8から始める関数型プログラミング
by
stylefreeslide
PPTX
Project lambda
by
Appresso Engineering Team
PPTX
Visual Studio による開発環境・プログラミングの進化
by
Fujio Kojima
社内Java8勉強会 ラムダ式とストリームAPI
by
Akihiro Ikezoe
C# 式木 (Expression Tree) ~ LINQをより深く理解するために ~
by
Fujio Kojima
Java8勉強会
by
賢太郎 前多
静かに変わってきたクラスファイルを詳細に調べて楽しむ(JJUG CCC 2024 Fall講演資料)
by
NTT DATA Technology & Innovation
jvmlang.daitokai 1.0.0 MinCamlJを作ってみた
by
Kazuyoshi Kamitsukasa
【java8 勉強会】 怖くない!ラムダ式, Stream API
by
dcomsolution
Java8 lambdas chapter1_2
by
yo0824
InvokeDynamic at #shikadriven 2012
by
Go Tanaka
Lambda: A Peek Under The Hood [Java Day Tokyo 2015 6-3]
by
David Buck
Java8から始める関数型プログラミング
by
stylefreeslide
Project lambda
by
Appresso Engineering Team
Visual Studio による開発環境・プログラミングの進化
by
Fujio Kojima
More from Taku Miyakawa
PDF
Javaのログ出力: 道具と考え方
by
Taku Miyakawa
PDF
Java SE 9の紹介: モジュール・システムを中心に
by
Taku Miyakawa
PDF
金勘定のためのBigDecimalそしてMoney and Currency API
by
Taku Miyakawa
PDF
擬似乱数生成器の評価
by
Taku Miyakawa
PDF
コルーチンの実装について
by
Taku Miyakawa
PDF
Kink: プロトタイプベースの俺々 JVM 言語
by
Taku Miyakawa
PDF
Kink: developing a programming language on the JVM
by
Taku Miyakawa
PDF
Java オブジェクトの内部構造
by
Taku Miyakawa
PDF
Matrix Multiplication in Strassen Algorithm
by
Taku Miyakawa
PDF
Summary of "Hacking", 0x351-0x354
by
Taku Miyakawa
PDF
言語設計者が意味論を書くときに考えていたこと
by
Taku Miyakawa
PDF
Kink: invokedynamic on a prototype-based language
by
Taku Miyakawa
PDF
Quasar: Actor Model and Light Weight Threads on Java
by
Taku Miyakawa
PDF
Hadoop jobbuilder
by
Taku Miyakawa
PDF
Java Quine Golf
by
Taku Miyakawa
PDF
Kink の宣伝
by
Taku Miyakawa
PDF
Processing LTSV by Apache Pig
by
Taku Miyakawa
PDF
Graph Algorithms Part 1
by
Taku Miyakawa
Javaのログ出力: 道具と考え方
by
Taku Miyakawa
Java SE 9の紹介: モジュール・システムを中心に
by
Taku Miyakawa
金勘定のためのBigDecimalそしてMoney and Currency API
by
Taku Miyakawa
擬似乱数生成器の評価
by
Taku Miyakawa
コルーチンの実装について
by
Taku Miyakawa
Kink: プロトタイプベースの俺々 JVM 言語
by
Taku Miyakawa
Kink: developing a programming language on the JVM
by
Taku Miyakawa
Java オブジェクトの内部構造
by
Taku Miyakawa
Matrix Multiplication in Strassen Algorithm
by
Taku Miyakawa
Summary of "Hacking", 0x351-0x354
by
Taku Miyakawa
言語設計者が意味論を書くときに考えていたこと
by
Taku Miyakawa
Kink: invokedynamic on a prototype-based language
by
Taku Miyakawa
Quasar: Actor Model and Light Weight Threads on Java
by
Taku Miyakawa
Hadoop jobbuilder
by
Taku Miyakawa
Java Quine Golf
by
Taku Miyakawa
Kink の宣伝
by
Taku Miyakawa
Processing LTSV by Apache Pig
by
Taku Miyakawa
Graph Algorithms Part 1
by
Taku Miyakawa
ラムダと invokedynamic の蜜月
1.
ラムダと invokedynamic の蜜月 宮川
拓 / @miyakawa_taku 2013-07-22 JJUG ナイトセミナー
2.
自己紹介 • 宮川 拓
(@miyakawa_taku) と申します • SI 屋です • JJUG 幹事です • Kink という JVM 言語を開発しています – https://bitbucket.org/kink/kink 1
3.
要旨 • ラムダ式の実行は invokedynamic
で実現さ れます。その理由と、実行の流れを見ます – 論点整理 – ラムダ式の実行 (1) – invokedynamic の復習 – ラムダ式の実行 (2) – なぜ invokedynamic? – ラムダの直列化 2 ※注記 この資料は、 JDK, JRE の「仕様」と「実装」を厳密に区別していません。
4.
論点整理 3
5.
静的構造 4 関数型インタフェース ラムダのクラス ラムダのインスタンス instance-of implements Comparable Comparable<String> c =
(x, y) -> x.length() - y.length(); c c のクラス
6.
実行の流れ 5 Comparable<String> c =
(x, y) -> x.length() - y.length(); Collections.sort(strings, c); main Collections ラムダ sort compare / 処理の中身の実行 new / ラムダ式の実行 今回の主な論点
7.
ラムダ式の実行 (1) 6
8.
ラムダのクラスの実行時生成 • 匿名クラスがコンパイル時に生成されるのに 対し、ラムダのクラスは実行時に生成されます。 まずはそれを確かめます 7 関数型インタフェース ラムダのクラス ラムダのインスタンス instance-of implements 実行時に生成
9.
匿名クラスをコンパイル • 匿名クラスは、「外側のクラス名$連番」という 名前で、コンパイラによって生成されます 8 $ cat
>AnonClass.java import java.util.*; class AnonClass { Comparator<String> comparator() { return new Comparator<String> { @Override public int compare(String x, String y) { return x.length() – y.length(); } }; } } $ javac AnonClass.java && ls *.class AnonClass$1.class AnonClass.class
10.
ラムダをコンパイル • 同等のラムダをコンパイルしても、対応するク ラスファイルは生成されません 9 $ cat
>Lambda.java import java.util.*; class Lambda { Comparator<String> comparator() { return (x, y) -> x.length() - y.length(); } } $ javac Lambda.java && ls *.class Lambda.class
11.
ラムダのクラスの生成タイミング • ラムダのクラスが、コンパイル時には生成され ないことが分かりました • したがって、実行時のどこかのタイミングで生 成されているはずです 10 ラムダを含む ソース クラス ファイル ラムダの クラスの生成 ラムダの インスタンス化 コンパイル
(JDK) 実行 (JVM) この時点では ラムダのクラスは 生成されない どこかの タイミング
12.
ラムダのクラスの名前 • まずはラムダのクラスの名前を確認します 11 $ cat
>Lambda.java import java.util.*; public class Lambda { public static void main(String[] args) { Comparator<String> c = (x, y) -> x.length() - y.length(); System.out.println(c.getClass()); } } $ javac Lambda.java && java Lambda class Lambda$$Lambda$1
13.
生成のタイミング • loadClass(name) すると、ラムダ式を実行する タイミングでラムダのクラスが出現しているこ とが分かります 12 $
cat >Lambda.java ... System.out.println(loadClassOrNull("Lambda$$Lambda$1")); Comparator<String> c = (x, y) -> x.length() - y.length(); System.out.println(loadClassOrNull("Lambda$$Lambda$1")); ... $ javac Lambda.java && java Lambda null class Lambda$$Lambda$1
14.
ラムダ式実行の過程 • ラムダ式を実行するタイミングで、ラムダのク ラスが生成されていることが分かりました • ではラムダ式は、バイトコードのレベルでは、ど のような過程で実行されているのでしょうか? 13
15.
ラムダ式のバイトコード • ラムダ式を含むプログラムのクラスファイルを、 javap コマンドで逆アセンブルします 14 $
cat >Lambda.java import java.util.function.*; class Lambda { IntUnaryOperator adder(int delta) { return n -> n + delta; } } $ javap -c -p Lambda.class ... (次ページ) ...
16.
javap による逆アセンブルの結果 15 class Lambda
{ ... java.util.function.IntUnaryOperator adder(int); Code: 0: iload_1 1: invokedynamic #2, 0 6: areturn private static int lambda$0(int, int); Code: 0: iload_1 1: iload_0 2: iadd 3: ireturn }
17.
再度 Java プログラム風に解釈 •
ラムダの処理の中身は lambda$0 というメ ソッドに記述されます • ラムダ式の実行は invokedynamic 命令の呼 び出しになっています 16 class Lambda { IntUnaryOperator adder(int delta) { return <invokedynamic>(delta); } private static int lambda$0(int delta, int n) { return n + delta; } }
18.
ここまでの整理 • 分かったこと – ラムダのクラスはラムダ式実行の際に生成されま す –
ラムダ式の実行は invokedynamic 命令です • 推定できること – invokedynamic 命令をきっかけとして、ラムダの クラスが生成され、またラムダのインスタンスが生 成されるはずです 17
19.
invokedynamic の復習 18
20.
invokedynamic の復習 • ラムダ式実行の流れを追いかけるにあたり、 まずは
invokedynamic をおさらいします 19
21.
invokedynamic とは • 本来は、
JRuby など、 Java 以外の言語処理 系のために、 Java SE 7 で追加されたメソッド 呼び出し命令です • invokevirtual, invokeinterface など、 Java SE 6 までのメソッド呼び出し命令と異なり、呼び 出す処理が実行時に選択できます 20
22.
Java のメソッド呼び出し手順 • どの呼び出し命令でも、手順は大体同じです 21 int
result = receiver.doSomething(arg0, arg1); receiver arg0 receiver arg1 arg0 receiver 戻り値 invokexxx レシーバと引数をスタックに積む 呼び出し 結果も スタックに void 以外の場合
23.
Java SE 6
までの呼び出し命令 • Java SE 6 までの呼び出し命令は、いずれも Java 言語と密に結びついてます – メソッドは再定義されない – 名前、引数の型、レシーバのクラスが決まれば、呼 び出すべき処理が定まる 22 invokestatic static メソッドを呼び出す invokespecial コンストラクタ、 private メソッド等を呼び出す invokevirtual クラスに属するメソッドを呼び出す invokeinterface インタフェースに属するメソッドを呼び出す
24.
Java 以外の言語処理系の実装 ―Java SE
6 以前 • Java 言語にない機構(メソッド再定義など)を 実現するため、処理系が呼び出しに介入 →JVM による実行時最適化が効きづらい 23 array.join invoke virtual 処理系 size Func@42 join Func@123 検索 def join ... invoke virtual 関数テーブル
25.
Java 以外の言語処理系の実装 ―Java SE
7 以降 • invokedynamic を使って、処理系を介さずに、 直接メソッドが呼び出せるようになりました →JVM による実行時最適化が効きやすい! 24 array.join invokedynamic def join ...
26.
invokedynamic の道具立て • 呼び出し元
(CallSite) ごとに、ブートストラップ メソッドで、呼び出し先の関数ポインタ (MethodHandle) を登録 25 Method Handle オブジェクト CallSite オブジェクト ブートストラップ メソッド <<create>> 初回呼び出しの前に 実行 対象の 処理 呼び出し元 <<create>> 呼び出し
27.
ブートストラップメソッド • static である必要がある •
ブートストラップメソッドの引数 – Lookup: MethodHandle のファクトリ – String: 「メソッド名」だが、使わなくても可 – MethodType: invokedynamic の引数型と戻り値型 – 任意個数の定数 • ブートストラップメソッドの戻り値 – MethodHandle の初期値が紐付けられた CallSite 26
28.
ブートストラップメソッドの例 • メソッドを呼び出した後、強制的に戻り値を 42 にする
MethodHandle を生成 27 static CallSite bsm(Lookup lu, String name, MethodType mt) throws Exception { MethodHandle vmh = lu.findVirtual(mt.parameterType(0), name, vmt); return new ConstantCallSite(filterReturnValue(vmh, dropArguments(constant(int.class, 42), 0, int.class))); } • 以上のように、個々の invokedynamic の動作は、 ブートストラップメソッドを見れば見当が付きます
29.
ラムダ式の実行 (2) 28
30.
ラムダ式の invokedynamic • 先ほど見たところでは、ラムダ式の実行は、 invokedynamic
命令の実行として実装され ていました →紐付けられているブートストラップメソッドを見 れば、実際の動作がわかるはずです 29
31.
ラムダ式の実行の流れ • ラムダ式の実行の invokedynamic
には、 java.lang.invoke.LambdaMetaFactory の metaFactory メソッドがブートストラップメソッ ドとして紐付いています 30 invoke dynamic <<ブートストラップ>> LambdaMetaFactory #metaFactory ラムダの インスタンス化 2 回目以降の 実行 1. ラムダのクラスを生成 2. ラムダをインスタンス化する MethodHandle を生成
32.
LambdaMetaFactory #metaFactory 31 CallSite metafactory(Lookup lookup,
// MethodHandle のファクトリ String name, // 関数型インタフェースの唯一の抽象メソッド (SAM) の名前 (例: compare) MethodType invokedType, // 命令の引数・戻り値型 MethodType samMethod, // SAM の引数・戻り値型 MethodHandle implMethod, // 処理本体のメソッド (例: lambda$0) MethodType instantiatedSamType) // 型パラメータ適用後の SAM の引数・戻り値型 シグネチャ 1. これらの情報を元にラムダのクラスを生成 • 引数をフィールドに格納するコンストラクタ • 処理本体のメソッドを呼び出す SAM の実装 2. ラムダをインスタンス化する MethodHandle を生成、 CallSite に紐付け
33.
最終的に実行される処理 32 class Lambda { static
class Lambda$1 implements IntUnaryOperator { private final int delta; Lambda$1(int delta) { this.delta = delta; } @Override public int applyAsInt(int n) { return lambda$0(this.delta, n); } } IntUnaryOperator adder(int delta) { return <invokedynamic: new Lambda$1(delta)>; } private static int lambda$0(int delta, int n) { return n + delta; } } metaFactory が生成 → 結局、やってることは匿名クラスと(ほぼ)同じ!
34.
なぜ invokedynamic? 33
35.
なぜ invokedynamic? • invokedynamic
によるラムダ式の実行は、動 作としては匿名クラスと似たようなものでした • なぜ、わざわざ invokedynamic を使うので しょうか? →(1) クラスファイルが少なくなるおかげで、起動が 速くなる、かもしれません →(2) JVM が LambdaMetaFactory を独自に実装 することで、最適なインスタンス生成の方法を選 択できるようになります 34
36.
(1) 起動時間 • Java
SE 8 では、 Streams API の採用によって、 プログラム中で全面的にラムダ式が利用され ることが想定されています(実態はどうあれ!) • その際、ラムダ式を匿名クラス方式で実装す ると、クラスファイルの数が飛躍的に増えるた め、クラスローディングが遅くなってしまいます • invokedynamic で、クラスを実行時に生成す れば、起動時間が抑えられる、かもしれません 35
37.
匿名クラスとラムダ式の起動時間比較 • 5,000 個の匿名クラス/ラムダをインスタンス 化するプログラムを実行(各10回) 36 平均 2,041ms 2,375ms CPU:
Core i3-2120T (2.6 GHz) OS: Arch Linux, カーネル: 3.9.9-1-ARCH JVM: JDK-8 build b99 (64-bit)
38.
匿名クラス<ラムダ式 の考察 • 匿名クラスの実行時間増加要因 A)
I/O B) jar の解凍 • ラムダ式の実行時間増加要因 C) ブートストラップメソッド呼び出し(それにともな う MethodHandle 作成など) D) バイトコード生成 37 A+B < C+D となった?
39.
(2) インスタンス生成戦略の選択 • LambdaMetaFactory
は JVM が提供する API です。したがって、実行時に JVM に都合 のよい方法でインスタンスが生成できます • 可能な選択肢: – 1 つのラムダ式ごとに 1 つのクラスを生成(既述) – 外部の値を参照しないラムダ式であれば、シング ルトンインスタンスを戻す(後述) 38
40.
シングルトンインスタンス • 次のラムダ式は、外側の変数に依存していな いため、何度実行しても、同じ働きのインスタ ンスを戻します →この場合、シングルトンインスタンスを毎回使 い回せばいいはずです 39 Comparator<String> comparator()
{ return (x, y) -> x.length() - y.length(); }
41.
シングルトンインスタンス: 実行の流れ • ラムダの処理の本体が、外側の変数に依存し ていない場合、ラムダ式はシングルトンインス タンスを戻します 40 invoke dynamic <<ブートストラップ>> LambdaMetaFactory #metaFactory シングルトン インスタンス 2
回目以降の 実行 1. ラムダのクラスを生成 2. ラムダのシングルトンインスタンスを生成 3. シングルトンインスタンスを戻す MethodHandle を生成
42.
シングルトンインスタンス: 確認 41 $ cat
>Lambda.java import java.util.*; public class Lambda { static Comparator<String> comparator() { return (x, y) -> x.length() - y.length(); } public static void main(String[] args) { System.out.println(comparator()); System.out.println(comparator()); System.out.println(comparator()); } } $ javac Lambda.java && java Lambda Lambda$$Lambda$1@84aee7 Lambda$$Lambda$1@84aee7 Lambda$$Lambda$1@84aee7
43.
その他の可能なインスタンス生成戦略 • 1 つの関数型インタフェースごとに
1 つのクラ スを生成。リフレクション経由で処理本体を呼 び出し • MethodHandle を関数型インタフェースに直 接ラップする機構を用意して、それを使う 42
44.
ラムダの直列化 43
45.
ラムダの直列化 • 関数型インタフェースが Serializable
を拡張 している場合、ラムダのインスタンスは直列化 できる必要があります – 直列化(ラムダ→バイト列)、非直列化(バイト列→ ラムダ)した時、元のラムダと同じように機能する 必要がある • ラムダのクラスが実行時に生成される時、どう したら直列化・非直列化できるのでしょうか? → writeReplace / readResolve を使う 44
46.
直列化の流れ 45 ラムダ インスタンス SerializedLambda バイト列 writeReplace インタフェース名、処理本体 のメソッド名など、ラムダを構 成する静的情報を保持 defaultWriteObject
47.
非直列化の流れ 46 defaultReadObject ラムダ インスタンス SerializedLambdaバイト列 ★ ★: 静的情報を元にラムダを復元 SerializedLambda ラムダ式を含むクラス ラムダ readResolve $deserializeLambda$ <<create>> invokedynamic コンパイル時に生成
48.
総括 47
49.
総括 • ラムダ式は匿名クラスの単純な構文糖ではあ りません。 invokedynamic
命令を使って、クラ スを実行時に生成しています • これにより、 JVM がラムダのインスタンスの生 成方法を選べるので、実行時最適化の余地 が大きくなります 48
50.
参考文献 49
51.
参考文献 • Java SE
8 API Specification – http://download.java.net/jdk8/docs/api/overview-summary.html • JSR-335 – http://jcp.org/en/jsr/detail?id=335 • Brian Goetz “From Lambdas to Bytecode” – http://wiki.jvmlangsummit.com/images/1/1e/2011_Goetz_Lambd a.pdf • 宮川 拓「Lambda 式に invokedynamic を使うのかもしれな い話」 – http://d.hatena.ne.jp/miyakawa_taku/20120728/1343478485 50
Download