jvm-class
A JVM class file parser written in Rust.
jvm-class turns the bytes of a .class file into a typed structure: constant pool,
access flags, fields, methods and attributes. Parsing borrows from the input buffer,
so string data, bytecode and unknown attribute payloads are slices, not copies.
Features
- Zero-copy:
Class<'a>borrows the input slice; no allocation for UTF-8 data or code arrays. - Strict validation: magic, class file version, constant pool bounds and slot usage, attribute lengths and constant pool entry kinds are all checked, and trailing bytes are an error.
- CESU-8 aware: constant pool strings are exposed as
Cesu8Bytes, decoded on demand (Java's modified UTF-8, including surrogate pairs and the two-byte encoded NUL). - Typed attributes: all attributes defined up to Java SE 8 are parsed into enum variants;
unrecognized ones are kept verbatim as
AttributeInfo::Unknown. - No
unsafe, two small dependencies (bitflags,cesu8).
Supported class file versions
Major versions 45 to 52 — Java 1.1 through Java 8. Anything outside that range is
rejected with Error::UnsupportedVersion.
Installation
Or add it manually:
[]
= "0.1"
Usage
use ;
let bytes = read?;
let class = parse?;
println!;
for method in &class.methods
# Ok::
Bytecode and the exception table live in the Code attribute:
use ;
# let bytes = read?;
# let class = parse?;
for method in &class.methods
# Ok::
The constant pool is indexed exactly like in the class file — 1-based, with Long and
Double taking two slots. Reading the unusable second slot is an error rather than a panic:
use ;
# let bytes = read?;
# let class = parse?;
for in class.constant_pool.iter
# Ok::
If you need to parse a class embedded in a larger buffer, use Class::try_read with a
Cursor instead of Class::parse; it leaves the remaining bytes in the cursor rather
than failing with Error::TrailingBytes.
Error handling
Every fallible operation returns jvm_class::Result<T>, an alias for
std::result::Result<T, jvm_class::Error>. Error implements Display and
std::error::Error, and each variant carries the offending value — the tag, index,
version or byte count that caused the failure.
Minimum supported Rust version
Rust 1.85 (edition 2024).
Testing
The test suite parses real class files compiled from the Java sources in
tests/fixtures/java, plus hand-built malformed classes that exercise every error variant.
To rebuild the fixtures you need a javac that supports --release 8 on PATH:
License
MIT — see LICENSE.