JDK JShell

用JShell像Unix脚本一样执行Java代码

创建一个 java_shell_code.txt 的文件

不一定必须声明一个Class,可以直接写一句代码,或者创建一个方法。

  1. // java_shell_code.txt contents.
  2. /* If you observe it does not need a class declaration.
  3. Using the power of jshell, we can write functions and call functions with out creating class, just like functional programming */
  4. // You can also include comments like above, anywhere in the script
  5. String var1 = "Hello";
  6. System.out.println(var1);
  7. public int getInt1(){
  8. return 2;
  9. }
  10. public int getInt2(){
  11. return 4;
  12. }
  13. getInt1() + getInt2();
  14. public class MyClass{
  15. public void sayHelloWorld(){
  16. System.out.println("HelloWorld");
  17. }
  18. }
  19. new MyClass().sayHelloWorld()

在文件中写一些Java代码,并执行以下命令

  1. java ex.jshell.extension.JShellScriptExecutor ./java_shell_code.txt

执行结果

  1. "Hello"
  2. Hello
  3. 6
  4. HelloWorld

JShell的详细介绍

在JDK9中提供了一个新的类 JShell.java,它属于jdk.jshell模块。可以使用它执行Java代码片段,或创建一个Java方法,而不用创建一个类。如果这个Java代码片段中有错误,可以通过 Snippet.status状态(只有两种状态:REJECTED、VALID)来检查。SourceCodeAnalysis是用来解析代码的,它使用分号、解析方法、或类的声明等。
下面是JShellScriptExecutor代码。可以拷贝,并修改它。也可以从GitHub仓库中克隆。
https://github.com/kotari4u/jshell_script_executor

  1. package ex.jshell.extension;
  2. import jdk.jshell.JShell;
  3. import jdk.jshell.Snippet;
  4. import jdk.jshell.SnippetEvent;
  5. import jdk.jshell.SourceCodeAnalysis;
  6. import java.io.IOException;
  7. import java.nio.file.Files;
  8. import java.nio.file.Paths;
  9. import java.util.Objects;
  10. /**
  11. * This class can execute jshell expressions in sequence
  12. * We can write java commands like shell script and execute it.
  13. * Just write commands in a way that we give in jshell and save it in a file and execute it.
  14. *
  15. * @author Hemamabara Vamsi, Kotari
  16. * @since 5/27/2017.
  17. */
  18. public class JShellScriptExecutor {
  19. public static void main(String[] args){
  20. new JShellScriptExecutor().evaluate(args[0]);
  21. }
  22. public void evaluate(String scriptFileName){
  23. try(JShell jshell = JShell.create()){
  24. // Handle snippet events. We can print value or take action if evaluation failed.
  25. jshell.onSnippetEvent(snippetEvent -> snippetEventHandler(snippetEvent));
  26. String scriptContent = new String(Files.readAllBytes(Paths.get(scriptFileName)));
  27. String s = scriptContent;
  28. while (true) {
  29. // Read source line by line till semicolon (;)
  30. SourceCodeAnalysis.CompletionInfo an = jshell.sourceCodeAnalysis().analyzeCompletion(s);
  31. if (!an.completeness().isComplete()) {
  32. break;
  33. }
  34. // If there are any method declaration or class declaration
  35. // in new lines, resolve it.
  36. jshell.eval(trimNewlines(an.source()));
  37. // EOF
  38. if (an.remaining().isEmpty()) {
  39. break;
  40. }
  41. // If there is semicolon, execute next seq
  42. s = an.remaining();
  43. }
  44. } catch (IOException e) {
  45. e.printStackTrace();
  46. }
  47. }
  48. public void snippetEventHandler(SnippetEvent snippetEvent){
  49. String value = snippetEvent.value();
  50. if(!Objects.isNull(value) && value.trim().length() > 0) {
  51. // Prints output of code evaluation
  52. System.out.println(value);
  53. }
  54. // If there are any erros print and exit
  55. if(Snippet.Status.REJECTED.equals(snippetEvent.status())){
  56. System.out.println("Evaluation failed : "+snippetEvent.snippet().toString()
  57. +"\nIgnoring execution of above script");
  58. }
  59. }
  60. private String trimNewlines(String s) {
  61. int b = 0;
  62. while (b < s.length() && s.charAt(b) == '\n') {
  63. ++b;
  64. }
  65. int e = s.length() -1;
  66. while (e >= 0 && s.charAt(e) == '\n') {
  67. --e;
  68. }
  69. return s.substring(b, e + 1);
  70. }
  71. }

module-info.java

  1. module ex.jshell.extension{
  2. requires jdk.jshell;
  3. }