JEP 423: Region Pinning for G1
JEP 423 (Region Pinning for G1) changes how the JVM handles JNI critical sections. Previously, when a thread entered native code that held a critical reference to Java objects, the JVM had to block moving (compacting) GC globally, which could delay garbage collection and lead to allocation failures. With JEP 423, the JVM pins only the heap regions containing those objects, instead of stopping GC for the entire heap. This allows GC to continue reclaiming memory in other regions, preventing artificial OOMs caused by global GC blocking.
Jira Case
Problem when native memory is allocated: https://support.atlassian.com/jira/kb/jira-running-out-of-memory-due-to-gc-allocation-race-condition/
Before JEP 423 (old behavior)
When a thread entered a JNI critical section (for example via
GetPrimitiveArrayCritical):
The JVM activated the GC locker
Certain GC phases (especially compacting / moving GC) were globally blocked
While GC was blocked:
Other threads kept allocating
Heap occupancy rose
Native + heap pressure accumulated
Eventually:
Allocation failed
JVM threw OOM or was killed
Even though a GC could have freed memory
So the failure mode was:
GC was paused globally because of native pinning, but allocation continued globally.
That mismatch is the real bug.
After JEP 423 (Region Pinning in G1)
Instead of:
“GC must stop globally while native code holds references”
The JVM now does:
“Only pin the regions that are referenced by native code”
Meaning:
Objects referenced by JNI critical sections:
are not moved
live in pinned regions
GC can still:
reclaim garbage in other regions
keep allocation pressure under control
No global GC lock
No allocation starvation
Crucially:
GC is no longer globally paused — only locally constrained.
Links:
Last updated