JDK 25 compatibility: Drop JDK 8 support, JCTools 4.x, VarHandle fencing, CI modernization#6
JDK 25 compatibility: Drop JDK 8 support, JCTools 4.x, VarHandle fencing, CI modernization#6halotukozak wants to merge 19 commits intobump-dependenciesfrom
Conversation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Change jcTools_Version from "3.3.0" to "4.0.5" in build.sbt - JCTools 4.x replaces sun.misc.Unsafe with VarHandle (JDK 25-safe) - Cross-compilation verified on Scala 2.12.20, 2.13.16, 3.3.5 - Shaded monix-internal-jctools assembly rebuilt with no sun/misc references
- JCTools upgraded 3.3.0 -> 4.0.5 (VarHandle-based, JDK 25-safe) - Full JVM test suite: 20,885 tests pass, 0 failures across Scala 2.12/2.13/3.3 - Updated ROADMAP.md: Phase 4 plan 01 marked complete, in-progress status Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ions - Replace olafurpg/setup-scala@v10 with actions/setup-java@v4 (temurin) in all jobs - Add JDK 21 and 25 to jvm-tests matrix (was [8, 11], now [8, 11, 21, 25]) - Update actions/checkout@v2 -> @v4, actions/cache@v1 -> @v4, actions/setup-node@v2.1.2 -> @v4 - Update all runs-on from ubuntu-20.04 to ubuntu-latest (20.04 is EOL) - JS tests, MiMa, unidoc, publish jobs stay on JDK 8 (matrix unchanged)
- Update ROADMAP.md: phase 04 progress updated (2/2 plans complete)
Already in .gitignore, these files were tracked from before the ignore rule. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…nce() in queue wrappers - Remove direct sun.misc.Unsafe import from FromMessagePassingQueue.scala - Remove direct sun.misc.Unsafe import from FromCircularQueue.scala - Add java.lang.invoke.VarHandle import to both files - Replace UNSAFE instance field + fullFence() calls with VarHandle.fullFence() static call - Eliminates JDK 25 JEP 498 Phase 2 runtime warnings from Monix's own Scala queue files - VarHandle.fullFence() (JDK 9+) is safe since Java8* classes are guarded by HAS_JAVA8_INTRINSICS
There was a problem hiding this comment.
Pull request overview
Updates Monix’s build/tooling and CI to improve compatibility with newer JDKs (incl. JDK 25), modernizes GitHub Actions, and bumps key build dependencies (including JCTools).
Changes:
- Bumped build tooling and plugins (SBT 1.10.7, sbt plugins, scalac/tpolecat configuration) and updated JCTools to 4.0.5.
- Replaced
Unsafe.fullFence()usage withVarHandle.fullFence()in two JVM queue adapters. - Modernized CI workflows (actions v4,
ubuntu-latest, expanded JVM test matrix to JDK 8/11/21/25).
Reviewed changes
Copilot reviewed 3 out of 4 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| project/plugins.sbt | Updates sbt plugin versions; adds a dependency scheme override for geny. |
| project/build.properties | Bumps sbt version to 1.10.7. |
| monix-execution/shared/src/main/scala/monix/execution/CancelablePromise.scala | Suppresses an exhaustivity warning for a list destructure. |
| monix-execution/jvm/src/main/scala/monix/execution/internal/collection/queues/FromMessagePassingQueue.scala | Switches fencing implementation to VarHandle.fullFence(). |
| monix-execution/jvm/src/main/scala/monix/execution/internal/collection/queues/FromCircularQueue.scala | Switches fencing implementation to VarHandle.fullFence(). |
| build.sbt | Bumps versions (JCTools, plugins) and adjusts scalac/tpolecat options. |
| .jvmopts | Removes a deprecated JVM option (CMSClassUnloadingEnabled). |
| .gitignore | Ignores .planning/. |
| .github/workflows/build.yml | Modernizes actions/runners; expands JVM matrix and updates Scala versions. |
Comments suppressed due to low confidence (1)
.github/workflows/build.yml:104
- Node.js 14 is end-of-life and may eventually stop being available on GitHub-hosted runners / receive security updates. Since this workflow is being modernized, consider bumping
node-versionto a supported LTS (e.g. 18 or 20) unless Scala.js tooling here explicitly requires 14.
- name: Setup NodeJS
uses: actions/setup-node@v4
with:
node-version: 14
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
.../jvm/src/main/scala/monix/execution/internal/collection/queues/FromMessagePassingQueue.scala
Show resolved
Hide resolved
...cution/jvm/src/main/scala/monix/execution/internal/collection/queues/FromCircularQueue.scala
Show resolved
Hide resolved
olafurpg/setup-scala installed both Java and SBT. The replacement actions/setup-java@v4 only installs Java. Adding `cache: sbt` both installs SBT and caches ~/.sbt, ~/.ivy2, and ~/.cache/coursier. Also removes redundant manual cache steps — setup-java handles this. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove branch filter from pull_request trigger so CI runs regardless of target branch. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
setup-java's `cache: sbt` only caches directories, it doesn't install sbt. The old olafurpg/setup-scala bundled sbt installation. Use the official sbt/setup-sbt@v1 action to install the sbt launcher. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…tibility Updated thread naming to use `Thread.threadId` instead of deprecated `Thread.getId` across thread factory implementations.
…ed compatibility" This reverts commit 0fca646.
… implementations
…threadId` usage - Refactored thread naming logic to use `ThreadCompatOps` for backward compatibility with JDK < 19. - Removed deprecated `@nowarn` annotations from thread factory implementations.
… JDK compatibility
mikkolaj
left a comment
There was a problem hiding this comment.
Calling this MR JDK 25 compatibility is a bit misleading - current Monix version is compatible with JDK 25, but has some worrying warnings about Unsafe deprecation. You successfully switched from UNSAFE.fullFence() to VarHandle.fullFence(), but there are still lots of references to Unsafe in monix.execution.internal.atomic package.
Eliminating Unsafe usage is a valid thing to do but we have yet to decide how to do it. AtomicAny#safe(...) docs give some insight into why Unsafe was used in the first place:
* NOTE that explicit usage of this builder is not usually necessary
* because [[create]] can auto-detect whether the underlying platform
* supports `sun.misc.Unsafe` and if it does, then its usage is
* recommended, because the "safe" atomic instances have overhead.
Support for Java 7 Unsafe can be dropped like you did in another MR, but it still leaves some Unsafe leftovers in monix.execution.internal.atomic package. Two simplest ways to get rid of them seem to be:
- switching to their "safe" counterparts
- migrating from
UnsafetoVarHandle
Both of these approaches might impact performance and we don't know the exact numbers. To decide which way to go we should compare benchmarks of all three variants - "safe", Unsafe and VarHandle. You might also want to check out this MR, which fixes some problems with Monix benchmarks.
| import java.lang.invoke.{MethodHandle, MethodHandles, MethodType} | ||
|
|
||
| //todo: remove when JDK < 19 support dropped | ||
| private[monix] object ThreadCompat { |
There was a problem hiding this comment.
I'm not sure if I like this approach. Both methods still exist on JDK 25 and migration to threadId is trivial - I think we can stick with the deprecated method for now and switch to threadId when dropping support for JDK < 19. This way we'll avoid ugly reflection.
Summary
sun.misc.Unsafe.fullFence()calls withVarHandle.fullFence()(JDK 9+) inFromMessagePassingQueue.scalaandFromCircularQueue.scalaolafurpg/setup-scala@v10withactions/setup-java@v4(Temurin), updated all actions to v4, runners toubuntu-latest, added JDK 21 and 25 tojvm-testsmatrixAlso includes infrastructure updates from
bump-dependencies: SBT 1.10.7, Scala 2.12.20/2.13.16/3.3.5, sbt-tpolecat 0.5.3, plugin updates.Test plan
jvm-testsmatrix passes for all 12 combinations (JDK [8, 11, 21, 25] × Scala [2.12, 2.13, 3.3])sun.misc.Unsafewarnings are non-fatalNote: The 40+ Java atomic files and shaded JCTools JAR still use
sun.misc.Unsafefor CAS operations. On JDK 25 (JEP 498 Phase 2), these produce non-fatal warnings. On JDK 26+ (Phase 3), they will need migration toVarHandle— tracked as future work.🤖 Generated with Claude Code