Skip to content

fix: upgrade protobuf-java to 4.36.1 to stop using sun.misc.Unsafe - #365

Merged
korniltsev-grafanista merged 1 commit into
grafana:mainfrom
korniltsev-grafanista-yolo-vibecoder239:fix-361-upgrade-dep
Sep 9, 2026
Merged

korniltsev-grafanista merged 1 commit into
grafana:mainfrom
korniltsev-grafanista-yolo-vibecoder239:fix-361-upgrade-dep

Conversation

@korniltsev-grafanista-yolo-vibecoder239

Copy link
Copy Markdown
Contributor

Fixes #361

What

Bumps the vendored com.google.protobuf:protobuf-java from 4.33.5 to 4.36.1. That is the whole change.

Why this fixes it

protobuf v36.0 stopped routing standard (non-lite) generated code through UnsafeUtil. Our JfrLabels gencode is full, not lite, so UnsafeUtil is now never class-loaded and the JDK 24+ warning never fires.

Note that 4.36.1 still contains sun.misc.Unsafe references (kept for the Lite path) and the classes are still in the shaded jar — they are just never touched. It also makes getUnsafe() probe arrayBaseOffset and fall back gracefully if it throws, which fixes the second half of the issue: with 4.33.5 the agent hard-crashes under --sun-misc-unsafe-memory-access=deny.

Gencode/runtime compatibility is fine: our checked-in gencode is 4.26.1, same major, older minor, which RuntimeVersion accepts. protobuf-java 4.36.1 still targets class file major 52 (Java 8) and has no transitive dependencies.

Verification

Built pyroscope.jar before and after via ubuntu-test.Dockerfile, ran the same labels-serializing program under Temurin 25.0.4 with -javaagent:

Before (4.33.5):

WARNING: A terminally deprecated method in sun.misc.Unsafe has been called
WARNING: sun.misc.Unsafe::arrayBaseOffset has been called by io.pyroscope.vendor.com.google.protobuf.UnsafeUtil$MemoryAccessor (file:/w/pyroscope.jar)
WARNING: Please consider reporting this to the maintainers of class io.pyroscope.vendor.com.google.protobuf.UnsafeUtil$MemoryAccessor
WARNING: sun.misc.Unsafe::arrayBaseOffset will be removed in a future release
dump bytes=39

After (4.36.1):

dump bytes=39

(The unrelated java.lang.System::load restricted-method warning from async-profiler is present in both and untouched by this PR.)

Also checked the --sun-misc-unsafe-memory-access=deny case with a plain roundtrip over our JfrLabels gencode — 4.33.5 dies with ExceptionInInitializerError / UnsupportedOperationException: arrayBaseOffset, 4.36.1 round-trips fine.

./gradlew test passes (run in the Java 11 builder container).

🤖 Generated with Claude Code

protobuf-java 4.36 stopped routing standard (non-lite) generated code
through UnsafeUtil, so the class is never loaded and JDK 24+ no longer
prints the terminally-deprecated sun.misc.Unsafe warning. It also makes
the runtime survive environments where Unsafe is present but throws
(--sun-misc-unsafe-memory-access=deny), which 4.33.x did not.

Fixes grafana#361

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@korniltsev-grafanista
korniltsev-grafanista marked this pull request as ready for review September 9, 2026 10:38
@korniltsev-grafanista
korniltsev-grafanista enabled auto-merge (squash) September 9, 2026 10:44
@korniltsev-grafanista
korniltsev-grafanista merged commit 2cc0cef into grafana:main Sep 9, 2026
92 checks passed
@korniltsev-grafanista-yolo-vibecoder239

Copy link
Copy Markdown
Contributor Author

Heads-up on a side effect of this upgrade, found while benchmarking the labels encoder in #363
not an argument against the change, which fixed the reported problem with one line and no
throughput cost.

4.36.1 encodes just as fast as 4.33.5, but allocates more, and quite a lot more for non-ASCII
strings.

Same benchmark, protobuf only, both versions driven through our LabelsSnapshot message
(map<int64, Context> + map<int64, string>) over identical fixtures in separate JVMs:

shape time 4.33.5 → 4.36.1 allocation 4.33.5 → 4.36.1
160k contexts × 2 labels, ASCII 164.93 → 168.65 ms (+2.3%) 175.8 → 179.9 MB/op (+2.3%)
10240 × 20, ASCII 135.78 → 131.53 ms (−3.1%) 71.5 → 77.5 MB/op (+8.4%)
10240 × 20, non-ASCII values 151.46 → 151.76 ms (+0.2%) 75.0 → 104.1 MB/op (+38.8%)

Every timing delta sits inside overlapping error bars, so there is no measurable throughput change.
The allocation numbers are the trustworthy half: error bars are ≤146 KB against deltas of 4–29 MB.

Likely mechanism, and it follows directly from what makes the fix work: with the full (non-lite)
gencode path no longer routing through UnsafeUtil, UTF-8 encoding falls back to the safe processor,
which allocates intermediate arrays instead of writing through Unsafe. That would explain why the
penalty is smallest for pure-ASCII label sets and largest when most strings need real multi-byte
encoding.

Practical impact is modest — this is per dump(), so per upload interval (10s by default), and it
is young-gen garbage. An app with ~200k unique non-ASCII label strings would see roughly 29 MB more
allocation per upload than it did on 4.33.5. Worth knowing for label-heavy workloads; probably not
worth acting on by itself.

Two caveats: measured on a 16-vCPU QEMU VM (ratios are more reliable than absolutes), and this is
one message shape rather than a general protobuf benchmark, so I would not extrapolate the
percentages to other schemas.

Method, raw JMH output and the full tables: the benchmark comment on
#363
and
this gist.
Each jar's runtime version was confirmed through RuntimeVersion.MAJOR/MINOR/PATCH rather than
assumed from the Gradle coordinate, and I separately reproduced the warning on 4.33.5 and its
absence on 4.36.1, which confirms the mechanism described in this PR.

🤖 Generated with Claude Code

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.

Deprecated sun.misc.Unsafe usage in vendored protobuf on JDK 25

3 participants