Skip to content

Incompatibility with -XX:+UseCompactObjectHeaders #915

@ben-manes

Description

@ben-manes

Thanks for the recent fixes! If JEP 519: Compact Object Headers is enabled on JDK-25+ runs, then this impacts the unsafe object offset calculations and can lead to a crash. Disabling that option for Lincheck runs fine, so there is an easy workaround.

hs_err_pid34138.log

console
./gradlew caffeine:lincheckTest -PjavaVersion=25 --console colored
Parallel Configuration Cache is an incubating feature.
Configuration on demand is an incubating feature.
Calculating task graph as configuration cache cannot be reused because the set of Gradle properties has changed: the value of 'javaVersion' was changed.
> Task :plugins:checkKotlinGradlePluginConfigurationErrors SKIPPED
> Task :plugins:generateExternalPluginSpecBuilders UP-TO-DATE
> Task :plugins:extractPrecompiledScriptPluginPlugins UP-TO-DATE
> Task :plugins:compilePluginsBlocks UP-TO-DATE
> Task :plugins:generatePrecompiledScriptPluginAccessors UP-TO-DATE
> Task :plugins:generateScriptPluginAdapters UP-TO-DATE
> Task :plugins:compileKotlin UP-TO-DATE
> Task :plugins:compileJava NO-SOURCE
> Task :plugins:pluginDescriptors UP-TO-DATE
> Task :plugins:processResources UP-TO-DATE
> Task :plugins:classes UP-TO-DATE
> Task :plugins:jar UP-TO-DATE
> Task :caffeine:processCodeGenResources NO-SOURCE
> Task :caffeine:processResources NO-SOURCE
> Task :caffeine:processLincheckTestResources NO-SOURCE
> Task :caffeine:downloadCaffeine UP-TO-DATE
> Task :caffeine:processJavaPoetResources UP-TO-DATE
> Task :caffeine:compileJavaPoetJava FROM-CACHE
> Task :caffeine:javaPoetClasses UP-TO-DATE
> Task :caffeine:generateNodes FROM-CACHE
> Task :caffeine:generateLocalCaches
> Task :caffeine:compileJava FROM-CACHE
> Task :caffeine:classes UP-TO-DATE
> Task :caffeine:compileLincheckTestJava FROM-CACHE
> Task :caffeine:lincheckTestClasses UP-TO-DATE
> Task :caffeine:compileCodeGenJava FROM-CACHE
> Task :caffeine:codeGenClasses UP-TO-DATE
> Task :caffeine:jar FROM-CACHE
WARNING: A terminally deprecated method in sun.misc.Unsafe has been called
WARNING: sun.misc.Unsafe::putInt has been called by org.jetbrains.kotlinx.lincheck.strategy.managed.ObjectIdentityHashCodeTracker (file:/Users/ben/.gradle/caches/modules-2/files-2.1/org.jetbrains.lincheck/lincheck/3.4/f9c285404ac39baa3f36f9e94d77551b5f1fda85/lincheck-3.4.jar)
WARNING: Please consider reporting this to the maintainers of class org.jetbrains.kotlinx.lincheck.strategy.managed.ObjectIdentityHashCodeTracker
WARNING: sun.misc.Unsafe::putInt will be removed in a future release

> Task :caffeine:lincheckTest

BoundedBufferLincheckTest > concurrent_drain_expandOrRetry() STARTED

BoundedBufferLincheckTest > concurrent_offer() STARTED

BoundedBufferLincheckTest > concurrent_drain_offer() STARTED

MpscGrowableArrayQueueLincheckTest > stressTest() STARTED

MpscGrowableArrayQueueLincheckTest > modelCheckingTest() STARTED

BoundedLincheckTest > stressTest() STARTED

BoundedLincheckTest > modelCheckingTest() STARTED

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x000000010ac23324, pid=34138, tid=18435
#
# JRE version: OpenJDK Runtime Environment Temurin-25+36 (25.0+36) (build 25+36-LTS)
# Java VM: OpenJDK 64-Bit Server VM Temurin-25+36 (25+36-LTS, mixed mode, tiered, compressed oops, compact obj headers, g1 gc, bsd-aarch64)
# Problematic frame:
# V  [libjvm.dylib+0x123324]  AccessInternal::PostRuntimeDispatch<G1BarrierSet::AccessBarrier<286822ull, G1BarrierSet>, (AccessInternal::BarrierType)3, 286822ull>::oop_access_barrier(oopDesc*, long)+0x8
#
# No core dump will be written. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# An error report file with more information is saved as:
# /Users/ben/projects/caffeine/caffeine/hs_err_pid34138.log
#
# If you would like to submit a bug report, please visit:
#   https://github.com/adoptium/adoptium-support/issues
#

> Task :caffeine:lincheckTest FAILED

BoundedLincheckTest > modelCheckingTest() SKIPPED

[Incubating] Problems report is available at: file:///Users/ben/projects/caffeine/build/reports/problems/problems-report.html

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':caffeine:lincheckTest'.
> Test process encountered an unexpected problem.
   > Process 'Gradle Test Executor 21' finished with non-zero exit value 134 (this value may indicate that the process was terminated with the SIGABRT signal)

* Try:
> Check common problems https://docs.gradle.org/9.3.0-rc-2/userguide/java_testing.html#sec:java_testing_troubleshooting.
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Get more help at https://help.gradle.org.

Deprecated Gradle features were used in this build, making it incompatible with Gradle 10.

You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.

For more on this, please refer to https://docs.gradle.org/9.3.0-rc-2/userguide/command_line_interface.html#sec:command_line_warnings in the Gradle documentation.

BUILD FAILED in 8m 47s
19 actionable tasks: 2 executed, 6 from cache, 11 up-to-date

Publishing Build Scan to Develocity...
https://caffeine.gradle-enterprise.cloud/s/o5fzrldq2ogti
AI analysis

What The hs_err Log Says

The JVM crashed with a SIGSEGV in the VMThread while executing a safepoint VM operation G1PauseRemark (G1 concurrent mark “remark” pause): caffeine/hs_err_pid34138.log.
The “problematic frame” is inside G1’s oop load barrier (G1BarrierSet ... oop_access_barrier): caffeine/hs_err_pid34138.log.
The faulting address is 0x14 (null + 0x14), and the register dump shows x0 = 0x0 at the crash site: caffeine/hs_err_pid34138.log. That’s consistent with heap/reference metadata corruption rather than a normal Java-level failure.

Why This Looks Like “Unsafe + Compact Headers” Corruption

Your test JVM is launched with -XX:+UseCompactObjectHeaders (explicitly on the command line): caffeine/hs_err_pid34138.log and caffeine/hs_err_pid34138.log.
Lincheck 3.4 is also clearly using Unsafe to write fields (UnsafeHolderKt::writeFieldViaUnsafe shows up as an actively compiled hot method in the crash log): caffeine/hs_err_pid34138.log.
Separately, your Gradle output already warned that Lincheck’s ObjectIdentityHashCodeTracker calls sun.misc.Unsafe::putInt (and JDK 25 warns it’s terminally deprecated). That class name and behavior are consistent with writing into object/header-adjacent state, which becomes especially risky once object header layouts change (as with compact headers).
Net: the crash site (GC remark / reference processing) is where corrupted oop fields tend to be detected “too late”; the cause is usually earlier memory corruption from unsafe writes.

Fix / Workaround Implemented In This Repo

I found the flag injection in the shared test lifecycle plugin and changed it so Lincheck test tasks on JDK 25+ explicitly disable compact headers while other tests keep them enabled: testing.caffeine.gradle.kts:53-60.
After that change, running Lincheck on JDK 25 no longer crashed for the previously-starting class; :caffeine:lincheckTest --tests com.github.benmanes.caffeine.cache.BoundedBufferLincheckTest completed successfully (the Unsafe deprecation warning remains, but no VM crash).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions