Skip to content

Commit 279aea2

Browse files
committed
Issue #139 Auto-skip jtd-codegen module on JDK 21, add README with benchmarks
- Move json-java21-jtd-codegen from main modules list to a JDK 24+ activation profile so it is automatically skipped when building with JDK 21 (where the ClassFile API is unavailable) - Add README.md documenting how the codegen works, usage examples, and full benchmark results showing average 8.7x speedup on valid docs
1 parent 5c6e43f commit 279aea2

2 files changed

Lines changed: 84 additions & 1 deletion

File tree

json-java21-jtd-codegen/README.md

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# JTD Bytecode Codegen
2+
3+
JTD schema-to-bytecode compiler using the JDK 24+ ClassFile API (JEP 484). Generates Java 21-compatible `.class` files at runtime for ~9x faster validation on hot paths.
4+
5+
## Requirements
6+
7+
- **Build**: JDK 24+ (uses `ClassFile` API, JEP 484)
8+
- **Generated bytecode**: Java 21+ (classfile version 65)
9+
- **Runtime**: JDK 24+ (the codegen itself runs at runtime to generate classes)
10+
11+
## How It Works
12+
13+
1. `JtdCodegen.compile(schema)` parses a JTD schema into an AST
14+
2. The emitter walks the AST and generates bytecode using `ClassFile.of().build()`
15+
3. The generated class is loaded via `MethodHandles.Lookup.defineClass()`
16+
4. The resulting `JtdValidator` validates JSON in ~9x less time than the interpreter
17+
18+
## Usage
19+
20+
```java
21+
import jdk.sandbox.java.util.json.*;
22+
import json.java21.jtd.JtdValidator;
23+
import json.java21.jtd.codegen.JtdCodegen;
24+
25+
JsonValue schema = Json.parse("""
26+
{"properties": {"name": {"type": "string"}, "age": {"type": "uint8"}}}
27+
""");
28+
JsonValue doc = Json.parse("{\"name\":\"Alice\",\"age\":30}");
29+
30+
// Codegen path (JDK 24+ only)
31+
JtdValidator validator = JtdCodegen.compile(schema);
32+
var result = validator.validate(doc);
33+
System.out.println(result.isValid()); // true
34+
35+
// Falls back to interpreter automatically via JtdValidator.compile()
36+
JtdValidator interp = JtdValidator.compile(schema);
37+
```
38+
39+
## Performance
40+
41+
Benchmark results (50k warmup, 200k measured iterations):
42+
43+
| Schema | Valid doc | Invalid doc | Classfile size |
44+
|--------|-----------|-------------|----------------|
45+
| simple-type | **6.8x** faster | **2.2x** | 990 B |
46+
| enum-5 | **1.2x** | **1.5x** | 1,162 B |
47+
| nullable-int | **6.3x** | **2.2x** | 1,205 B |
48+
| properties-3 | **9.5x** | **5.3x** | 2,453 B |
49+
| props-with-optional | **12.3x** | **2.3x** | 2,112 B |
50+
| elements-of-type | **47.3x** | **3.5x** | 1,486 B |
51+
| values-of-type | **17.4x** | **4.0x** | 1,816 B |
52+
| nested-elements-of-props | **11.2x** | **4.1x** | 2,698 B |
53+
| discriminator-2-variants | **3.3x** | **3.5x** | 2,671 B |
54+
| ref-with-definitions | **1.9x** | **0.7x** | 3,008 B |
55+
| deep-nesting | **0.7x** | **0.5x** | 3,406 B |
56+
| worked-example-rfc8927 | **2.9x** | **3.6x** | 5,565 B |
57+
| **Average** | **8.7x** | **3.1x** ||
58+
59+
Codegen shines for array iteration (`elements-of-type` at 47x, `values-of-type` at 17x) and property validation (9-12x). It's slower on deeply nested schemas and ref-heavy schemas where bytecode overhead outweighs interpreter dispatch cost.
60+
61+
## When to Use Codegen
62+
63+
- **Use codegen when**: validating the same schema against many documents (e.g., event processing, API gateways)
64+
- **Use interpreter when**: one-off validation, JDK 21 runtime, or schemas dominated by deep refs/nesting
65+
66+
## Build
67+
68+
```bash
69+
# Automatically included on JDK 24+, skipped on JDK 21
70+
./mvnw test -pl json-java21-jtd-codegen -am -Djava.util.logging.ConsoleHandler.level=INFO
71+
```
72+
73+
The parent `pom.xml` uses a profile (`jtd-codegen`) that activates on `<jdk>[24,)</jdk>`, so the module is automatically skipped when building with JDK 21.

pom.xml

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@
4242
<module>json-compatibility-suite</module>
4343
<module>json-java21-jtd</module>
4444
<module>json-java21-jsonpath</module>
45-
<module>json-java21-jtd-codegen</module>
4645
</modules>
4746

4847
<properties>
@@ -213,6 +212,17 @@
213212
</plugins>
214213
</build>
215214
</profile>
215+
216+
<!-- JTD Codegen module requires JDK 24+ (ClassFile API, JEP 484) -->
217+
<profile>
218+
<id>jtd-codegen</id>
219+
<activation>
220+
<jdk>[24,)</jdk>
221+
</activation>
222+
<modules>
223+
<module>json-java21-jtd-codegen</module>
224+
</modules>
225+
</profile>
216226
</profiles>
217227

218228
</project>

0 commit comments

Comments
 (0)