Expand description
Safe, idiomatic Rust bindings for the JVM Tool Interface (JVMTI).
This crate wraps jvmti2-sys (raw FFI bindings) and provides:
- Lifetime-tracked
Envfor safe JVMTI function calls - RAII memory management (
JvmtiString,JvmtiArray) - Idiomatic Rust enums for all JVMTI C enumerations
- A builder-based
CapabilitiesAPI - Both raw fn-pointer and generic/monomorphized event callback APIs
- Agent entry-point macros (
agent_onload!,agent_onattach!,agent_onunload!) - Tight integration with the
jnicrate
§Getting Started
A JVMTI agent is a native shared library that the JVM loads at startup (or
attaches to a running process). The library exports a well-known entry point
(Agent_OnLoad) where you configure capabilities, install event callbacks,
and enable the events you care about.
The example below builds a minimal agent that prints every method name as it is entered.
use std::ffi::CStr;
use jvmti2::{agent_onload, Capabilities, Env, Event, EventHandler, EventMode, JMethodID, JThread};
// 1. Define a handler struct that implements the EventHandler trait.
// You only need to override the callbacks you care about; the rest
// are no-ops by default.
struct MyHandler;
impl EventHandler for MyHandler {
fn method_entry(
&self,
jvmti_env: &Env<'_>,
_jni_env: &mut jni::EnvUnowned<'_>,
_thread: &JThread<'_>,
method: JMethodID,
) {
// Resolve the method name for display.
if let Ok((name, _sig, _generic)) = jvmti_env.get_method_name(method) {
eprintln!(">> {name}");
}
}
}
// 2. Write the on_load function that the macro will wire up.
fn on_load(env: &mut Env<'_>, _options: Option<&CStr>) -> jvmti2::Result<()> {
// Request the capability we need.
let caps = Capabilities::new().can_generate_method_entry_events();
env.add_capabilities(&caps)?;
// Install our handler and enable the event.
let handler = env.install_event_handler(MyHandler)?;
env.set_event_notification_mode(EventMode::Enable, Event::MethodEntry, None)?;
// Leak the guard -- the agent lives for the JVM's lifetime.
std::mem::forget(handler);
Ok(())
}
// 3. Generate the Agent_OnLoad entry point.
agent_onload!(on_load);Key concepts demonstrated above:
-
agent_onload!generates theextern "system" fn Agent_OnLoadsymbol that the JVM calls when the agent is loaded. There are correspondingagent_onattach!andagent_onunload!macros for dynamic attach and shutdown hooks. -
EventHandleris a trait with 35+ callback methods (one per JVMTI event). Every method has a default no-op implementation, so you only override the ones you need. -
InstalledHandleris the RAII guard returned byEnv::install_event_handler. Dropping it clears the callbacks and frees the handler. Leaking it (viastd::mem::forget) keeps the callbacks active for the lifetime of the JVM, which is the typical pattern for agents. -
Envis the central entry point for all JVMTI operations: capabilities, events, class and method introspection, thread management, heap walking, and more.
§Building and Loading
A JVMTI agent must be compiled as a C-compatible shared library
(cdylib). Your Cargo.toml should contain:
[lib]
crate-type = ["cdylib"]
[dependencies]
jvmti2 = "0.1"
jni-sys = "0.4"Build and load the agent:
cargo build --release
java -agentpath:target/release/libmy_agent.so MyAppThe shared library extension depends on the platform: .so on Linux,
.dylib on macOS, and .dll on Windows.
§Examples
The repository ships five complete example agents:
examples/jvmti-tracing– Method entry/exit tracerexamples/jvmti-class-watcher– Class load/prepare monitorexamples/jvmti-native-spy– Native method bind watcherexamples/jvmti-field-guard– Field access/modification watchdogexamples/jvmti-android-recon– Attack surface reconnaissance agent
Each example is a standalone Cargo project with its own Cargo.toml and
a README explaining how to build and run it.
§See Also
- JVMTI Specification – the authoritative reference for all JVMTI functions, events, and capabilities.
jvmti2-sys– raw FFI bindings generated from the JVMTI C headers. Re-exported by this crate assys.jni– JNI bindings for JVM creation and Java interop, used alongside this crate when you need to call Java methods or manipulate Java objects from your agent.
Re-exports§
pub use errors::JvmtiError;pub use errors::Result;pub use memory::JvmtiString;pub use memory::JvmtiArray;pub use capabilities::Capabilities;pub use monitor::RawMonitor;pub use event::EventHandler;pub use event::EventCallbacksBuilder;pub use event::InstalledHandler;pub use jvmti2_sys as sys;pub use enums::*;pub use flags::*;pub use objects::*;
Modules§
- agent
- Agent entry-point macros.
- capabilities
- Builder-pattern wrapper for JVMTI capabilities.
- enums
- Idiomatic Rust enums wrapping JVMTI C enumerations.
- errors
- Error types for JVMTI operations.
- event
- Event callback system.
- flags
- Bitflag types wrapping JVMTI bitmask constants.
- memory
- RAII wrappers for JVMTI-allocated memory.
- monitor
- RAII wrapper for JVMTI raw monitors.
- objects
- Typed wrappers around JNI object references for JVMTI-specific types.
Macros§
- agent_
onattach - Generates the
Agent_OnAttachentry point (dynamic attach). - agent_
onload - Generates the
Agent_OnLoadentry point. - agent_
onunload - Generates the
Agent_OnUnloadentry point.
Structs§
- Env
- A JVMTI environment handle.
- Jvmti
Version - JVMTI version number.