Skip to content

Boot Log

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

Boot Log

Logging subsystem for boot sequence messages before the full logging infrastructure is ready.

Overview

BootLog is JNode's logging interface used during the bootstrap phase—before Log4j or other full logging systems are initialized. It provides a lightweight, immediate logging mechanism with five severity levels: DEBUG, INFO, WARN, ERROR, and FATAL.

The boot logging system consists of three key components:

Component File Purpose
BootLog core/src/core/org/jnode/bootlog/BootLog.java Interface defining logging methods
BootLogInstance core/src/core/org/jnode/bootlog/BootLogInstance.java Singleton accessor for the system BootLog
BootLogImpl core/src/core/org/jnode/vm/BootLogImpl.java Default implementation

How It Works

Initialization

BootLog is initialized early in VmSystem.initialize():

VmSystem.initialize()
  └─> InitialNaming.setNameSpace(new DefaultNameSpace())
  └─> BootLogImpl.initialize()         <-- Boot log initialized here
       └─> BootLogInstance.set(new BootLogImpl())

This happens immediately after the InitialNaming namespace is set up, making BootLog available to all subsequent boot code.

Singleton Access

Code retrieves the system BootLog via BootLogInstance.get():

BootLog log = BootLogInstance.get();
log.info("Starting device manager");
log.error("Failed to initialize", ex);

The BootLogInstance class uses InitialNaming.lookup(BootLog.class) to retrieve the registered instance, providing type-safe service access similar to JNDI but simpler.

Logging Levels

Level Constant Typical Output
DEBUG 1 Console (configurable via setDebugOut)
INFO 2 System.out
WARN 3 System.out
ERROR 4 System.err
FATAL 5 System.err

Fallback Behavior

If no PrintStream is available (e.g., early boot before System streams are set up), BootLogImpl.log() falls back to Unsafe.debug() for raw output:

private void log(int level, PrintStream ps, String msg, Throwable ex) {
    if (ps != null) {
        // Use PrintStream
        ps.println(msg);
        if (ex != null) ex.printStackTrace(ps);
    } else {
        // Fallback to Unsafe.debug
        Unsafe.debug(msg);
        Unsafe.debug("\n");
    }
}

Transition to Log4j

Once the system is fully initialized, the Log4jConfigurePlugin replaces the BootLog with full Log4j logging:

BootLogInstance.get().setDebugOut(new PrintStream(new WriterOutputStream(console.getOut(), false), true));

Key Components

BootLog Interface

public interface BootLog {
    public static final int DEBUG = 1;
    public static final int INFO = 2;
    public static final int WARN = 3;
    public static final int ERROR = 4;
    public static final int FATAL = 5;

    void debug(String msg);
    void debug(String msg, Throwable ex);
    void info(String msg);
    void info(String msg, Throwable ex);
    void warn(String msg);
    void warn(String msg, Throwable ex);
    void error(String msg);
    void error(String msg, Throwable ex);
    void fatal(String msg);
    void fatal(String msg, Throwable ex);
    void setDebugOut(PrintStream out);
}

BootLogInstance

A utility class providing static get/set methods that delegate to InitialNaming:

public final class BootLogInstance {
    public static BootLog get() {
        return InitialNaming.lookup(BootLog.class);
    }
    public static void set(BootLog bootLog) throws NameAlreadyBoundException, NamingException {
        InitialNaming.bind(BootLog.class, bootLog);
    }
}

Usage Patterns

BootLog is used extensively across the codebase (240+ references), typically for:

  • Driver initialization — Device managers, drivers, bus enumeration
  • Compiler debug output — L1/L2 compiler state, method compilation
  • Plugin lifecycle — Plugin loading, dependency resolution
  • Error reporting — Fatal conditions, missing resources

Example usage:

// From DefaultDeviceManager.java
BootLogInstance.get().debug("Found " + extensions.length + " device finders");
BootLogInstance.get().warn("Ignoring unrecognised descriptor element: " + elementName);
BootLogInstance.get().error("Cannot find finder class " + className, ex);

Gotchas

  • No filtering — Unlike Log4j, BootLog has no concept of log levels to suppress output; all calls print immediately.
  • No category/logger separation — All messages go through a single global logger; no per-component filtering.
  • InitialNaming dependencyBootLogInstance.get() will throw an Error if called before InitialNaming is initialized.
  • Debug output streams — The setDebugOut() method only affects DEBUG level; other levels use System.out/System.err directly.
  • No exception handling during fatal — The error() method historically had a commented-out Thread.sleep() for crash dump scenarios.

Related Pages

Clone this wiki locally