Skip to content

AIVory Monitor Java JVMTI Agent - Low-level JVM monitoring via JVMTI

License

Notifications You must be signed in to change notification settings

aivorynet/agent-java-jvmti

Repository files navigation

AIVory JVMTI Agent

Native JVMTI agent for full debugger-level local variable capture on exceptions.

What This Does

The standard Java agent (ByteBuddy) can only capture:

  • Method arguments
  • Instance fields (this.xxx)

This JVMTI agent captures everything a debugger sees:

  • All local variables in each stack frame
  • Method arguments
  • Instance fields
  • Static fields
  • Full object state

Requirements

  • Java Application: Must be compiled with -g (debug info) for local variable names
  • Build Tools: CMake 3.10+, C compiler (gcc/clang/MSVC)
  • JAVA_HOME: Must be set to JDK installation

Building

Linux/macOS

mkdir build && cd build
cmake ..
make

Output: libaivory_jvmti.so (Linux) or libaivory_jvmti.dylib (macOS)

Windows

mkdir build && cd build
cmake .. -G "Visual Studio 17 2022"
cmake --build . --config Release

Output: aivory_jvmti.dll

Usage

Load both the JVMTI native agent and the Java agent:

java \
  -agentpath:/path/to/libaivory_jvmti.so=debug \
  -javaagent:/path/to/aivory-agent.jar \
  -Daivory.api.key=YOUR_API_KEY \
  -jar your-application.jar

Options

  • debug - Enable debug logging from native agent

How It Works

  1. JVMTI Exception Event: When any exception is thrown, JVMTI fires a callback
  2. Non-Blocking: The callback runs in the throwing thread but does NOT pause execution
  3. Variable Capture: Uses GetLocalVariableTable + GetLocal* JVMTI functions
  4. JNI Callback: Captured data is passed to Java agent via JVMTICallback.onException()
  5. Backend Transmission: Java agent sends the enriched data to AIVory backend

Performance Notes

  • Escape Analysis: JVMTI with can_access_local_variables capability may disable EA optimization
  • Filtering: Internal Java/JDK classes are skipped to reduce overhead
  • Deduplication: Same exception instance is only captured once as it propagates

Comparison

Feature ByteBuddy Only With JVMTI Agent
Method arguments Yes Yes
Instance fields Yes Yes
Local variables No Yes
All stack frames No Yes
Requires -g flag No Yes
Native code No Yes

Troubleshooting

"No local variable table" warnings

The Java code was not compiled with debug info. Add -g to javac:

javac -g MyClass.java

Or in Maven:

<plugin>
  <artifactId>maven-compiler-plugin</artifactId>
  <configuration>
    <debug>true</debug>
    <debuglevel>lines,vars,source</debuglevel>
  </configuration>
</plugin>

Agent not loading

Check that:

  1. JAVA_HOME points to a JDK (not JRE)
  2. The native library matches your OS/architecture
  3. Both -agentpath and -javaagent are specified

About

AIVory Monitor Java JVMTI Agent - Low-level JVM monitoring via JVMTI

Topics

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Packages

No packages published