boxlang-core-dev-runtime-architecture — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited boxlang-core-dev-runtime-architecture (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
BoxLang is a dynamic JVM language (JRE 21+) that compiles source to Java bytecode at runtime. The central singleton BoxRuntime acts as a service locator providing access to all core services. Understanding the architecture is essential for building modules, BIFs, interceptors, and custom language extensions.
import ortus.boxlang.runtime.BoxRuntime;
// Get the singleton instance
BoxRuntime runtime = BoxRuntime.getInstance();
// Start programmatically (e.g., in tests or embedding scenarios)
BoxRuntime runtime = BoxRuntime.getInstance( true ); // true = start immediately
// Core service accessors
runtime.getInterceptorService() // Event system
runtime.getModuleService() // Module management
runtime.getCacheService() // Cache providers
runtime.getAsyncService() // Executors, futures
runtime.getSchedulerService() // Cron scheduling
runtime.getDataSourceService() // JDBC connections
runtime.getFunctionService() // BIF registry
runtime.getComponentService() // Component/tag registry
runtime.getClassLocator() // Class resolution
runtime.getConfiguration() // Runtime config
runtime.getTypeService() // Type systemManages the global event bus. See interceptors skill for full details.
InterceptorService svc = runtime.getInterceptorService();
svc.announce( Key.of("myEvent"), dataStruct );
svc.register( myInterceptor );
svc.unregister( myInterceptor );ModuleService moduleSvc = runtime.getModuleService();
// Check if a module is loaded
boolean loaded = moduleSvc.hasModule( Key.of("bx-redis") );
// Get module record
ModuleRecord record = moduleSvc.getModuleRecord( Key.of("bx-redis") );
String version = record.version;
String physPath = record.physicalPath;
IStruct settings = record.settings;
// List all loaded modules
Set<Key> modules = moduleSvc.getLoadedModules();FunctionService fnSvc = runtime.getFunctionService();
// Register a custom BIF at runtime
fnSvc.registerGlobalFunction( Key.of("myBif"), new MyBIF() );
// Check if a BIF exists
boolean exists = fnSvc.hasGlobalFunction( Key.of("len") );
// Get a BIF instance
BIF len = fnSvc.getGlobalFunction( Key.of("len") );AsyncService asyncSvc = runtime.getAsyncService();
// Create a named executor
IBoxExecutor executor = asyncSvc.newExecutor( "myPool", ExecutorType.FIXED, 4 );
// Get an existing executor
IBoxExecutor exec = asyncSvc.getExecutor( "boxlang-tasks" );
// Create a future
BoxFuture<Object> future = asyncSvc.newFuture( () -> expensiveWork() );Every BoxLang execution has a context. Contexts form a linked chain for scope resolution.
BoxRuntime
└── ScriptingRequestBoxContext (CLI / script execution)
└── FunctionBoxContext (inside a function call)
└── ClosureBoxContext (inside a closure)
└── LambdaBoxContext (inside a lambda)
└── WebRequestBoxContext (HTTP request)
└── ApplicationBoxContext (Application.bx scope)
└── SessionBoxContext (Session scope)
└── FunctionBoxContextimport ortus.boxlang.runtime.context.IBoxContext;
import ortus.boxlang.runtime.context.FunctionBoxContext;
import ortus.boxlang.runtime.context.ScriptingRequestBoxContext;
// Traverse parent contexts
IBoxContext current = context;
while ( current != null ) {
System.out.println( current.getClass().getSimpleName() );
current = current.getParent();
}
// Find a scope nearby (walks up the context chain)
IScope localScope = context.getScopeNearby( LocalScope.name );
IScope sessionScope = context.getScopeNearby( SessionScope.name );
// Resolve a variable (checks all scopes in order)
ScopeSearchResult result = context.scopeFindNearby( Key.of("myVar"), null );
if ( result != null ) {
Object value = result.value();
IScope foundIn = result.scope();
}
// Invoke a BIF from Java code
Object result = context.invokeFunction( Key.of("len"), new Object[]{ "hello" } );When BoxLang resolves an unqualified variable name, it searches these scopes in order:
local — declared with var in current functionarguments — function parametersvariables — class/component private scopeurl, form, cgi, cookierequest — per-request shared scopesession — user sessionapplication — application-wideserver — server-wideDynamicObject wraps Java objects and provides BoxLang-style method invocation:
import ortus.boxlang.runtime.dynamic.DynamicObject;
// Wrap any Java object
DynamicObject wrapped = DynamicObject.of( new java.util.ArrayList() );
// Invoke methods
wrapped.invoke( context, "add", new Object[]{ "item" } );
Object size = wrapped.invoke( context, "size", new Object[]{} );
// Get/set fields
Object field = wrapped.getField( Key.of("fieldName") );
wrapped.setField( Key.of("fieldName"), value );All BoxLang values implement IBoxType:
import ortus.boxlang.runtime.types.*;
import ortus.boxlang.runtime.types.IType;
// Core type classes
BoxArray bxArray = new BoxArray(); // Array
BoxStruct bxStruct = BoxStruct.of("k","v"); // Struct
BoxString bxStr = BoxString.of("hello"); // String (immutable)
BoxInteger bxInt = BoxInteger.of(42); // Integer
BoxDouble bxDbl = BoxDouble.of(3.14); // Double
BoxBoolean bxBool = BoxBoolean.of(true); // Boolean
BoxNull bxNull = BoxNull.INSTANCE; // Null singleton
// Check type
if ( value instanceof BoxArray arr ) {
// work with array
}
if ( value instanceof IStruct struct ) {
// work with struct
}
// Key — interned string for scope/struct access
Key nameKey = Key.of("name"); // interned (fast equality)
Key idKey = Key.of("id");Source code → AST → Java Bytecode:
Source (.bx / .bxs / .bxm / .cfm / .cfc)
│
▼
Lexer (ANTLR4) → Token stream
│
▼
Parser (ANTLR4) → Parse tree
│
▼
AST Builder → BoxLang AST (BoxNode tree)
│
▼
Transpiler/Transformer → Java AST (JavaParser)
│
▼
Java Compiler → Java bytecode (.class)
│
▼
ClassLoader → Loaded & executed by JVM# Print the AST for a file
boxlang --bx-printast myScript.bxs
# Print AST from stdin
echo 'var x = 1 + 2' | boxlang --bx-printast -
# Print AST with file path context
boxlang --bx-printast /path/to/file.bxsOnce compiled, the generated .class files are cached by the ClassLoader. Re-compilation only happens when the source timestamp changes or when reloadOnChange=true is configured.
Each module gets its own isolated ClassLoader for the libs/ directory:
BoxLang Runtime ClassLoader
├── Core BIFs & Runtime Classes
├── Module A ClassLoader
│ └── libs/moduleA-dependency.jar
├── Module B ClassLoader
│ └── libs/moduleB-dependency.jar (no conflict with Module A)
└── Application ClassLoader
└── Application-specific JARs (this.javaSettings)This prevents JAR version conflicts between modules — each module's libs/ directory is visible only to that module.
| Package | Contents |
|---|---|
ortus.boxlang.runtime | BoxRuntime, configuration |
ortus.boxlang.runtime.bifs | BIF base classes, annotations |
ortus.boxlang.runtime.context | Context classes, scope resolution |
ortus.boxlang.runtime.scopes | Scope implementations, Key |
ortus.boxlang.runtime.types | BoxArray, BoxStruct, IStruct, etc. |
ortus.boxlang.runtime.events | BaseInterceptor, InterceptorService |
ortus.boxlang.runtime.services | All service classes |
ortus.boxlang.runtime.modules | ModuleRecord, ModuleService |
ortus.boxlang.runtime.dynamic | DynamicObject, Java interop |
ortus.boxlang.runtime.loader | Class loading, bytecode generation |
ortus.boxlang.compiler.ast | AST node classes |
BoxLang uses JRE 21 virtual threads (Project Loom) for its default executor:
// Virtual thread executor (default in BoxLang)
// - Lightweight: millions can coexist
// - Ideal for I/O-bound work (HTTP, DB, file I/O)
// - Automatically unmounted during blocking operations
ExecutorService virtualExec = Executors.newVirtualThreadPerTaskExecutor();
// BoxLang's AsyncService uses virtual threads by default:
// Type.VIRTUAL → Executors.newVirtualThreadPerTaskExecutor()
// Type.FIXED → Executors.newFixedThreadPool(n)
// Type.CACHED → Executors.newCachedThreadPool()BoxLang supports Java CDS archives for faster startup:
# Generate a CDS archive
java -Xshare:dump -XX:SharedArchiveFile=boxlang.jsa -jar boxlang.jar
# Use the archive on startup (significantly faster cold starts)
java -Xshare:on -XX:SharedArchiveFile=boxlang.jsa -jar boxlang.jar// Get boxlang.json configuration
BoxLangConfiguration config = runtime.getConfiguration();
boolean debugMode = config.debugMode;
String timezone = config.timezone;
IStruct modules = config.modules;
IStruct caches = config.caches;
IStruct datasources = config.datasources;
// Get a module's settings
IStruct moduleSettings = config.modules
.getAsStruct( Key.of("bx-redis") )
.getAsStruct( Key.of("settings") );import ortus.boxlang.runtime.BoxRuntime;
import ortus.boxlang.runtime.context.ScriptingRequestBoxContext;
import ortus.boxlang.runtime.scopes.Key;
// Start the runtime
BoxRuntime runtime = BoxRuntime.getInstance( true );
// Create a scripting context
ScriptingRequestBoxContext context = new ScriptingRequestBoxContext( runtime.getRuntimeContext() );
// Set variables
context.getScope( VariablesScope.name ).put( Key.of("greeting"), "Hello!" );
// Execute BoxLang code
runtime.executeStatement( "println( greeting )", context );
// Execute a file
runtime.executeTemplate( "/path/to/script.bxs", context );
// Shutdown
runtime.shutdown();Attempt<T> is a fluent, immutable wrapper for values that may be null or invalid. It is analogous to Java's Optional but with built-in BoxLang validation support. Used extensively in BIFs and services, especially for optional argument handling.
import ortus.boxlang.runtime.dynamic.Attempt;
// Create an attempt from any value (including null)
Attempt<String> attempt = Attempt.of( arguments.get( Key.of("name") ) );
Attempt<Integer> empty = Attempt.empty();
// Basic presence checks
if ( attempt.isPresent() ) { ... }
if ( attempt.isEmpty() ) { ... }
// Get value (throws NoElementException if empty)
String value = attempt.get();
// Get with default
String value = attempt.orElse( "default" );
String value = attempt.orElseGet( () -> computeDefault() );
// Throw a specific exception if empty
Attempt.of( null ).orThrow( "mymodule.NotFound", "Value not found" );
// Map and filter
Attempt<Integer> len = attempt.map( s -> s.length() );
Attempt<String> filtered = attempt.filter( s -> s.length() > 3 );
// Build a stream
attempt.stream().forEach( v -> process(v) );// Validate type (uses BoxLang's isValid() function)
Attempt.of( value ).toBeType( "email" ).isValid(); // true/false
// Range validation (inclusive)
Attempt.of( 42 ).toBeBetween( 1.0, 100.0 ).isValid();
// Regex pattern
Attempt.of( "hello" ).toMatchRegex( "^[a-z]+$" ).isValid();
Attempt.of( "HELLO" ).toMatchRegex( "^[a-z]+$", false ).isValid(); // case-insensitive
// Custom predicate
Attempt.of( user ).toSatisfy( u -> u.isActive() ).isValid();@Override
public Object invoke( IBoxContext context, ArgumentsScope arguments ) {
// getAsAttempt returns Attempt<T> — safe for optional params
String name = arguments.getAsAttempt( Key.of("name"), String.class ).orElse( "World" );
Integer timeout = arguments.getAsAttempt( Key.of("timeout"), Integer.class ).orElse( 30 );
return "Hello, " + name + "!";
}BoxLang provides a rich set of type casters in ortus.boxlang.runtime.dynamic.casters. Each returns a CastAttempt<T> (similar to Attempt) with .wasSuccessful() and .get().
import ortus.boxlang.runtime.dynamic.casters.*;
// Safe casting — returns CastAttempt
CastAttempt<String> strAttempt = StringCaster.attempt( value );
CastAttempt<Integer> intAttempt = IntegerCaster.attempt( value );
CastAttempt<Long> longAttempt = LongCaster.attempt( value );
CastAttempt<Double> dblAttempt = DoubleCaster.attempt( value );
CastAttempt<Boolean> boolAttempt = BooleanCaster.attempt( value );
if ( intAttempt.wasSuccessful() ) {
int n = intAttempt.get();
}
// Direct casting (throws if fails)
String str = StringCaster.cast( value );
Integer num = IntegerCaster.cast( value );
Boolean bool = BooleanCaster.cast( value );
Array arr = ArrayCaster.cast( value );
IStruct strc = StructCaster.cast( value );
// Specific casters available:
// ArrayCaster, BooleanCaster, DateTimeCaster, DoubleCaster,
// FloatCaster, IntegerCaster, KeyCaster, LongCaster,
// NumberCaster, QueryCaster, StringCaster, StructCaster,
// UUIDCaster, XMLCaster, ThrowableCaster, FunctionCasterImplement IService to create a service that's lifecycle-managed by the BoxLang runtime. The runtime discovers and calls lifecycle methods automatically.
import ortus.boxlang.runtime.services.IService;
import ortus.boxlang.runtime.scopes.Key;
public class MyCustomService implements IService {
private static final Key SERVICE_NAME = Key.of( "MyCustomService" );
private BoxLangLogger logger;
@Override
public Key getName() {
return SERVICE_NAME;
}
@Override
public void onConfigurationLoad() {
// Called when boxlang.json is loaded; access config here
this.logger = BoxRuntime.getInstance().getLoggingService().getLogger( "mycustomservice" );
logger.debug( "Configuration loaded" );
}
@Override
public void onStartup() {
logger.info( "MyCustomService started" );
// Initialize resources, open connections, warm up caches, etc.
}
@Override
public void onShutdown( Boolean force ) {
logger.info( "MyCustomService shutting down (force={})", force );
// Release resources, close connections, flush buffers
}
// Add your service-specific methods:
public String doSomething( String input ) {
return input.toUpperCase();
}
}// ModuleConfig.bx (via Java in onLoad)
// or register directly from Java:
BoxRuntime.getInstance().registerService( new MyCustomService() );// ModuleConfig.bx
class {
function onLoad() {
var svc = createObject( "java", "com.example.services.MyCustomService" ).init()
boxRuntime.registerService( svc )
log.info( "MyCustomService registered" )
}
}// Retrieve by name
MyCustomService svc = (MyCustomService) BoxRuntime.getInstance()
.getService( Key.of("MyCustomService") );
svc.doSomething( "hello" );~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.