Running

Interactive REPL

jbang --interactive enables use of jshell to explore and use your script and any dependencies in a REPL editor.

When using --interactive for java/jar scripts/apps jbang sets up a jshell function named userMain. userMain delegates to the main function that would have been called if not running in interactive. You can call it with arguments as follows userMain(args).

One caveat about jshell is that it cannot access classes in default package. Thus you will need to add a package statement to your script/class to see it.

Flight Recorder

Flight recorder is a feature of the Java VM that lets you gather diagnostic and profiling data about your script.

You can use //RUNTIME_OPTIONS to have full control over it; but for the easiest setup jbang lets you just run with --jfr, e.g.,

jbang --jfr myapp.java

By default --jfr will start flight recorder and tell it to dump event recordings to myapp.jfr (i.e. using base name of the script as its filename).

Then you can use tools like jvisualvm or jmc to explore the data.

If you want to tweak the configuration you can pass flight recorder options, like jbang --jfr=filename={basename}.jfr,maxage=24h where {basename} will be replaced by the filename and then added maxage=24h to flight recording options.

If you want further control use //COMPILE_OPTIONS -XX:StartFlightRecording=<your options> instead.

java, javac and nativeimage Options

You can pass options directly from JBang to the compiler and runtime tools that it uses to build and run your code.

The following source tags are available for setting JVM (java) options, compiler options (javac, kotlinc, etc) and native image builders (nativeimage) respectively: //RUNTIME_OPTIONS, //COMPILE_OPTIONS and //NATIVE_OPTIONS.

You can also set the same options from the command line using: --runtime-option, --compile-option and --native-option.

As an example, if you want to enable preview features you can set up the necessary options as in the following example that uses Java 14 experimental record feature:

///usr/bin/env jbang "$0" "$@" ; exit $?
//COMPILE_OPTIONS --enable-preview -source 14
//RUNTIME_OPTIONS --enable-preview

import static java.lang.System.*;

public class records {

    record Point(int x, int y) {}

    public static void main(String[] args) {
        var p = new Point(2,4);
        out.println(p);
    }
}

Since Java 9 JDK_JAVA_OPTIONS and JDK_JAVAC_OPTIONS are also picked up by the Java runtime and compiler automatically.

For Java 8 and if you want to set explicitly only for jbang you can also add flags by setting JBANG_JAVA_OPTIONS and JBANG_JAVAC_OPTIONS respectively.

Module support (EXPERIMENTAL)

You can mark code as being part of a module by adding the following line:

//MODULE <module-name>

This will make JBang treat the code a being a module with the given name, and it will compile it as such. Any declared dependencies are automatically marked as being required.

You can also set this on the command line by using the --module=<name> option on the jbang build command. The option also exists for jbang run where it will treat anything to be run as a module.

Setting main class

Normally JBang will figure out by itself what your code’s main class is, but in case you want to override this behaviour in code, you can use the following line:

//MAIN <main-class-name>

The main class selected by the line is permanent and will be stored as the default main class in the resulting JAR file.

One can also override the main class on the command line by using --main <name> or -m <name> for jbang build or jbang run. Main classes set for jbang build are permanent, just like using a //MAIN line in the code. But main classes set for jbang run are temporary and will only be used for that execution run.

Adding entries to MANIFEST.MF

If you want to set custom entries in the MANIFEST.MF file of the Jar file generated by JBang then you can do so adding a //MANIFEST line to your source file. It takes a list of key=value items separated by spaces. If an item has no equals sign and no value than the value is taken to be the string "true".

//MANIFEST Built-By=Shadowman Sealed

(Experimental) Application Class Data Sharing

If your scripts uses a lot of classes Class Data Sharing might help on your startup. The following requires Java 13+.

Using --cds jbang will build the jar with Application Class Data Sharing enabled and when run have it load shared class data.

You can put //CDS in the java file to enable it by default, or simply use --cds to force it or --no-cds to turn it off no matter what the jbang script file contains.

Java Agents

You can activate a javaagent using --javaagent=<agent>[=<options>] where agent can be a already packaged agent jar from file, http url or Maven Coordinate.

It can also be a jbang script itself where you have put //JAVAAGENT to activate agent packaging.

You can create a basic agent using jbang init -t agent myagent.java to get started.

Remote File Arguments

The run command has a special feature where any of the arguments for the code to be executed can be a reference to a remote file by appending a % in front of a URL. Imagine for example a wordcount.java script that takes as its argument a path to a file. Now with this feature we could write:

$ jbang run wordcount.java %https://github.com/jbangdev/jbang/blob/main/README.md

JBang will download the given file to its local cache and then run the code with the path to the file substituted for the URL. It will be as if the code has suddenly acquired the feature to read and analyse remote files!

There is an alternative syntax in case the substitution needs to be part of an existing text, for example when it has to be part of a flag passed to an application:

$ jbang run analyse.java --file=%{https://github.com/jbangdev/jbang/blob/main/README.md}

In this case wrap the URL with braces to explicitly mark the beginning and end.

Remote-File for --javaagent

The remote-file syntax is also available for the --javaagent option for the run command, for example:

$ jbang —javaagent=byteman@maxandersen=script:%{https://xam.dk/myscript.btm myapp.java}

As you can see it’s necessary here to use the syntax with the braces because it’s part of larger string of text.

Escaping Remote-File Arguments

If, for some reason, you really need to be able to pass the text %http://some.url to an application without JBang downloading the file and turning it into a file path for you, then you simply add an extra % to the beginning. That will tell JBang to ignore what follows and just treat it as an ordinary string of text. For example:

$ jbang run wordcount.java %%https://github.com/jbangdev/jbang/blob/main/README.md

Would simply pass %https://github.com/jbangdev/jbang/blob/main/README.md to the script.