Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

In a modular application, sun.misc.Unsafe is a problem #6913

Closed
io7m opened this issue Nov 30, 2024 · 3 comments · Fixed by #6920
Closed

In a modular application, sun.misc.Unsafe is a problem #6913

io7m opened this issue Nov 30, 2024 · 3 comments · Fixed by #6920
Labels
Bug Something isn't working

Comments

@io7m
Copy link

io7m commented Nov 30, 2024

Describe the bug

When running an application that exclusively uses the module path, and places its own modules plus those of OpenTelemetry on the module path, I get errors like this:

   cardant: WARN: io.opentelemetry.sdk.metrics.export.PeriodicMetricReader: Exporter threw an Exception
   java.lang.NoClassDefFoundError: Could not initialize class io.opentelemetry.exporter.internal.marshal.UnsafeString
           at io.opentelemetry.exporter.internal@1.44.1/io.opentelemetry.exporter.internal.marshal.StatelessMarshalerUtil.getUtf8Size(StatelessMarshalerUtil.java:308)
           at io.opentelemetry.exporter.internal@1.44.1/io.opentelemetry.exporter.internal.marshal.StatelessMarshalerUtil.getUtf8Size(StatelessMarshalerUtil.java:303)
           at io.opentelemetry.exporter.internal@1.44.1/io.opentelemetry.exporter.internal.marshal.StatelessMarshalerUtil.sizeStringWithContext(StatelessMarshalerUtil.java:98)
           at io.opentelemetry.exporter.internal.otlp@1.44.1/io.opentelemetry.exporter.internal.otlp.metrics.MetricStatelessMarshaler.getBinarySerializedSize(MetricStatelessMarshaler.java:202)
           at io.opentelemetry.exporter.internal.otlp@1.44.1/io.opentelemetry.exporter.internal.otlp.metrics.MetricStatelessMarshaler.getBinarySerializedSize(MetricStatelessMarshaler.java:28)
           at io.opentelemetry.exporter.internal@1.44.1/io.opentelemetry.exporter.internal.marshal.StatelessMarshalerUtil.sizeRepeatedMessageWithContext(StatelessMarshalerUtil.java:135)
           at io.opentelemetry.exporter.internal.otlp@1.44.1/io.opentelemetry.exporter.internal.otlp.metrics.InstrumentationScopeMetricsStatelessMarshaler.getBinarySerializedSize(InstrumentationScopeMetricsStatelessMarshaler.java:58)
           at io.opentelemetry.exporter.internal.otlp@1.44.1/io.opentelemetry.exporter.internal.otlp.metrics.InstrumentationScopeMetricsStatelessMarshaler.getBinarySerializedSize(InstrumentationScopeMetricsStatelessMarshaler.java:22)
           at io.opentelemetry.exporter.internal@1.44.1/io.opentelemetry.exporter.internal.marshal.StatelessMarshalerUtil$RepeatedElementPairSizeCalculator.accept(StatelessMarshalerUtil.java:263)
           at java.base/java.util.IdentityHashMap.forEach(Unknown Source)
           at io.opentelemetry.exporter.internal@1.44.1/io.opentelemetry.exporter.internal.marshal.StatelessMarshalerUtil.sizeRepeatedMessageWithContext(StatelessMarshalerUtil.java:188)
           at io.opentelemetry.exporter.internal.otlp@1.44.1/io.opentelemetry.exporter.internal.otlp.metrics.ResourceMetricsStatelessMarshaler.getBinarySerializedSize(ResourceMetricsStatelessMarshaler.java:70)
           at io.opentelemetry.exporter.internal.otlp@1.44.1/io.opentelemetry.exporter.internal.otlp.metrics.ResourceMetricsStatelessMarshaler.getBinarySerializedSize(ResourceMetricsStatelessMarshaler.java:28)
           at io.opentelemetry.exporter.internal@1.44.1/io.opentelemetry.exporter.internal.marshal.StatelessMarshalerUtil$RepeatedElementPairSizeCalculator.accept(StatelessMarshalerUtil.java:263)
           at java.base/java.util.IdentityHashMap.forEach(Unknown Source)
           at io.opentelemetry.exporter.internal@1.44.1/io.opentelemetry.exporter.internal.marshal.StatelessMarshalerUtil.sizeRepeatedMessageWithContext(StatelessMarshalerUtil.java:188)
           at io.opentelemetry.exporter.internal.otlp@1.44.1/io.opentelemetry.exporter.internal.otlp.metrics.LowAllocationMetricsRequestMarshaler.calculateSize(LowAllocationMetricsRequestMarshaler.java:84)
           at io.opentelemetry.exporter.internal.otlp@1.44.1/io.opentelemetry.exporter.internal.otlp.metrics.LowAllocationMetricsRequestMarshaler.initialize(LowAllocationMetricsRequestMarshaler.java:57)
           at io.opentelemetry.exporter.internal.otlp@1.44.1/io.opentelemetry.exporter.internal.otlp.metrics.MetricReusableDataMarshaler.export(MetricReusableDataMarshaler.java:45)
           at io.opentelemetry.exporter.otlp@1.44.1/io.opentelemetry.exporter.otlp.metrics.OtlpGrpcMetricExporter.export(OtlpGrpcMetricExporter.java:107)
           at io.opentelemetry.sdk.metrics@1.44.1/io.opentelemetry.sdk.metrics.export.PeriodicMetricReader$Scheduled.doRun(PeriodicMetricReader.java:167)
           at io.opentelemetry.sdk.metrics@1.44.1/io.opentelemetry.sdk.metrics.export.PeriodicMetricReader$Scheduled.run(PeriodicMetricReader.java:153)
           at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
           at java.base/java.util.concurrent.FutureTask.runAndReset(Unknown Source)
           at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source)
           at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
           at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
           at java.base/java.lang.Thread.run(Unknown Source)
   Caused by: java.lang.ExceptionInInitializerError: Exception java.lang.NoClassDefFoundError: sun/misc/Unsafe [in thread "PeriodicMetricReader-1"]
           at io.opentelemetry.exporter.internal@1.44.1/io.opentelemetry.exporter.internal.marshal.UnsafeAccess$UnsafeHolder.getUnsafe(UnsafeAccess.java:85)
           at io.opentelemetry.exporter.internal@1.44.1/io.opentelemetry.exporter.internal.marshal.UnsafeAccess$UnsafeHolder.<clinit>(UnsafeAccess.java:77)
           at io.opentelemetry.exporter.internal@1.44.1/io.opentelemetry.exporter.internal.marshal.UnsafeAccess.arrayBaseOffset(UnsafeAccess.java:64)
           at io.opentelemetry.exporter.internal@1.44.1/io.opentelemetry.exporter.internal.marshal.UnsafeString.<clinit>(UnsafeString.java:13)
           ... 28 common frames omitted

Previously, I'd get a warning about a missing sun.misc.Unsafe class, but everything would still work correctly.

Steps to reproduce

It seems like placing the OpenTelemetry artifacts on the module path is enough to trigger this.

What did you expect to see?

No exceptions.

What did you see instead?

A rather nasty exception, and no telemetry being sent.

What version and what artifacts are you using?

1.44.1.

https://github.com/io7m-com/cardant/blob/db0178a55f80d2a5f729da6cb22af56ebdfa5a94/pom.xml#L530

Environment

openjdk version "23" 2024-09-17
OpenJDK Runtime Environment (build 23)
OpenJDK 64-Bit Server VM (build 23, mixed mode, sharing)
@io7m io7m added the Bug Something isn't working label Nov 30, 2024
@io7m
Copy link
Author

io7m commented Nov 30, 2024

More context: 1.43.0 doesn't have this problem.

On that version, you'll get this on startup:

WARN: io.opentelemetry.sdk.trace.internal.JcTools: Cannot create high-performance queue, reverting to ArrayBlockingQueue (java.lang.NoClassDefFoundError: sun/misc/Unsafe)

But everything works anyway.

@breedx-splk
Copy link
Contributor

Thanks @io7m for the submission. Please see the discussion in #6433 for some gory details about this.

As I understood things, this should have been guarded against in JDKs where Unsafe is no longer available (like the jdk 23 you were using). Am I safe in assuming that there is something different/special in the way you're using the module path instead of just classpath?

Would you be able to provide a repo that reproduces this error?

@io7m
Copy link
Author

io7m commented Dec 4, 2024

To my knowledge, I'm not doing anything special. The application is fully modularized and places all of its own jars and dependencies (including OpenTelemetry) on the module path. The application in question is this one:

https://github.com/io7m-com/cardant

You should just be able to mvn -DskipTests=true clean package.

The build produces a zip com.io7m.cardant.main/target/cardant-distribution.zip that contains the project jars and a trivial shell script that places the jars on the module path and runs the application. The classpath should be completely empty. Note that I've downgraded to 1.43.0 there, so you'll need to set the version in the POM back to 1.44.1.

#!/bin/sh

if [ -z "${CARDANT_HOME}" ]
then
  echo "CARDANT_HOME is unset" 1>&2
  exit 1
fi

exec /usr/bin/env java \
-p "${CARDANT_HOME}/lib" \
-m com.io7m.cardant.main/com.io7m.cardant.main.CAMain \
"$@"

If any of this is a problem, I can try to get something smaller together.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants