By now, most of you might have heard about JDK9 JShell. If you are not aware of it, please click here. In this article, I am going to use JShell to show you how to execute Java code like Unix script.

Let me show you an example first and then go into details:

Open a file and save it with .txt by naming it as java_shell_code.txt

Write some Java code and execute the below command by passing the file name as an argument. You don't need to declare a class. Just write statements or create methods and enjoy functional programming.

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





java_shell.code.txt

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





Output of the above script: "Hello" Hello 6 HelloWorld

Details

Let's get into the details. In JDK 9, the Java team has introduced a new class called JShell.java under the jdk.jshell module. Using this class, we can evaluate Java code snippets, and create Java methods on the fly without declaring a class. If there are any errors in the Java code snippet it will provide a Snippet.status (either REJECTED or VALID). SourceCodeAnalysis will analyze the code till the semicolon and also resolves methods or class declarations, if there are any.

Here is the JShellScriptExecutor code. Please feel free to take and extend it as you want. You can also clone it from my GitHub page.

package ex.jshell.extension; import jdk.jshell.JShell; import jdk.jshell.Snippet; import jdk.jshell.SnippetEvent; import jdk.jshell.SourceCodeAnalysis; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.util.Objects; /** * This class can execute jshell expressions in sequence * We can write java commands like shell script and execute it. * Just write commands in a way that we give in jshell and save it in a file and execute it. * * @author Hemamabara Vamsi, Kotari * @since 5/27/2017. */ public class JShellScriptExecutor { public static void main(String[] args){ new JShellScriptExecutor().evaluate(args[0]); } public void evaluate(String scriptFileName){ try(JShell jshell = JShell.create()){ // Handle snippet events. We can print value or take action if evaluation failed. jshell.onSnippetEvent(snippetEvent -> snippetEventHandler(snippetEvent)); String scriptContent = new String(Files.readAllBytes(Paths.get(scriptFileName))); String s = scriptContent; while (true) { // Read source line by line till semicolon (;) SourceCodeAnalysis.CompletionInfo an = jshell.sourceCodeAnalysis().analyzeCompletion(s); if (!an.completeness().isComplete()) { break; } // If there are any method declaration or class declaration // in new lines, resolve it. jshell.eval(trimNewlines(an.source())); // EOF if (an.remaining().isEmpty()) { break; } // If there is semicolon, execute next seq s = an.remaining(); } } catch (IOException e) { e.printStackTrace(); } } public void snippetEventHandler(SnippetEvent snippetEvent){ String value = snippetEvent.value(); if(!Objects.isNull(value) && value.trim().length() > 0) { // Prints output of code evaluation System.out.println(value); } // If there are any erros print and exit if(Snippet.Status.REJECTED.equals(snippetEvent.status())){ System.out.println("Evaluation failed : "+snippetEvent.snippet().toString() +"

Ignoring execution of above script"); } } private String trimNewlines(String s) { int b = 0; while (b < s.length() && s.charAt(b) == '

') { ++b; } int e = s.length() -1; while (e >= 0 && s.charAt(e) == '

') { --e; } return s.substring(b, e + 1); } }





module-info.java

module ex.jshell.extension{ requires jdk.jshell; }

Enjoy the power of JShell and this class and start writing Java code like a Unix script and execute it like the way we execute .sh. Hope you like it!