A Bazel-based Java project demonstrating runtime code compilation and execution. This project provides an API for compiling and running Java code provided as strings, allowing dynamic code execution at runtime.
THIS PROJECT IS FOR PROTOTYPING AND EDUCATIONAL PURPOSES ONLY
This tool executes arbitrary Java code without any sandboxing or security restrictions. It is NOT SAFE for production use with untrusted input.
DO NOT:
- Use this with untrusted user input
- Deploy this in production environments
- Use this to execute code from unknown sources
- Expose this API to the internet
Potential security risks include:
- Arbitrary code execution
- File system access
- Network access
- Resource exhaustion
- System compromise
This project is designed for controlled development and prototyping environments only.
The Java Code Runner provides an API that:
- Takes Java source code as a string
- Compiles it at runtime using the Java Compiler API
- Executes the compiled code with provided inputs
- Returns the output
The code must implement BiFunction<U, D, T> where:
Uis the type of the keyDis the type of the key dataTis the type of the result
- Runtime compilation: Compile Java code on-the-fly
- Library access: Code can use Java standard library and Guava
- CLI interface: Run code from command line or files
- Built-in examples: Several working examples demonstrating different use cases
- Bazel build system: Modern, scalable build configuration
- Bazel 8+ (configured for WORKSPACE)
- JDK 11 or later (must be a full JDK, not just JRE)
Build the project:
bazel build //:clibazel run //:cli -- listbazel run //:cli -- example <example-name>Examples:
simple- String concatenationmath- Mathematical operationslist- List processing with streamsguava- Guava library usagefilter- Filtering and transforming datamap- Map data structure processing
bazel run //:cli -- file <absolute-path> <key> <keyData>Example:
bazel run //:cli -- file /path/to/java-interp/examples/Calculator.java add "15,25"Note: Use absolute paths when running code from files.
import com.example.coderunner.CodeRunner;
// Create a runner
CodeRunner<String, String, String> runner = new CodeRunner<>();
// Define code as a string
String code = """
import java.util.function.BiFunction;
public class Example implements BiFunction<String, String, String> {
@Override
public String apply(String key, String data) {
return key + ": " + data.toUpperCase();
}
}
""";
// Run the code
String result = runner.runCode("greeting", "hello world", code);
System.out.println(result); // Outputs: greeting: HELLO WORLD// Compile the code once
Class<?> compiledClass = runner.compile(code);
// Run it multiple times with different inputs
String result1 = runner.runCompiledCode("key1", "data1", compiledClass);
String result2 = runner.runCompiledCode("key2", "data2", compiledClass);Code provided to the CodeRunner must:
- Define a class (can be public or package-private)
- Implement
BiFunction<U, D, T> - Have a no-argument constructor (default or explicit)
- Not rely on external files or resources
Code executed by the runner can access:
- Java Standard Library: All
java.*andjavax.*packages - Guava: Google's core libraries (
com.google.common.*) - Collections Framework: Full access to Java Collections
- Streams API: Functional-style operations on collections
The examples/ directory contains several working examples:
Reverses a string and prepends it with the key.
bazel run //:cli -- file $PWD/examples/StringReverser.java mykey "hello world"Counts words in a string.
bazel run //:cli -- file $PWD/examples/WordCounter.java doc1 "The quick brown fox"Performs mathematical operations.
bazel run //:cli -- file $PWD/examples/Calculator.java multiply "5,7"Processes comma-separated values using Guava.
bazel run //:cli -- file $PWD/examples/ListProcessor.java mylist "apple,banana,cherry"java-interp/
├── BUILD.bazel # Bazel build configuration
├── WORKSPACE.bazel # Bazel workspace configuration
├── .bazelrc # Bazel configuration options
├── README.md # This file
├── maven_install.json # Pinned Maven dependencies
├── examples/ # Example code files
│ ├── Calculator.java
│ ├── ListProcessor.java
│ ├── StringReverser.java
│ └── WordCounter.java
└── src/main/java/com/example/coderunner/
├── CodeRunner.java # Main API
├── RuntimeCompiler.java # Compilation engine
├── CLI.java # Command-line interface
└── Examples.java # Built-in examples
The project uses the Java Compiler API (javax.tools.JavaCompiler) to compile source code at runtime:
- Source code is wrapped in a
JavaFileObject - Compilation is performed in-memory
- Compiled bytecode is stored in memory
- Classes are loaded via a custom
ClassLoader
Each compiled class is loaded in its own ClassLoader, providing basic isolation between different code executions.
- No sandboxing: Code has full access to the JVM and system
- No resource limits: Code can consume unlimited CPU/memory
- No network restrictions: Code can make network calls
- No file system restrictions: Code can read/write files
- Classpath limitations: Only pre-configured libraries are available
For a production system, consider:
- Security Manager or sandboxing (e.g., Seccomp, containers)
- Resource limits (CPU time, memory, threads)
- Network isolation
- File system restrictions
- Code signing and verification
- Rate limiting
- Audit logging
This is a prototype project for demonstration purposes. When sharing or using this code:
- Always include the security warnings
- Never deploy to production without proper sandboxing
- Document any modifications
- Test thoroughly in isolated environments
This project is provided as-is for educational and prototyping purposes.