introduction to jshell #javadaytokyo #jdt_jshell
TRANSCRIPT
#jdt_jshell Question: https://sli.do/
Introduction to JShell:the Java REPL Tool吉田 真也(@bitter_fox, @shinyafox)OpenJDK Committer(JDK9, Kulla)立命館大学 大学院 情報理工学研究科#jdt_jshell
#jdt_jshell Question: https://sli.do/
アジェンダ
●Introduction to JShell●Inside of JShell●Integration of JShell
#jdt_jshell Question: https://sli.do/
他の環境では?
●Read-Eval-Print Loop(REPL)ツール
–Python, Ruby, Haskell, Scala, Groovy, Clojure, etc…–各言語のプログラムの一部を入力–その場で実行し,結果を出力
●教育分野ではREPLツールがある環境が人気
–REPLがないために,Javaの人気低下
API,構文挙動確認
プロトタイプ開発
プレゼン教育
#jdt_jshell Question: https://sli.do/
JShell
●JavaのREPLツール
–Javaコードを逐次実行できる
●JDK9 EA is available–http://jdk.java.net/9/–注:Win, Macでは,環境が壊れる可能性
–2017/07/27 General Availability???
API,構文挙動確認
プロトタイプ開発
プレゼン教育
#jdt_jshell Question: https://sli.do/
例(Demo)
jshell> int k = 14k ==> 14
jshell> long fibo(int n) { ...> return n <= 1 ? n : fibo(n-1)+fibo(n-2); ...> }| 次を作成しました: メソッド fibo(int)
jshell> fibo(3)$3 ==> 2
jshell> fibo(k)$4 ==> 377
#jdt_jshell Question: https://sli.do/
Javaコード
Import宣言
Class/Interface/Enum/Annotation宣言
フィールド宣言
メソッド宣言
ブロック
文
式
Package宣言
#jdt_jshell Question: https://sli.do/
JShellで実行できるJavaコード
Import宣言
Class/Interface/Enum/Annotation宣言
フィールド宣言
メソッド宣言
ブロック
文(変数宣言はフィールド宣言)式
Package宣言
#jdt_jshell Question: https://sli.do/
フィールド宣言(変数宣言)/式
jshell> int MAX;
MAX ==> 0●フィールド宣言なので初期値0
jshell> int MAX = 300
MAX ==> 300●セミコロンの省略が可能
jshell> MAX / 2
$1 ==> 150●式の結果は一時変数$nに
#jdt_jshell Question: https://sli.do/
Import宣言
jshell> import java.time.*;
jshell> import java.nio.LocalDate
#jdt_jshell Question: https://sli.do/
Class/Enum/Interface/Anno宣言
jshell> class Student { ...> int age; ...> String name; ...> }| created class Student
jshell> final class MyUtil {}| 警告:| 修飾子'final' は、トップ・レベル宣言で使用できません。無視されます
| final class MyUtil {}| ^---^| 次を作成しました: クラス MyUtil
●一部の修飾子(public, finalなど)は無視される
#jdt_jshell Question: https://sli.do/
メソッド宣言
jshell> int f(int n) {return n*2;}
| created method f(int)
jshell> f(100)
$2 ==> 200
●一部の修飾子(public, finalなど)は無視される
#jdt_jshell Question: https://sli.do/
宣言の更新
メソッドやクラスの定義は後から変えられる
jshell> int f(int n) {return n*2;}
| created method f(int)
jshell> f(100)
$2 ==> 200
jshell> int f(int n) {return n*n;}
| modified method f(int)
jshell> f(100)
f(100)
$4 ==> 10000
#jdt_jshell Question: https://sli.do/
前方参照
●宣言前に参照可能
jshell> class Professor { ...> List<Student> myStudents; ...> }| 次を作成しました: クラス Professor。しかし、 class Studentが宣言されるまで、参照できません
jshell> class Student { ...> Professor myProf; ...> }| 次を作成しました: クラス Student
jshell> new Professor() ; new Student()$10 ==> Professor@e45f292$11 ==> Student@31a5c39e
ProfessormyStudents
StudentmyProf
#jdt_jshell Question: https://sli.do/
Java9LangFeature(デモ)
●識別子_はコンパイルエラー
●外部の変数をtry-w-resの対象に
AutoCloseable ac = …;
try (ac) {…}●匿名クラスでダイアモンド演算子
list = new ArrayList<>() {{add(...);}}●@SafeVarargs on private methods●private interface method
#jdt_jshell Question: https://sli.do/
JShellのコマンド
●/で始まる
●履歴/スニペットの表示/編集/保存
●設定の表示/変更
●スニペットの実行
●一意に定まれば,先頭数文字でOK–/help → \he
#jdt_jshell Question: https://sli.do/
JShellのコマンド
履歴/スニペットの表示/編集/保存
●/vars, /methods, /types, /imports●/list●/history●/edit●/drop●/save
スニペットの実行
●/open
●/!
●/<id>
●/-<n>
その他
●/help
●/?
●/exit
設定の表示/変更
●/env
●/reset
●/reload
●/set
#jdt_jshell Question: https://sli.do/
JShellのコマンド
履歴/スニペットの表示/編集/保存
●/vars, /methods, /types, /imports●/list●/history●/edit●/drop●/save
スニペットの実行
●/open
●/!
●/<id>
●/-<n>
その他
●/help
●/?
●/exit
設定の表示/変更
●/env
●/reset
●/reload
●/set
#jdt_jshell Question: https://sli.do/
JShellのコマンド:/help
jshell> /help| Java言語の式、文または宣言を入力します。
| または、次のコマンドのいずれかを入力します:| /list [<name or id>|-all|-start]| 入力したソースをリストします
(...)
jshell> /help /list| /list| スニペットIDが付くスニペットのソースを表示します。
| | /list| 入力した、または/openで読み取ったコードの現在アクティブなスニペットをリストします
| /list -start| 自動的に評価された起動スニペットをリストします
| /list -all| 失敗、オーバーライド済、削除済および起動を含むすべてのスニペットをリストします
| /list <name>| 指定した名前のスニペットをリストします(アクティブなスニペットのプリファレンス)| /list <id>| 指定したスニペットIDのスニペットをリストします
#jdt_jshell Question: https://sli.do/
JShellのコマンド:/list
●入力したスニペットを表示–<id> : <snippet>
jshell> /list -all s1 : import java.io.*; s2 : import java.math.*; s3 : import java.net.*; s4 : import java.nio.file.*; s5 : import java.util.*; s6 : import java.util.concurrent.*; s7 : import java.util.function.*; s8 : import java.util.prefs.*; s9 : import java.util.regex.*; s10 : import java.util.stream.*; 1 : int n = 100; 2 : System.out.println(n) e1 : this is error
#jdt_jshell Question: https://sli.do/
JShellのコマンド:/list
●入力したスニペットを表示–<id> : <snippet>
jshell> /list -all s1 : import java.io.*; s2 : import java.math.*; s3 : import java.net.*; s4 : import java.nio.file.*; s5 : import java.util.*; s6 : import java.util.concurrent.*; s7 : import java.util.function.*; s8 : import java.util.prefs.*; s9 : import java.util.regex.*; s10 : import java.util.stream.*; 1 : int n = 100; 2 : System.out.println(n) e1 : this is error
Startup
Error
#jdt_jshell Question: https://sli.do/
Startup
●最初に実行されるプログラム–設定可能–自分なりに改造すると捗る
●プリセット–DEFAULT(デフォルト)
●主なパッケージのインポート
–PRINTING●出力関数(printlnなど)の定義
–JAVASE●Java SEのパッケージをすべてインポート●awtのせいでListがFQCNでしか使えなくなるので辛い
#jdt_jshell Question: https://sli.do/
JShellのコマンド:/set
●設定変更
/set <kind> [args]●<kind>
editor /editで用いるエディタの設定(emacsにすると良い)
start Startupの設定
feedback
mode
prompt
truncation
format
出力に関する設定
#jdt_jshell Question: https://sli.do/
JShellのコマンド:/set
●設定変更
/set <kind> [args]●<kind>
editor /editで用いるエディタの設定(emacsにすると良い)
start Startupの設定
feedback
mode
prompt
truncation
format
出力に関する設定
#jdt_jshell Question: https://sli.do/
JShellのコマンド:/set
/set start <file>…
/set start ~/file1.jsh–file1.jshが起動時に実行
/set start DEFAULT ~/file1.jsh–プリセット(DEFAULT, PRINTING, JAVASE)も指定可能
–DEFAULT, file1.jshの順で起動時に実行
●反映させるには/reset, /reload
●jshellを終了させると,元の設定に戻る
–永続化には永続化オプション(-retain)が必要
#jdt_jshell Question: https://sli.do/
JShellのコマンド:/set -retain
●設定の永続化
/set <kind> -retain [args]
/set start -retain file1.jsh
/set start -retain DEFAULT file1.jsh
#jdt_jshell Question: https://sli.do/
実行時オプション
●起動時の設定
--class-path <path>
--module-path <path>
--add-modules <module>(,<module>)*
--startup <file>
--no-startup
--feedback <mode>
-s, -q, -v 出力モードの指定(非常に簡潔,簡潔,詳細)
-J<flag> 実行時システムオプション
-R<flag> リモート実行時システムオプション
-C<flag> コンパイラオプション
--help, -X ヘルプの表示(-Xは非標準オプションヘルプ)
--version
#jdt_jshell Question: https://sli.do/
実行時オプション
●起動時の設定
--class-path <path>
--module-path <path>
--add-modules <module>(,<module>)*
--startup <file>
--no-startup
--feedback <mode>
-s, -q, -v 出力モードの指定(非常に簡潔,簡潔,詳細)
-J<flag> 実行時システムオプション
-R<flag> リモート実行時システムオプション
-C<flag> コンパイラオプション
--help, -X ヘルプの表示(-Xは非標準オプションヘルプ)
--version
#jdt_jshell Question: https://sli.do/
外部ライブラリ
●--class-path(-c)か--module-path(-m)
–フォーマットは他ツールと同様
–-mの場合,--add-modulesで利用するモジュールも指定
$ jshell\> -c=~/.m2/repository/com/google/guava/\> guava/19.0/guava-19.0.jar
jshell> import com.google.common.base.Strings
jshell> Strings.commonPrefix("java", "jshell")$3 ==> "j"
#jdt_jshell Question: https://sli.do/
jshell> Introduction to JShell ...> Completion & Documentation
#jdt_jshell Question: https://sli.do/
補完機能
●コード補完/シグネチャ/Javadoc表示
–Tab●import補完
–Shift-Tab i●変数定義の補完
–Shift-Tab v
#jdt_jshell Question: https://sli.do/
コード補完/シグネチャ/Javadoc表示
jshell> IntStream.range([Tab]
n number
Signatures:IntStream IntStream.range(int startInclusive, int endExclusive)
<press tab again to see documentation>
jshell> IntStream.range([Tab]IntStream IntStream.range(int startInclusive, int endExclusive)Returns a sequential ordered IntStream from startInclusive (inclusive) to endExclusive(exclusive) by an incremental step of 1 .
Parameters:startInclusive - the (inclusive) initial valueendExclusive - the exclusive upper bound
Returns:a sequential IntStream for the range of int elements
<press tab again to see all possible completions; total possible completions: 546>
jshell> IntStream.range([Tab]AbstractCollection AbstractExecutorService AbstractList AbstractMap AbstractMethodError
候補とシグネチャ
Javadoc
すべての候補
#jdt_jshell Question: https://sli.do/
デモ
●Stream.o([Tab]
–Stream.of●Stream.of([Tab]●Stream.of(Color[Shift+Tab i]
–Import java.awt.Color●Stream.of(Color.GR[Tab]
–Choose GREEN●Stream.of(Color.GREEN).collect(Collectors.toList())[Shift+Tab v]
–List<Color> | =...
#jdt_jshell Question: https://sli.do/
JShellの仕組み
JShell Tooljline
int a = 0
a ==> 0
JShell Core Impl
JSh
ell AP
I
Is Complete?CompletionDocumentationEval & Result
JdiExecutionControl
Compiler(javac)
RemoteExecutionControl
JVM
int a = 0
Compiler API
SP
I
JDPA
JDI
#jdt_jshell Question: https://sli.do/
snippet()
JShell API
JShell
SourceCodeAnalysis
SnippetEvent
XxxSnippet
eval(), d rop()
sourceCodeAnalysis()
state
#analyzeCompletion()#analyzeType()#completeSuggesions()#documentation()#listQualifiedNames()
#jdt_jshell Question: https://sli.do/
デモ
JShellAPIをJShellから叩く
JShell js = JShell.create()
js.eval(“int n = 0;”)
#jdt_jshell Question: https://sli.do/
Inside eval()int a = 0 Snippet.Kindを決定
Snippetを作成
ラップしたJavaコード
クラスファイル
依存性を検索再コンパイル
Exec.Controlで実行
クラスをロード
実行
SnippetEventを作成
ExecutionControl
a ==> 0
#jdt_jshell Question: https://sli.do/
ヒミツのコマンド:/debug(デモ)
jshell> /debug
| Debugging on
jshell> int n=0
Compiling: int n = 0;
Kind: VARIABLE -- int n=0
compileAndLoad [Unit(n)]
++setCompilationInfo() Snippet:VariableKey(n)#1-int n=0;
package REPL;
class $JShell$1 {
public static int n;
public static Object do_it$() throws Throwable {
int n_ = 0;
return n = n_;
}
}
-- diags: []
setStatus() Snippet:VariableKey(n)#25-int n = 0; - status: VALID
compileAndLoad ins = [Unit(n)] -- legit = [Unit(n)]
Compiler generating class REPL.$JShell$25
compileAndLoad [Unit(n)] -- deps: [] success: true
recordCompilation: Snippet:VariableKey(n)#25-int n = 0; -- status VALID, unresolved []
n ==> 0
#jdt_jshell Question: https://sli.do/
ヒミツのコマンド:/debug(デモ)
jshell> /debug
| Debugging on
jshell> int n=0
Compiling: int n = 0;
Kind: VARIABLE -- int n=0
compileAndLoad [Unit(n)]
++setCompilationInfo() Snippet:VariableKey(n)#1-int n=0;
package REPL;
class $JShell$1 {
public static int n;
public static Object do_it$() throws Throwable {
int n_ = 0;
return n = n_;
}
}
-- diags: []
setStatus() Snippet:VariableKey(n)#25-int n = 0; - status: VALID
compileAndLoad ins = [Unit(n)] -- legit = [Unit(n)]
Compiler generating class REPL.$JShell$25
compileAndLoad [Unit(n)] -- deps: [] success: true
recordCompilation: Snippet:VariableKey(n)#25-int n = 0; -- status VALID, unresolved []
n ==> 0
入力を解析し,種類を判別
対応するSnippet作成
Snippetに応じた
Wrap
コンパイル依存性解析
#jdt_jshell Question: https://sli.do/
JavaFX on JShell
●JavaFXをJShellから使いたいけど・・・
jshell> new javafx.stage.Stage()
| java.lang.ExceptionInInitializerError thrown
| at Window.<init> (Window.java:1380)
| at Stage.<init> (Stage.java:239)
| at Stage.<init> (Stage.java:227)
| at (#1:1)●JavaFXのスレッドから呼び出さないといけない!
#jdt_jshell Question: https://sli.do/
JShellの仕組み
JShell Core ImplJdiExecutionControl
Compiler(javac)
RemoteExecutionControl
JVM
new Stage()
Compiler API
SP
I
JDPA
JDI
#jdt_jshell Question: https://sli.do/
JavaFXSupportsForJShell
●JavaFXを動かせるJShellプラグイン
–https://github.com/bitterfox/JavaFXSupportsForJShell
JShell Core ImplJdiExecutionControl
Compiler(javac)
JavaFXRemoteExecutionControl
JVM
Platform.runLater
Compiler API
SP
I
JDPA
JDI
new Stage()
#jdt_jshell Question: https://sli.do/
JShell with Maven and dependencies
● https://github.com/bitterfox/jshell-maven-plugin– プロジェクトのクラスと,依存するjarを含めてjshellを実行
● pom.xml <build> <plugins> <plugin> <groupId>net.java.openjdk.shinyafox</groupId> <artifactId>jshell-maven-plugin</artifactId> <version>1.0-SNAPSHOT</version> </plugin> </plugins> </build>
● $mvn jshell:compile
#jdt_jshell Question: https://sli.do/
JShell with Gradle and dependencies
●https://github.com/bitterfox/jshell-gradle-plugin
–プロジェクトのクラスと,依存するjarを含めてjshellを実行
●build.gradle plugins { id "net.java.openjdk.shinyafox.jshell.gradle.plugin" version "1.0.3" }
●$ ./gradlew --no-daemon --console plain jshell
●注:gradleとJDK9の相性が悪くて動かない場合あり
#jdt_jshell Question: https://sli.do/
まとめ
●JShellで快適Javaプログラミング
●JShellはOSS&拡張可能
●Please Try JShell & Give Me Feedback!–http://jdk.java.net/9/
#jdt_jshell Question: https://sli.do/
Q&A質問はsli.doの#jdt_jshellで頂いたました
原文のママ掲載しております皆さん,多数のご質問ありがとうございました
#jdt_jshell Question: https://sli.do/
●jshellはスクリプトファイルにできるのかな?–できます.
–jshell hoge.jsh●ファイルの最後に/exitを入れると綺麗に動く
–jshell内では/open hoge.jsh–詳しくはヘルプをご参照ください.
●「教育ツール」「開発時の便利ツール」以外の用途はありますか?
–jshellをコンソールアプリケーションのベースに利用するというユースケースがありました
● https://github.com/YaSuenag/heapstats-shell–この他にも皆さんにご利用いただく中で面白い使い方が出てくるかもしれません
その際にはぜひ共有していただけると幸いです
#jdt_jshell Question: https://sli.do/
●jshell内でThreadを生成して実行したらどうなる?–普通に実行できます
–thread.start()を実行後すぐにプロンプトが帰ってきます
–スレッド内でSystem.outへ出力している場合は,出力メソッドがよばれたタイミングでコンソールに出力されます
–jshell> new Thread(() -> {
...> try {
...> Thread.sleep(1000);
...> System.out.println("hoge");
...> } catch (Exception e) {}
...> }).start()
–jshell> hoge
#jdt_jshell Question: https://sli.do/
●いつも使うようなライブラリ(commonsなど)を常にパスに通しておくような機能はありますか?
–プレゼンでは,「綺麗にはできない」と回答しましたが,比較的綺麗にできました
–/envコマンドでのパス指定をスタートアップに含めていただくと綺麗に行なえます
–start.jsh
/env -class-path --class-path /home/bitter_fox/dev/jdt2017/keynote/target/classes
–$jshell -startup start.jsh
| JShellへようこそ -- バージョン9-ea
–| 概要については、次を入力してください: /help intro–
–jshell> import keynote.*–
–jshell>
#jdt_jshell Question: https://sli.do/
●JShellの仕組みで、RemoteExectuionControlで別のJVMを呼び出す理由について教えてください。
–別のJVMでユーザコードを実行することによって,JShell APIを実行するJVMへのユーザコードの影響を最小限にするためです.
–例えば,同一のJVMでユーザコードを実行すると,「System.exit(0)」がよばれると,JShell APIを呼び出すJVMまで終了してしまいます
●JShellと関係ないですが、シェルを実行しているアプリはなんでしょうか?(画面上からビロっとでてくるやつ)
–ウィンドウマネージャにXMonadを使用しています
–そのカスタマイズのうちの機能の1つです
#jdt_jshell Question: https://sli.do/
●thisは使えますか? 使えたら、なにをさしますか?–使えません
●JShellの仕様策定や開発過程で壁(難しかったこと)などあったのでしょうか?
–発表時に回答から漏れてしまい申し訳ありません
–Project Leaderではないため,なかなか詳細には答えにくいですが,
前方参照や宣言の更新,Javadoc機能などはかなり実装が辛かったように見えました
–また,補完機能のためのjarファイル解析によって起動に時間がかかる問題の解決も難しかったように見えました
#jdt_jshell Question: https://sli.do/●何度もメソッドを書き直した結果の、「最新」のメソッド定義を見たいときも /list ですか?
–はい./listで確認いただけます.
–/listの後に確認したいメソッドの名前を指定することでその名前の定義だけを確認できます
–jshell> /list m
3 : void m() {int n = 100;}
jshell> void m() {int n = 200;}
| 次を変更しました: メソッド m()
jshell> /list m
4 : void m() {int n = 200;}
–最新のメソッド定義の「シグネチャ」を確認したい場合は/methodを利用ください
–jshell> /method–| void m()
#jdt_jshell Question: https://sli.do/
●セミコロンが省略できない場面は?–;が入力の末尾に予期される場合のみ利用できます
–以下のような場面では省略できません–クラス宣言,メソッド宣言,ブロック文内
jshell> class C{ ...> int n = 0; ...> void m() { ...> int i = 0; ...> if (i == 0) { ...> System.out.println(i); ...> } ...> } ...> }
–必要の式,文を1行で書く場合の末尾以外の;–jshell> int n = 0 ; System.out.println(n)–n ==> 0–0
#jdt_jshell Question: https://sli.do/
●教育、プロト開発用ではなく、製品版での利用は想定されていないのでしょうか
–想定されていません–公式にはお勧めされませんが,自己責任の元で利用いただけるかと思います
–より詳細にはJDKベンダにお問い合わせいただくのが確実です
●groovyConsoleでも限りなくJavaに近い形で実行できるのですが、Javaで新たにjConsoleが追加されて差分やメリットが今のところ見えてないのです。どの辺がgroovyConsoleと比べてメリットなのでしょうか?
–jshellとの比較とのことですので,groovysh–メリットとしては「Java」言語での教育の場面でご利用いただけたり,
より強力な補完機能がご利用いただけます
–(と言っても僕はあまりgroovyshを使いこなした訳ではないので,
より詳細にはわからないです)–どちらにも一長一短あるかと思いますので,ぜひjshellも試してみてください
–そして,その結果を共有して頂けると助かります
#jdt_jshell Question: https://sli.do/●一度importしたクラスを後でimportから外すことはできますか。
–/dropコマンドにて行なえます
–例は次の質問で
●java.awtをimportから外すことも頑張れば可能に?
jshell> List<String> strings| エラー:| Listの参照はあいまいです| java.util のインタフェース java.util.Listとjava.awtのクラスjava.awt.Listの両方が一致します| List<String> strings;| ^--^
jshell> /drop s2●s2はimport java.awt.*のid
jshell> List<String> stringsstrings ==> null
#jdt_jshell Question: https://sli.do/●jshellのスクリプトファイルをステップ実行できますか?
–残念ながら行えません–後日機会があればフィードバックとして開発者MLで共有しようと思います
●jshell をファイルから読み込む時にargsを使用することはできますか?
–mainメソッドのargsでしょうか?
–ファイル読み込み時にはエントリーポイント(public static void main(String… args))があってもそれを実行しません
–そのためファイル読み込み時にコマンドラインオプションやjshellオプションからargsを指定することはできません
●class Professor{ String name; Student student; }
class Student{ String name; }
Professor professor = new Professor()
professor.name = "ゆうぽん"
これも動きます
jshell> class Professor{ String name; Student student; }| 次を作成しました: クラス Professor 。しかし、 class Studentが宣言されるまで、参照できません
jshell> class Student{ String name; }| 次を作成しました: クラス Student
jshell>
jshell> Professor professor = new Professor()professor ==> Professor@2f686d1f
jshell> professor.name = "ゆうぽん"$1 ==> "ゆうぽん"
#jdt_jshell Question: https://sli.do/
JShell’s developped by
●Engineering
–Robert Field
–Jan Lahoda●OpenJDK Committers
–Shinya Yoshida
–YOU?
●Advisors/Cheerleaders/Reviewers
–Brian Goets
–Maurizio Cimadamore
–Joe Darcy
–Paul Sandoz
–Jonathan Gibbions
–Michel Trudeau
–Sundararajan Athijegannathan
–Remi Forax
–Arun Gupta
–Mani sarkar
–Daniel Daugherty