GitHub

Monarch Java Agent

Monarch is a hybrid Java agent for production diagnostics and JVM observation. It lets you attach targeted bytecode instrumentation to a live JVM, expose Prometheus-compatible JVM metrics, and move between instrumenter, observer, and hybrid workflows without changing the application code.

Operational safety: Monarch contains agent-side failures at startup and runtime boundaries so instrumentation errors degrade behavior instead of crashing application flow.

“Arise, shadows of execution!”

Why Monarch

Use Monarch when you need to:

Key Abilities

MonArgs

Argument Description
configFile Path to the configuration file specifying agent behavior [Mandatory].
agentLogFileDir Directory where initialization logs will be written.
agentLogLevel Log verbosity level (DEBUG, INFO, WARN, ERROR).
smtpProperties Path to SMTP configuration for sending alert emails.
agentJarPath Path to the MonarchJavaAgent jar [Mandatory for startup attach].

Summoning the Monarch

You can attach MonarchJavaAgent either during startup or during runtime.

For startup:

  1. Download the latest agent JAR file from releases.
  2. Start your Java application using -javaagent.
  3. Pass the config file and bootstrap arguments.
java -Xverify:none -javaagent:/path/to/MonarchJavaAgent.jar=configFile=/path/to/config.yaml,agentLogFileDir=/path/to/log/dir,agentLogLevel=DEBUG,smtpProperties=/path/to/smtpProperties.props,agentJarPath=/path/to/MonarchJavaAgent.jar YourMainClass

For runtime attach:

  1. Start your application normally.
  2. Run monarchAgentStart.bat or monarchAgentStart.sh.
  3. Provide the agent jar, config file, bootstrap arguments, and target PID.

Commanding the Shadows

Monarch supports a nested, mode-aware YAML structure.

Canonical sample configuration:

mode: hybrid

instrumentation:
  enabled: true
  configRefreshInterval: 15
  traceFileLocation: C:\\TraceFileDumps
  agentRules:
    - ClassA::methodA@INGRESS::STACK
    - ClassA::methodA@INGRESS::ARGS
    - ClassA::methodA@EGRESS::RET
    - ClassA::methodB@INGRESS::ARGS
    - ClassA::methodB@INGRESS::STACK::[com.asm]
    - ClassA::methodB@EGRESS::STACK
    - ClassA::methodB@EGRESS::RET
    - ClassB::methodC@PROFILE
    - ClassB::methodC@INGRESS::HEAP
    - ClassB::methodC@INGRESS::ADD::[System.out.println(20);]
    - ClassA::methodA@INGRESS::ADD::[System.out.println(this.getClass().getName());]
    - ClassA::methodA@CODEPOINT(11)::ADD::[System.out.println(499);]
    - ClassA::methodA@CODEPOINT(11)::ADD::[System.out.println(499 + "," + "Ashutosh Mishra");]
    - com.example.MyService@CHANGE::FILE::[/opt/patches/MyService.class]
    - com.example.*@CHANGE::JAR::[/opt/patches/hotfix.jar]

observer:
  enabled: true
  printClassLoaderTrace: true
  printJVMSystemProperties: true
  printEnvironmentVariables: true
  metrics:
    exposeHttp: true
    port: 9090
    heapUsage: true
    cpuUsage: true
    threadUsage: true
    gcStats: true
    classLoaderStats: true

alerts:
  enabled: true
  maxHeapDumps: 3
  emailRecipientList:
    - abc@example.com
    - ashutosh@asm.com

Legacy flat keys are still accepted, but nested config is the default and takes precedence when both forms are present.

The Monarch’s Decrees

Rule syntax:

<FQCN>::<MethodName>@<EVENT>::<ACTION>

Where:

Class replacement rule syntax:

<ClassPattern>@CHANGE::FILE::[</absolute/path/to/ClassName.class>]
<ClassPattern>@CHANGE::JAR::[</absolute/path/to/patches.jar>]

Where:

Shadow Metrics Gate

If observer.metrics.exposeHttp: true is enabled, Monarch starts a lightweight HTTP server exposing JVM metrics.

Default endpoints:

Prometheus scrape config:

global:
  scrape_interval: 5s

scrape_configs:
  - job_name: "monarch-java-agent"
    static_configs:
      - targets: ["127.0.0.1:9090"]

Common Prometheus queries:

Example Grafana dashboard:

Grafana dashboard for MonarchJavaAgent metrics

Forging the Shadow

git clone https://github.com/AshutoshIWNL/MonarchJavaAgent.git
cd MonarchJavaAgent
mvn clean package

Shadow Trials

powershell -ExecutionPolicy Bypass -File scripts\smoke-all.ps1

Individual suites:

powershell -ExecutionPolicy Bypass -File scripts\smoke-javaagent.ps1
powershell -ExecutionPolicy Bypass -File scripts\smoke-attach.ps1
powershell -ExecutionPolicy Bypass -File scripts\smoke-class-replace.ps1
powershell -ExecutionPolicy Bypass -File scripts\smoke-config-reload.ps1
powershell -ExecutionPolicy Bypass -File scripts\smoke-invalid-rule.ps1
powershell -ExecutionPolicy Bypass -File scripts\smoke-config-precedence.ps1

The Architect of Shadows

The Shadow’s Pact

This project is licensed under the Apache License 2.0 - see the LICENSE file for details.