jeval - command line Java code evaluator. It is similar to JShell except it provides you additional functionality.

jeval allows you to execute Java code straight from the command line (same as you would do with perl -e, bash -c):

jeval -e 'out.println("Hello world")' Hello world

In JShell to achieve that you need to use additional command like echo for example:

echo 'System.out.println("Hello world")' | jshell -

Additionally with jeval you can execute complete Java shell scripts and see compilation errors if any:

cat System.out.println("Hello world"); jeval Hello world

With JShell you would have to use "/exit" in the end (otherwise it will start interactive mode):

cat System.out.println("Hello world"); /exit jshell Hello world

And JShell will not print you any errors:

cat System.out.println("Hello world"); error here /exit jshell Hello world

Another nice feature of jeval is that you can use pipes to pass data to your Java code (it binds all standard streams to support lazy reading from stdin predefined variable which is described later):

echo -e "ab\ncd\nef" | jeval -e "stdin.lines().collect(joining(\",\"))" "ab,cd,ef"

For JShell there is no default support of that.

With jeval you can pass arguments to your Java scripts and handle them in same way as you do it in Java (through global args variable similar as in main() function):

jeval -e 'format("args %s, %s", args[0], args[1])' "arg1" "arg2" "args arg1, arg2"

jeval does not require you to write class body with main method and all boilerplate code (but you still can do it if you want). You just write Java as you would do it with JShell.


You can download jeval from here


Java 11



Run following command if you use bash:

echo "export PATH=$PATH:<JEVAL_INSTALL_DIR>" >> ~/.bashrc

Or in case you use zsh:

echo "export PATH=$PATH:<JEVAL_INSTALL_DIR>" >> ~/.zshrc


Open cmd and execute following command:



jeval [ <JAVA_SCRIPT> | -e <JAVA_SNIPPET> | -i ] [ARGS]



Class path

To add new JAR files into class path use CLASSPATH env variable:

CLASSPATH=/opt/javafx-sdk-11.0.2/lib/* jeval

JVM arguments

To pass arguments to the JVM use JAVA_ARGS env variable:

JAVA_ARGS="-Dtest=hello -Xmx50m" jeval -e 'System.getProperty("test")' "hello"


jeval provides you with some additional commands which you can put to your Java script files. All of them can be called from Java comments only (it helps to keep Java code in your scripts clean an easily compilable later with javac, or within any IDEs)


This command allows you to include dependencies to any artifacts from Maven repository into the Java script files. Without need to create pom.xml or build.gradle for that.

Format of this command is:

//dependency ARTIFACT_NAME

Where ARTIFACT_NAME is a full name of the artifact in the format: <groupId>:<artifactId>[:<extension>[:<classifier>]]:<version>

Here is an example of simple script which declares dependency on snakeyaml library and uses it:

//dependency org.yaml:snakeyaml:1.21
import org.yaml.snakeyaml.*;
Yaml yaml = new Yaml();
String document = "\n- Hesperiidae\n- Papilionidae\n- Apatelodidae\n- Epiplemidae";
List list = (List) yaml.load(document);

To run:

[Hesperiidae, Papilionidae, Apatelodidae, Epiplemidae]

To provide this functionality jeval integrates with depresolve tool which depends on maven-resolver library


jeval supports "//open" command similar to "/open" command which JShell provides. For example using that command you can extract some common logic into separate script file so jeval will read that.

For example here we keep parsing functions in script called

String parseToHex(int num) {
    return Integer.toHexString(num);

And use them from script called

printf(parseToHex(123) + "\n");

Now run:


Here in we include and then call parseToHex method defined there.

Default imports

jeval by default imports following packages and static methods to the global space so you don't need to worry to import them each time manually:**


jeval comes with xfunction library and exports most of it classes and methods to global space as well.

Predefined variables

String[] args

Arguments (if any) passed to the Java script

BufferedReader stdin

This is an instance of connected to which allows you to operate with as with stream of lines which is often useful when writing scripts (see Snippets section).

Optional<Path> scriptPath

Contains path to currently executing script. It is empty when used in Java snippets (jeval with -e option)

In addition to them jeval exports following variables from xfunction library:

Predefined functions

void sleep(long msec)

Standard way to sleep in Java is pretty verbose because it throws checked exception which you need to handle:

 try {
 } catch (InterruptedException e) {
     throw new RuntimeException(e);

When you write scripts in Java you probably want it to fit in one line and wrap any thrown exception to unchecked. With this function now you can sleep like that:


void error(String msg)

Throws RuntimeException with a given message

void assertTrue(boolean expr)

If expr is false throw RuntimeException

void assertTrue(boolean expr, String message)

If expr is false throw RuntimeException with message

Stream<String> findMatches(String regexp, String str)

Search string for substrings which satisfy the regexp and return them in a stream

Predefined classes


Implements netcat operations:

static void listen(int port)

static void connect(String host, int port)

All input/output goes through stdin/stdout.

Shebang (#!)

jeval supports "#!" interpreter directive which is available in Unix-like operating systems.

It allows instead of calling jeval each time to execute Java script:


To run it directly as ordinary executable file:


For that to work you need to put following line as a first line of

#!/usr/bin/env jeval

And make file executable:

chmod u+x


Here are some examples of calling Java standard classes with jeval right from the command line.

Say hello to the world

jeval -e 'out.println("Hello world")' Hello world

Print sequence of numbers

jeval -e "range(1,10).forEach(out::println)" 1 2 3 4 5 6 7 8 9

Read XML and print value of the element using its XPath

cat << EOF > /tmp/r.xml <notes> <note> <to test="ggg1">Tove</to> </note> <note> <to test="ggg2">Bove</to> </note> </notes> EOF $ jeval -e 'out.println(XPathFactory.newInstance().newXPath().evaluate("//note/to", DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new File("/tmp/r.xml"))))' Tove

Return integer in binary format:

echo 14 | jeval -e 'Integer.toBinaryString(new Scanner(in).nextInt())' "1110"

Create temporary file and return its name

jeval -e 'Files.createTempFile(null, "tmp")' /tmp/11873450107364399793tmp

Join lines using "," as a delimeter

echo -e "ab\ncd\nef" | jeval -e "stdin.lines().collect(joining(\",\"))" "ab,cd,ef"

Execute JavaScript snippet which will read JSON and return value of specified parameter

echo '{"menu":123}' | jeval -e 'new ScriptEngineManager().getEngineByName("nashorn").eval("var v = " + stdin.lines().collect(joining("\n")) + "; v[\"menu\"]");' 123

Use Netcat and listen for incoming connection on port 12345

jeval -e "Netcat.listen(12345)"

Use commandline arguments

jeval -e 'format("args %s, %s", args[0], args[1])' "arg1" "arg2" "args arg1, arg2"

Measure execution real time

jeval -e "new Microprofiler().measureRealTime(() -> sleep(1000));"

Run command

jeval -e 'new XExec("curl -L -G -vvv").run().stderr().forEach(out::println)'

Query XML using XPath

jeval -e 'out.println(Xml.query("<notes><note><to test=\"ggg1\">Tove</to></note><note><to test=\"ggg2\">Bove</to></note></notes>", "//note/to/@test"))' [ggg1, ggg2]

Search substrings using regexp

jeval -e 'findMatches("\\d.jpg", "1.jpg 2.png 3.jpg 4.txt 5.txt").forEach(out::println)' 1.jpg 3.jpg

Run commands in parallel

Here is an example which creates 20 files with random names doing this in parallel on different threads:

jeval -e 'try (var c = new ParallelConsumer(s -> new XExec("touch /tmp/test-" + s).run().await())) {XStream.infiniteRandomStream(12).limit(20).forEach(c);}'

Generate string with length N

jeval -e 'out.println("x".repeat(1000))'


Why jeval -e 'out.format("args")' prints at the end

With -e option jeval evaluates the expression and prints its result. In this case method PrintStream::format returns reference to PrintStream so that is why it is printed.

To overcome this you can use printf method defined by jeval.

Why I get SPIResolutionException

Those are generated by JShell. Most likely you run multiple threads and some of them try to execute unresolved snippets. Wait until jeval finishes then search for its diagnostics in stderr.