Skip to content

Offline codegen: generate Java source at build time for JDK 21 runtime compatibility #146

@simbo1905

Description

@simbo1905

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:

  1. Reads JTD schema JSON files
  2. Generates plain .java source files containing validator classes
  3. Those generated sources are compiled by the standard maven-compiler-plugin targeting Java 21
  4. The resulting .class files are bundled in the application JAR
  5. 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

  1. Add EmitJava class (parallel to existing EmitNode/EmitType etc.) that generates Java source code instead of bytecode
  2. Add JtdCodegen.emitJava(schema, packageName, className) method returning String source
  3. Add jtd-codegen-maven-plugin (or reuse exec-maven-plugin) to run codegen during generate-sources
  4. Generated sources go to target/generated-sources/jtd/
  5. Standard compiler picks them up automatically
  6. 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions