Skip to content

Support @WithConfig on IBM J9 8 / OpenJ9 / Semeru 11 JVMs#11388

Draft
bric3 wants to merge 1 commit into
masterfrom
bdu/fix-with-config-ext-non-openjdk
Draft

Support @WithConfig on IBM J9 8 / OpenJ9 / Semeru 11 JVMs#11388
bric3 wants to merge 1 commit into
masterfrom
bdu/fix-with-config-ext-non-openjdk

Conversation

@bric3
Copy link
Copy Markdown
Contributor

@bric3 bric3 commented May 15, 2026

What Does This Do

Fallback to unsafe when retransformation fail on old IBM J9 / Semeru 11 JVMs.

Motivation

Additional Notes

Contributor Checklist

Jira ticket: [PROJ-IDENT]

Note: Once your PR is ready to merge, add it to the merge queue by commenting /merge. /merge -c cancels the queue request. /merge -f --reason "reason" skips all merge queue checks; please use this judiciously, as some checks do not run at the PR-level. For more information, see this doc.

ByteBuddy retransformation silently fails on IBM J9 / OpenJ9 / Semeru,
leaving `InstrumenterConfig.INSTANCE` / `Config.INSTANCE` as
`private static final`.  `rebuildConfig()`'s `Field.set(null, ...)` then
throws for every test in the class — including ones with no `@WithConfig`
at all:

```
org.opentest4j.AssertionFailedError: expected: <true> but was: <false>
    at WithConfigExtension.checkWritable(WithConfigExtension.java:331)
    at WithConfigExtension.checkConfigTransformation(...:324)
    at WithConfigExtension.beforeAll(...:91)
  Suppressed: java.lang.AssertionError: Failed to rebuild config
    at WithConfigExtension.rebuildConfig(...:295)
  Caused by: java.lang.IllegalAccessException: ... InstrumenterConfig
    with modifiers "private static final"
    at java.lang.reflect.Field.set(Field.java:784)
    at WithConfigExtension.rebuildConfig(...:291)
```

This commit keep ByteBuddy as the primary mechanism to transform bytecode
bit adds a `sun.misc.Unsafe`-based fallback:

* `makeConfigInstanceModifiable()` checks the actual field modifiers and
  picks `WriteMode.REFLECTION` when retransformation worked, or
  `WriteMode.UNSAFE` otherwise.
* The Unsafe mechanism is encapsulated in a `UnsafeFieldWriter` that
  handle updating the field value via `Unsafe::putObjectVolatile`.
* Unsafe is resolved lazily and propagates `ReflectiveOperationException`
  so a JVM without `sun.misc.Unsafe` lands in the existing
  `configModificationFailed` branch.
* `ConfigInstrumentationFailedListener` now flags failures for
  `InstrumenterConfig` as well, not only `Config`.

[ci: NON_DEFAULT_JVMS]
@bric3 bric3 added tag: no release notes Changes to exclude from release notes comp: tooling Build & Tooling labels May 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp: tooling Build & Tooling tag: no release notes Changes to exclude from release notes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant