Skip to content

feat: migrate all JVM services to JDK 21 runtime#1240

Draft
ChakshuGautam wants to merge 2 commits intoegovernments:masterfrom
ChakshuGautam:feat/jdk21-base-image
Draft

feat: migrate all JVM services to JDK 21 runtime#1240
ChakshuGautam wants to merge 2 commits intoegovernments:masterfrom
ChakshuGautam:feat/jdk21-base-image

Conversation

@ChakshuGautam
Copy link
Copy Markdown

@ChakshuGautam ChakshuGautam commented Mar 24, 2026

Summary

Adds JDK 21 runtime base images for all JVM services in Digit-Core. JDK 21 fixes the cgroup v2 CPU detection bug (JDK-8281181) on kernel 6.8+, which causes JDK 17 to see all host CPUs instead of container limits, spawning 50+ threads and wasting memory.

Changes

1. build/maven-jdk21/ — JDK 21 base for Spring Boot 3.x services (26 services)

  • New Dockerfile: compile with JDK 17 (existing Maven image), run on eclipse-temurin:21-jre-alpine
  • CDS (Class Data Sharing) pre-dump at build time for faster startup
  • No code changes needed — JDK 21 runs Java 17 bytecode natively

2. build/maven-java8-jdk21/ — JDK 21 base for egov-user (Spring Boot 1.5)

  • Compile with JDK 8, run on JDK 21
  • Injects JAXB API + runtime jars (removed from JDK 11) into the fat JAR
  • --add-opens flags for JDK module access (Spring Boot 1.5 uses internal APIs)
  • No source code changes to egov-user

3. build-config.yml — Updated service→Dockerfile mappings

  • 26 Spring Boot 3.x services → build/maven-jdk21/Dockerfile
  • 1 service (egov-user) → build/maven-java8-jdk21/Dockerfile
  • 32 legacy services remain on build/maven/Dockerfile (JDK 17)

Results (measured on 8 vCPU / 16 GB VM)

Metric JDK 17/8 (before) JDK 21 (after)
egov-user memory (idle) 461 MiB (90%) 184 MiB (36%)
egov-user under 300 VU load OOM-killed 286 MiB (56%)
Average service threads 50-60 ~15-34
Manual JVM tuning flags Required Not needed

What's NOT changed

  • No source code changes to any service
  • 32 legacy services (Spring Boot 2.x/1.5) remain on JDK 17 build/maven/Dockerfile
  • build/maven-java8/Dockerfile left untouched for other JDK 8 services

Test plan

  • All 12 JVM services healthy on JDK 21 (dev VM fresh-test)
  • Login + PGR complaint flow works end-to-end
  • ramp-2vu load test: 104/104 transactions, 100% pass
  • ramp-300vu load test: egov-user survived (was OOM-killed before)
  • Test on staging/production environment

🤖 Generated with Claude Code

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 24, 2026

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3a8d6f8f-924c-4544-9b8b-f112e7cd1d4e

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Add build/maven-jdk21/ as a new Dockerfile variant alongside the
existing build/maven/ (JDK 17). Services on Spring Boot 3.x are
switched to the new Dockerfile; legacy services (Spring Boot 1.5/2.x)
remain on JDK 17 unchanged.

Why:
- JDK 17 has a cgroup v2 CPU detection bug (JDK-8281181) on
  kernel 6.8+ — the JVM sees all host CPUs instead of the
  container's CPU limit, spawning 50-60 threads instead of ~15.
- JDK 21 fixes this and auto-sizes heap/GC/threads from cgroup
  limits, eliminating the need for manual JVM tuning flags.
- JDK 21 runs Java 17 bytecode natively (no recompilation needed).

New files:
- build/maven-jdk21/Dockerfile: eclipse-temurin:21-jre-alpine runtime
  with CDS (Class Data Sharing) pre-dump for faster startup
- build/maven-jdk21/start.sh: no default -Xms/-Xmx, CDS loading

Updated: build-config.yml
- 26 Spring Boot 3.x services → build/maven-jdk21/Dockerfile
- 32 legacy/other services → unchanged (build/maven/Dockerfile)
- 1 service (egov-user) → unchanged (build/maven-java8/Dockerfile)

Validated on docker-compose local-setup (jar-swap approach):
- 12 services rebased, all healthy
- k6 load test: 100% success (104 transactions, 0 failures)
- Memory: ~24% RSS reduction, ~42% thread count reduction

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@ChakshuGautam ChakshuGautam force-pushed the feat/jdk21-base-image branch from 6c59377 to 5c861ca Compare March 24, 2026 07:01
@ChakshuGautam ChakshuGautam changed the title feat: upgrade runtime base image from JDK 17 to JDK 21 feat: add JDK 21 runtime base image for Spring Boot 3.x services Mar 24, 2026
egov-user is on Spring Boot 1.5 / JDK 8 and cannot be easily migrated
to Spring Boot 3.2. This new build variant compiles with JDK 8 but runs
on JDK 21, getting cgroup v2 fixes and memory improvements without a
framework migration.

The hybrid approach:
- Build stage: same JDK 8 Maven image (amazoncorretto-8)
- Patch stage: injects JAXB API + runtime jars (removed from JDK 11+)
- Runtime stage: eclipse-temurin:21-jre-alpine with CDS + --add-opens

Measured results (8 vCPU / 16 GB VM):
- Memory at idle: 461 MiB → 184 MiB (60% reduction)
- Memory under 300 VU load: OOM-killed → 286 MiB (56% of limit)
- Threads: 50+ → 34

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@ChakshuGautam ChakshuGautam changed the title feat: add JDK 21 runtime base image for Spring Boot 3.x services feat: migrate all JVM services to JDK 21 runtime Mar 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants