
Welcome to PAL
The Core Insight
PAL instruments every Java operation at build time. At runtime, instrumented operations become messages when you enable logging, interception, or publishing.
Your Code PAL Runtime Messages
calculator.add(2, 3) ──────────► ExecMessage {
class: "Calculator"
method: "add"
args: [2, 3]
}
│
┌──────────────────────┼──────────────────────┐
▼ ▼ ▼
LOGGED REPLAYED INTERCEPTED
(write-ahead log) (deterministic replay) (modify behavior)
│ │ │
▼ ▼ ▼
Time-travel Reproduce any Hot-patch
debugging execution production
Method calls, field access, and constructors are instrumented at build time, and become discrete, serializable messages at runtime based on your configuration. Because operations can become messages, they can be logged, intercepted, and replayed.
PAL is a post-compile weaving layer and runtime that adds message-passing semantics to Java operations. Method calls, field access, and constructors are instrumented at build time via AspectJ. At runtime, when logging, interception, or publishing is enabled, these instrumented operations become messages that can be logged to a write-ahead log, replayed for deterministic debugging, or intercepted by dynamic callbacks—without modifying your application source code.
The idea of reifying operations as messages has a long heritage: Smalltalk (1970s), Erlang/OTP, Akka, and others have built on this principle. PAL's contribution is applying it to existing Java code through bytecode weaving, enabling capabilities like write-ahead logging, deterministic replay, dynamic interception, and cross-peer invocation as runtime options rather than architectural commitments. All features are off by default—you enable only what you need, and pay no runtime cost for features you don't use.
This single abstraction enables capabilities that are not available in standard JVMs.
One Abstraction, Many Capabilities
PAL's capabilities share a common foundation: operations represented as messages. Because method calls, field access, and constructors are instrumented, they can become messages that are logged, intercepted, and replayed—each unlocking a different set of capabilities:
Logged:
- Time-travel debugging (replay any execution)
- Audit trails (observe every operation)
- Event sourcing (automatic, transparent)
Replayed:
- Deterministic debugging (reproduce any execution exactly)
- Root cause analysis (step through the exact sequence that led to a failure)
- State reconstruction (rebuild state from the operation log)
Intercepted:
- Hot-patching production (modify behavior at runtime)
- Testing without mocks (replace implementations dynamically)
- Monitoring (observe calls as they happen)
Because intercept callbacks can mutate arguments, skip execution, or override return values, higher-level patterns like routing, filtering, transformation, and caching follow naturally from this mechanism.
Without modifying your application source code (AspectJ weaving is configured at build time). No annotations, no interfaces in your source files.
What You Can Do
Development & Testing
- Test real code without mocks (replay messages instead of stubbing dependencies)
- Debug with time-travel (replay any execution from the write-ahead log)
- Inspect method calls at runtime (observe message flow)
Production
- Hot-patch bugs in 60 seconds (via runtime intercepts, as a targeted incident response measure until a proper fix is deployed)
- Audit every operation (messages provide compliance trail)
- Trace requests across distributed systems (messages carry context)
Quick Start
1. Install PAL
# Clone and build
git clone https://github.com/quasientio/pal.git
cd pal
./mvnw install -DskipTests
# Add to PATH
export PATH="$(pwd)/bin:$PATH"
# Verify
pal help
See Getting Started for detailed installation.
The distributed examples below assume the following environment variable:
and infrastructure containers started (see Start/Stop Infrastructure).
2. Run Your First Peer
# Simple local peer with Chronicle Queue
pal run --wal file:/tmp/my-wal -cp myapp.jar com.example.Main
# Distributed peer with Kafka
pal run --wal my-wal -k localhost:29092 -cp myapp.jar com.example.Main
3. Call a Remote Method
# List running peers
pal peers
# Call a method
pal peer call peer-uuid com.example.Calculator add 5 3
Core Concepts
Peers
Peers are PAL runtime instances that execute your code. Each peer:
- Has a unique ID and optional name
- Can have its operations intercepted by dynamic callbacks
- Can register intercepts that target other peers' operations
- Can read from and write to logs (durable message streams backed by Kafka or Chronicle Queue)
- Can send and receive RPC calls
- Registers in a directory (etcd) for discovery
Learn more: Peers and Logs
Remote Procedure Calls
PAL converts method calls into messages that can be:
- Sent to remote peers (RPC)
- Written to logs for replay
- Intercepted for testing/monitoring
Two formats: Binary (fast) and JSON (interoperable)
Learn more: Remote Procedure Calls
Logs
Logs are durable message streams. PAL supports:
- Chronicle Queue: Memory-mapped files, ultra-fast, local
- Kafka: Distributed, networked, scalable
Choose Chronicle for local dev, Kafka for distributed systems.
Learn more: Log Backends
Interception
Insert callbacks before, after, or around any method call at runtime:
// Register intercept via constructor
InterceptRequest<InterceptableMethodCall> intercept =
new InterceptRequest<>(
UUID.randomUUID(), // intercept ID
myPeerUuid, // callback peer
InterceptType.BEFORE, // type
"com.example.Calculator", // class to intercept
"com.example.Monitor", // callback class
"onBeforeAdd", // callback method
new InterceptableMethodCall(
"add", Arrays.asList("int", "int")));
palDirectory.createIntercept(intercept);
// Your callback gets called before Calculator.add()
Learn more: Interception
Common Use Cases
Local Development and Testing
# Run with Chronicle (no infrastructure needed)
pal run --wal file:/tmp/dev-log -cp build/classes/java/main com.example.Dev
# Test with interception
# Register intercepts to verify method calls
Guide: Local Development
Building Distributed Applications
# Peer A: Service provider
pal run --wal service-wal --json-rpc 7767 -n my-service -cp service.jar com.example.Service
# Peer B: Client
pal peer call my-service com.example.Service processRequest data
Guide: Distributed Application
Testing with Interception
# Run application under test
pal run --interceptable -cp app.jar com.example.App
# Register intercepts from test code
# Verify method calls, inspect state
Concept: Interception
CLI Commands
| Command | Purpose |
|---|---|
pal init |
Initialize a project for PAL (scaffold or patch existing) |
pal run |
Start a peer and run application code |
pal peer |
Manage peers (ls, call, print, rm, stats) |
pal log |
Manage logs (ls, call, print, rm, index, stats) |
pal intercept |
Manage intercepts (ls) |
pal replay |
Replay application and verify against recorded WAL |
See CLI Reference for complete documentation.
Example Workflows
Capture and Replay Execution
# Run with WAL
pal run --wal file:/tmp/execution-log -cp app.jar com.example.Main arg1 arg2
# Print to see what happened
pal log print file:/tmp/execution-log --full
# Replay and verify execution against the WAL
pal replay --wal file:/tmp/execution-log -cp app.jar com.example.Main arg1 arg2
Concept: Deterministic Replay
Distributed RPC
# Terminal 1: Start service peer
pal run --wal service-wal --json-rpc 7767 -n calculator -cp calc.jar com.example.Calculator
# Terminal 2: Call service
pal peer call calculator com.example.Calculator add 10 20
Monitor Method Calls
# Start peer with interception enabled
pal run --interceptable -n monitored-app -cp app.jar com.example.App
# From monitoring code, register intercepts
# Get callbacks for every method call
Getting Help
- Concepts: Understand peers, RPC, interception, logs
- Guides: Follow step-by-step tutorials
- CLI Reference: Complete command documentation
- Getting Started: Detailed installation guide
Requirements
- Java: JDK 17 or later
- Build: Gradle or Maven 3.x
- Infrastructure (for distributed mode):
- etcd 3.x (directory service)
- Kafka 3.x (distributed logs)
- Docker (for local etcd/Kafka)
Next Steps
- Install: Follow Getting Started
- Learn Concepts: Read Peers and Logs
- Try It: Follow Local Development Guide
- Go Distributed: Build a Distributed Application
License
PAL is licensed under the Apache License, Version 2.0.