Scripting in Java, by Java, for Java
JavaBox tries to answer the question, “Where is the thing that will let me run scripts written in Java within my Java application?”
JavaBox is a simple container (“sandbox”) for executing scripts written in Java. JavaBox does not provide a secure sandbox; it’s not safe for untrusted code. Rather, it provides a basic sandbox that allows you to impose simple controls like time limits, instruction count limits, and restrictions on accessible classes. This allows, for example, an application to use Java as a runtime configuration language while restricting unwanted functionality like network I/O, System.exit()
, etc.
Each JavaBox instance relies on an underlying JShell configured for local execution mode. That means JavaBox scripts are really JShell scripts that happen to be executing on the same JVM instance. Unlike with normal JShell, in which scripts can only return strings, JavaBox scripts can return arbitrary Java objects, and those objects can then be used normally, outside of the container.
JavaBox supports imposing restrictions on scripts using controls. Controls are allowed to intercept a script’s class loading step and each execution it performs.
JavaBox supports interrupting scripts in the middle of execution. It also has a suspend/resume function, which allows an application thread to block script on certain operations and regain control.
Here’s a simple “Hello, World” example:
Config config = Config.builder().build();
try (JavaBox box = new JavaBox(config)) {
box.initialize();
box.setVariable("target", "World");
rv = box.execute("""
String.format("Hello, %s!", target);
""").returnValue();
}
System.out.println(rv); // prints "Hello, World!"
Here’s an example that shows how to use a TimeLimitControl
to restrict how long a script may execute:
// Set up control
Config config = Config.builder()
.withControl(new TimeLimitControl(Duration.ofSeconds(5)))
.build();
// Execute script
ScriptResult result;
try (JavaBox box = new JavaBox(config)) {
box.initialize();
result = box.execute("""
while (true) {
Thread.yield();
}
""");
}
// Check result
switch (result.snippetOutcomes().get(0)) {
case SnippetOutcome.ExceptionThrown e when e.exception() instanceof TimeLimitExceededException
-> System.out.println("script was taking too long");
}
controls
module requires Java 24+ because the Control
’s therein rely on the new ClassFile
API; everything else requires JDK 17+.JavaBox is available from Maven Central.