<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/a-peek-behind-the-curtain-of-modern-runtime-codegen-part-2--hcq7smsle" -->

---
title: A peek behind the curtain of modern runtime codegen (Part 2)
description: Hibernate Accessor generates bytecode at runtime instead of relying on MethodHandle or LambdaMetafactory, aiming for hand-written field access speed. It uses...
canonical: https://daily.dev/posts/a-peek-behind-the-curtain-of-modern-runtime-codegen-part-2--hcq7smsle
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: A peek behind the curtain of modern runtime codegen (Part 2) | daily.dev
og:description: Hibernate Accessor generates bytecode at runtime instead of relying on MethodHandle or LambdaMetafactory, aiming for hand-written field access speed. It uses...
og:url: https://daily.dev/posts/a-peek-behind-the-curtain-of-modern-runtime-codegen-part-2--hcq7smsle
og:image: https://api.daily.dev/og/posts/HcQ7SmslE.png
og:image:alt: A peek behind the curtain of modern runtime codegen (Part 2)
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# A peek behind the curtain of modern runtime codegen (Part 2)

**[Hibernate Blog](https://daily.dev/sources/hibernate-blog)** · 19 min read · 0 upvotes · 0 comments

## Summary

Hibernate Accessor generates bytecode at runtime instead of relying on MethodHandle or LambdaMetafactory, aiming for hand-written field access speed. It uses hidden classes from JEP 371, defining generated accessors as nestmates of entity classes to reach private fields. Crossing JPMS module boundaries loses the MODULE access bit on a teleported lookup, so the library builds a synthetic bridge class injected into the target package to regain it. Two generation strategies exist: BULK_SWITCH, which uses a TABLESWITCH jump table per entity, and PER_MEMBER, which generates a dedicated class per field or method. Generated accessors are cached in ClassValue via WeakReference so the cache does not strongly retain them.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://in.relation.to/2026/10/28/peek-behind-the-curtain-of-accessor-codegen>

## Questions this post answers

### Why can't I define a hidden class using a Lookup obtained across JPMS module boundaries?

Obtaining a private lookup across module boundaries (a teleported lookup) causes it to lose the MODULE access bit, per JDK-8228624. Defining hidden classes requires both PRIVATE and MODULE access bits, so a teleported lookup can no longer create a hidden class even though it can still access private members. A workaround is to inject a small named bridge class into the target package using the PACKAGE access bit that the teleported lookup retains, then obtain a fresh module-local lookup from inside that bridge.

_Working through JPMS lookup edge cases? daily.dev surfaces deep JVM internals posts like this one._

### Does inheritance make two Java classes nestmates for private field access?

No, inheritance does not make two top-level classes nestmates. A subclass and its superclass have separate nests unless they are also nested under the same nest host, so a hidden nestmate class attached to the subclass cannot access a private field declared on the superclass. Hibernate Accessor works around this by generating a separate bulk accessor in each declaring class's own nest and combining them with a coordinating multi-reader.

_daily.dev collects runtime codegen deep dives for engineers tuning JVM-level data access._

### How do you avoid memory leaks when caching generated classes per Class using ClassValue in Java?

Store the cached value behind a WeakReference instead of a strong reference inside the ClassValue slot. Because ClassValue entries live inside the key class's internal maps and can outlive the owning factory, a strongly referenced generated accessor can keep the accessor, its library classes, and classloader alive long after the factory that created it has been destroyed. A weak reference lets the accessor be collected once no other strong references remain.

_Caching per-class state safely comes up often for framework authors following JVM memory patterns on daily.dev._

## Similar posts on daily.dev

- [The quest for reflection-free access \(Part 1\)](https://daily.dev/posts/the-quest-for-reflection-free-access-part-1--5nqbuilyc) · Hibernate Blog · 0 upvotes · 0 comments
- [Decapsulation: Breaking Java Strong Encapsulation](https://daily.dev/posts/decapsulation-breaking-java-strong-encapsulation-xzmoii8fd) · Awesome Java Newsletter · 3 upvotes · 0 comments
- [Value Classes Still Need Compiler Sympathy](https://daily.dev/posts/value-classes-still-need-compiler-sympathy-6gmnyemca) · Inside Java · 0 upvotes · 0 comments
- [Reverse Engineering with Hibernate 7.4 and IntelliJ IDEA](https://daily.dev/posts/reverse-engineering-with-hibernate-7-4-and-intellij-idea-ftoyzdfii) · JetBrains · 0 upvotes · 0 comments

---

Tags: [#java](https://daily.dev/tags/java)

[View this post on daily.dev](https://daily.dev/posts/a-peek-behind-the-curtain-of-modern-runtime-codegen-part-2--hcq7smsle)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"TechArticle","headline":"A peek behind the curtain of modern runtime codegen (Part 2)","url":"https://daily.dev/posts/a-peek-behind-the-curtain-of-modern-runtime-codegen-part-2--hcq7smsle","mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/posts/a-peek-behind-the-curtain-of-modern-runtime-codegen-part-2--hcq7smsle"},"datePublished":"2026-10-28T11:20:19.495Z","dateModified":"2026-10-28T14:59:47.131Z","description":"Hibernate Accessor generates bytecode at runtime instead of relying on MethodHandle or LambdaMetafactory, aiming for hand-written field access speed. It uses...","image":"https://media.daily.dev/image/upload/s--0_ODbtD2--/f_auto/v1722860399/public/Placeholder%2008","thumbnailUrl":"https://media.daily.dev/image/upload/s--0_ODbtD2--/f_auto/v1722860399/public/Placeholder%2008","isAccessibleForFree":true,"articleSection":"Hibernate Blog","inLanguage":"en","publisher":{"@type":"Organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180}},"author":{"@type":"Organization","name":"Hibernate Blog","logo":"https://media.daily.dev/image/upload/s--vjB4--Ol--/f_auto,q_auto/v1773648769/logos/hibernate-blog?_a=BAMAMiiu0","url":"https://daily.dev/sources/hibernate-blog"},"commentCount":0,"discussionUrl":"https://daily.dev/posts/a-peek-behind-the-curtain-of-modern-runtime-codegen-part-2--hcq7smsle","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":0},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":0}],"keywords":"java","timeRequired":"PT19M"}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"Hibernate Blog","item":"https://daily.dev/sources/hibernate-blog"},{"@type":"ListItem","position":3,"name":"A peek behind the curtain of modern runtime codegen (Part 2)"}]}
{"@context":"https://schema.org","@type":"FAQPage","@id":"https://daily.dev/posts/a-peek-behind-the-curtain-of-modern-runtime-codegen-part-2--hcq7smsle#faq","mainEntity":[{"@type":"Question","name":"Why can't I define a hidden class using a Lookup obtained across JPMS module boundaries?","acceptedAnswer":{"@type":"Answer","text":"Obtaining a private lookup across module boundaries (a teleported lookup) causes it to lose the MODULE access bit, per JDK-8228624. Defining hidden classes requires both PRIVATE and MODULE access bits, so a teleported lookup can no longer create a hidden class even though it can still access private members. A workaround is to inject a small named bridge class into the target package using the PACKAGE access bit that the teleported lookup retains, then obtain a fresh module-local lookup from inside that bridge. Working through JPMS lookup edge cases? daily.dev surfaces deep JVM internals posts like this one."}},{"@type":"Question","name":"Does inheritance make two Java classes nestmates for private field access?","acceptedAnswer":{"@type":"Answer","text":"No, inheritance does not make two top-level classes nestmates. A subclass and its superclass have separate nests unless they are also nested under the same nest host, so a hidden nestmate class attached to the subclass cannot access a private field declared on the superclass. Hibernate Accessor works around this by generating a separate bulk accessor in each declaring class's own nest and combining them with a coordinating multi-reader. daily.dev collects runtime codegen deep dives for engineers tuning JVM-level data access."}},{"@type":"Question","name":"How do you avoid memory leaks when caching generated classes per Class using ClassValue in Java?","acceptedAnswer":{"@type":"Answer","text":"Store the cached value behind a WeakReference instead of a strong reference inside the ClassValue slot. Because ClassValue entries live inside the key class's internal maps and can outlive the owning factory, a strongly referenced generated accessor can keep the accessor, its library classes, and classloader alive long after the factory that created it has been destroyed. A weak reference lets the accessor be collected once no other strong references remain. Caching per-class state safely comes up often for framework authors following JVM memory patterns on daily.dev."}}]}
```

