Goal
Enable offline, build-time code generation so that JTD validators compiled via the codegen path do not require a JDK 24+ runtime.
Problem
Currently JtdCodegen.compile() uses the JDK 24+ ClassFile API (JEP 484) to generate bytecode at runtime. This means:
- The application must run on JDK 24+ to use the codegen path
- Generated bytecode is not persisted — it's regenerated on every startup
- No offline/aot compilation option exists
Proposed Solution
Add a Java source code emitter alongside the existing bytecode emitter. At build time (on JDK 24+), run a Maven plugin or CLI tool that:
- Reads JTD schema JSON files
- Generates plain
.java source files containing validator classes
- Those generated sources are compiled by the standard
maven-compiler-plugin targeting Java 21
- The resulting
.class files are bundled in the application JAR
- At runtime (JDK 21+), the pre-compiled validators are loaded via standard classloading — no
ClassFile API needed
Architecture
Build time (JDK 24+) Runtime (JDK 21+)
┌─────────────────────┐ ┌─────────────────────┐
│ JTD schema (.json) │ │ Pre-compiled │
│ │ │ │ validator.class │
│ ▼ │ │ (Java 21 bytecode) │
│ JtdCodegen.emitJava()│ │ │ │
│ → generates .java │ │ ▼ │
│ │ │ │ JtdValidator.validate()│
│ ▼ │ │ │
│ javac -release 21 │────────────────▶│ ~9x faster than │
│ → .class files │ │ interpreter │
└─────────────────────┘ └─────────────────────┘
Implementation Steps
- Add
EmitJava class (parallel to existing EmitNode/EmitType etc.) that generates Java source code instead of bytecode
- Add
JtdCodegen.emitJava(schema, packageName, className) method returning String source
- Add
jtd-codegen-maven-plugin (or reuse exec-maven-plugin) to run codegen during generate-sources
- Generated sources go to
target/generated-sources/jtd/
- Standard compiler picks them up automatically
JtdValidator.compileGenerated() falls back to loading pre-compiled classes via Class.forName() instead of MethodHandles.defineClass()
Benefits
- JDK 21 runtime compatible — generated validators work on any JDK 21+
- No runtime codegen overhead — zero ClassFile API usage at runtime
- Offline/AOT friendly — works in restricted environments (containers, air-gapped)
- Debuggable — generated Java source can be inspected, debugged, decompiled
- Smaller attack surface — no runtime
defineClass() calls
Goal
Enable offline, build-time code generation so that JTD validators compiled via the codegen path do not require a JDK 24+ runtime.
Problem
Currently
JtdCodegen.compile()uses the JDK 24+ClassFileAPI (JEP 484) to generate bytecode at runtime. This means:Proposed Solution
Add a Java source code emitter alongside the existing bytecode emitter. At build time (on JDK 24+), run a Maven plugin or CLI tool that:
.javasource files containing validator classesmaven-compiler-plugintargeting Java 21.classfiles are bundled in the application JARClassFileAPI neededArchitecture
Implementation Steps
EmitJavaclass (parallel to existingEmitNode/EmitTypeetc.) that generates Java source code instead of bytecodeJtdCodegen.emitJava(schema, packageName, className)method returningStringsourcejtd-codegen-maven-plugin(or reuseexec-maven-plugin) to run codegen duringgenerate-sourcestarget/generated-sources/jtd/JtdValidator.compileGenerated()falls back to loading pre-compiled classes viaClass.forName()instead ofMethodHandles.defineClass()Benefits
defineClass()calls