Skip to content

IsolateThread

opencode-agent[bot] edited this page May 10, 2026 · 1 revision

IsolateThread

Thread wrapper for isolated execution contexts with dual-statics architecture. IsolateThread provides the execution mechanism for isolated environments, managing separate static fields and execution contexts while sharing kernel resources.

Overview

IsolateThread (core/src/core/org/jnode/vm/isolate/IsolateThread.java) is the thread type used to start a new isolate in JNode. It extends java.lang.Thread and serves as the entry point for isolate execution, wrapping the main thread of each isolate with isolate-specific I/O streams, plugin manager reference, and most critically, the isolate's VmIsolatedStatics table.

When a new isolate is started via VmIsolate.start(), the VM creates an IsolateThread as the isolate's main thread. The IsolateThread constructor passes the isolate's VmIsolatedStatics table to the underlying Thread via super(group, null, isolate.getMainClassName(), isolate.getIsolatedStaticsTable()). This statics table becomes the thread's "isolated statics" reference, which is switched when the thread enters or exits an isolate context.

Each IsolateThread also carries redirectable standard I/O streams (stdout, stderr, stdin) bound at construction time via VmStreamBindings. This ensures isolate output is isolated from the parent isolate's console. Additionally, it holds a reference to the PluginManager to support plugin loading within the isolate.

Key Components

Class / File Role
core/src/core/org/jnode/vm/isolate/IsolateThread.java Thread wrapper implementation — constructor binds I/O and statics table, run() delegates to VmIsolate.run()
core/src/core/org/jnode/vm/isolate/VmIsolate.java Isolate context management — owns the VmIsolatedStatics table, creates IsolateThread, lifecycle state machine
core/src/core/org/jnode/vm/isolate/IsolateThreadFactory.java Factory pattern for creating Thread instances that belong to a specific isolate's statics table
core/src/core/org/jnode/vm/isolate/VmStreamBindings.java Per-isolate stdin/stdout/stderr redirection
core/src/core/org/jnode/vm/memmgr/VmIsolatedStatics.java Per-isolate static field storage (131,072 slots)

How It Works

IsolateThread Creation and Startup

When VmIsolate.start() is called, it performs the following steps to create and start the main thread:

// Create a new ThreadGroup rooted under the system isolate
this.threadGroup = new ThreadGroup(StaticData.getRoot().threadGroup, mainClass);

// Create redirectable I/O streams for this isolate
final PrintStream stdout = bindings.createIsolatedOut();
final PrintStream stderr = bindings.createIsolatedErr();
final InputStream stdin = bindings.createIsolatedIn();

// Create the main IsolateThread, binding the isolate's statics table
final IsolateThread mainThread = new IsolateThread(
    threadGroup, this, piManager, stdout, stderr, stdin);

// Start the thread
mainThread.start();

The run() Method

The IsolateThread.run() method is deliberately simple — it delegates to VmIsolate.run():

@Override
public final void run() {
    isolate.run(this);
}

VmIsolate.run() then:

  1. Sets IsolatedStaticData.current = VmIsolate.this as the current isolate
  2. Redirects System.setOut/setErr/setIn to the thread's isolated streams
  3. Sets system properties from the isolate's initial properties
  4. Sets the context classloader to an isolate-specific classloader
  5. Loads and invokes the main class's main(String[]) method

Thread Group and Statics Binding

The IsolateThread constructor passes the statics table to the underlying Thread constructor:

IsolateThread(ThreadGroup group, VmIsolate isolate,
              PluginManager piManager, PrintStream stdout, PrintStream stderr,
              InputStream stdin) {
    super(group, null, isolate.getMainClassName(),
          isolate.getIsolatedStaticsTable());
    this.isolate = isolate;
    // ...
}

The fourth argument to Thread — the VmIsolatedStatics table — is stored as the thread's inherited access control context and is used by VmThread.switchToIsolate() to update the processor's statics reference when switching between isolates.

I/O Stream Redirection

A notable side effect in the constructor: it immediately redirects System.in/out/err to the isolated streams:

System.setIn(stdin);
System.setOut(stdout);
System.setErr(stderr);

This is marked with a // TODO crawley, review this comment indicating this side effect during thread construction may have unintended consequences.

Gotchas & Non-Obvious Behavior

  • Statics table passed to Thread constructor — The VmIsolatedStatics table is not directly stored in IsolateThread but is passed to the underlying Thread constructor. The VM scheduler retrieves it via VmThread.getIsolatedStatics() when context-switching.
  • Side-effecting constructorIsolateThread's constructor calls System.setIn/setOut/setErr, which affects the creating thread's System streams, not just the new thread's. This is a known concern flagged by the TODO comment.
  • No override of Thread.interrupt()IsolateThread does not override interrupt(). Thread termination uses ThreadGroup.stop() in VmIsolate.halt() and stopAllThreads().
  • ThreadGroup hierarchy — All isolate thread groups are nested under the root isolate's thread group, but each isolate has its own VmIsolatedStatics table, providing the isolation boundary.
  • Root isolate has no IsolateThread — The root isolate (kernel) runs in the primordial thread created by the boot sequence, not via IsolateThread. Only child isolates use IsolateThread as their main thread.

Related Pages

Clone this wiki locally