Skip to content

archiecobbs/javabox

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

62 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

JavaBox

Scripting in Java, by Java, for Java

What is it?

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 as Java source code snippets. JavaBox does not provide a secure sandbox; it's not safe for untrusted code.

Instead, 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 having the ability to restrict unwanted functionality like network I/O, System.exit(), etc.

How does it Work?

Each JavaBox instance relies on an underlying JShell instance configured for local execution mode. That means JavaBox scripts are really JShell scripts that happen to be executing on the same JVM instance. Unlike normal JShell scripts, which can only return strings, JavaBox scripts can return arbitrary Java objects, and those objects can then be used outside of the scripting environment.

JavaBox supports imposing restrictions on scripts using Controls. Controls are allowed to intercept a script's class loading step as well as each time it executes.

JavaBox supports interrupting scripts in the middle of execution if necessary, and it also has suspend and resume functions, allowing an application thread to suspend scripts on certain operations and forcibly regain control.

Examples

Here's a "Hello, World" example:

Object returnValue;
try (JavaBox box = new JavaBox(Config.builder().build())) {
    box.initialize();
    box.setVariable("target", "World");
    String script = "String.format(\"Hello, %s!\", target);";
    returnValue = box.execute(script).returnValue();
}
System.out.println(returnValue);     // prints "Hello, World!"

Here's an example that shows how to use a TimeLimitControl to kill a script that takes too long:

// Set up control
Config config = Config.builder()
  .withControl(new TimeLimitControl(Duration.ofSeconds(5)))
  .build();

// A script that takes too long
String script = """
    while (true) {
        Thread.yield();
    }
""";

// Execute the script
ScriptResult result;
try (JavaBox box = new JavaBox(config)) {
    box.initialize();
    result = box.execute(script);
}

// Check the result of script execution
switch (result.snippetOutcomes().get(0)) {
    case SnippetOutcome.ExceptionThrown e when e.exception() instanceof TimeLimitExceededException
      -> System.out.println("script was taking too long");
}

Caveats

  • The controls module requires Java 24+ because it uses the new ClassFile API; everything else requires JDK 17+.

Where do I get it?

JavaBox is available from Maven Central.

More Information

Releases

Packages

Used by

Contributors

Languages