Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

JDK9: Execute Java Code Like Unix Shell Script

DZone's Guide to

JDK9: Execute Java Code Like Unix Shell Script

How cool would it be to write Java code and save it with any readable file extension and execute it like a Unix shell script? Read on to find out!

· Java Zone
Free Resource

Just released, a free O’Reilly book on Reactive Microsystems: The Evolution of Microservices at Scale. Brought to you in partnership with Lightbend.

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()
                                +"\nIgnoring execution of above script");
        }
    }

    private String trimNewlines(String s) {
        int b = 0;
        while (b < s.length() && s.charAt(b) == '\n') {
            ++b;
        }
        int e = s.length() -1;
        while (e >= 0 && s.charAt(e) == '\n') {
            --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!

Strategies and techniques for building scalable and resilient microservices to refactor a monolithic application step-by-step, a free O'Reilly book. Brought to you in partnership with Lightbend.

Topics:
java ,shell ,unix

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}