JMA (JVM Model API) is a high-level framework for analyzing, validating, and generating JVM class structures, supporting class files from Java 8 to Java 24.
It is designed to be:
- Fully compatible with the Java® Virtual Machine Specification, Java SE 24 Edition
- Interoperable with tools like ASM
- Extensible with custom validation, linking, and type resolution mechanisms
- Modular with full support for the Java Platform Module System (JPMS)
- Compiler-oriented, aiming to serve as a backend framework for language implementations on the JVM
JMA handles generics, annotations, bridge method generation, module resolution, and provides meaningful error messages — including source code locations — to simplify debugging and diagnostics.
It is ideal for:
- Programmatic class file manipulation
- Building compilers for new JVM languages
- Validating or rewriting
.class
or.jar
files with full spec compliance
See Karina for an example of a JVM language built on top of JMA.
// Locate the JDK's java.base.jmod file (which contains the core Java classes)
var javaHome = Objects.requireNonNull(System.getProperty("java.home"));
if (javaHome.endsWith("jre")) { javaHome = Paths.get(javaHome).getParent().toString(); }
var jmodPath = Paths.get(javaHome, "jmods", "java.base.jmod");
// Load, link and verify the core classes
UnlinkedModel jdkUnlinked = ModelReader.fromJMod(jmodPath);
Model jdkModel = ModelLinker.DEFAULT.link(jdkUnlinked);
ModelVerifier.DEFAULT.verify(jdkModel);
// Create a linker to reference the JDK model
var jdkLinker = new ModelLinker(jdkModel);
// Create a verifier to reference the JDK model
var jdkVerifier = new ModelVerifier(jdkModel);
// Create a custom class via ASM
var node = new ClassNode();
node.name = "com/example/customClass";
node.version = Flags.VERSION_LATEST;
node.superName = "java/lang/Object";
node.access = Flags.PUBLIC;
var identifier = ClassIdentifier.of("CustomClass");
// Convert into an UnlinkedClass
UnlinkedClass customUnlinked = ClassNodeParser.parse(identifier, node);
// Create a Model with a single class
UnlinkedModel customModel = UnlinkedModel.of(customUnlinked);
// Link against the existing core classes
Model linkedModel = jdkLinker.link(customModel);
jdkVerifier.verify(linkedModel);