Describe the bug
The JVM experiences a fatal crash (SIGSEGV) at Unsafe_GetByte when the OpenTelemetry Java agent attempts to export spans via the BatchSpanProcessor. The crash occurs within io.opentelemetry.exporter.internal.marshal.UnsafeStringEncoder.isLatin1.
Additionally, attempting to work around the issue by disabling Unsafe optimizations via system properties (-Dotel.javaagent.experimental.disable-unsafe=true and -Dio.opentelemetry.exporter.internal.marshal.UnsafeStringEncoder.enabled=false) fails. The agent appears to ignore these flags for this specific OTLP attribute marshalling execution path and continues to call sun.misc.Unsafe.getByte, resulting in the same JVM crash.
Steps to reproduce
Run WildFly v34 using OpenTelemetry Java Agent v2.26.1 on JDK 21.
Configure the agent to export via OTLP (-Dotel.metrics.exporter=otlp, -Dotel.logs.exporter=otlp, etc.).
Generate application load to trigger span batch exports.
The JVM crashes during BatchSpanProcessor$Worker.exportCurrentBatch(). Added the following flags to the JVM startup script, but the crash still occurred in the exact same frame:
-Dotel.javaagent.experimental.disable-unsafe=true -Dio.opentelemetry.exporter.internal.marshal.UnsafeStringEncoder.enabled=false
Expected behavior
The agent should safely marshal strings without causing memory segmentation faults. Furthermore, if the disable-unsafe flags are explicitly provided, the agent should strictly fall back to standard String.getBytes() APIs and completely avoid sun.misc.Unsafe calls.
Actual behavior
The JVM terminates abruptly with a SIGSEGV (memory segmentation fault) in libjvm.so at the Unsafe_GetByte frame. This crash occurs on the BatchSpanProcessor_WorkerThread-1 thread while the agent is marshalling OTLP attributes via io.opentelemetry.exporter.internal.marshal.UnsafeStringEncoder.isLatin1.
Crucially, the agent ignores explicit configuration flags intended to disable Unsafe string optimizations (-Dotel.javaagent.experimental.disable-unsafe=true and -Dio.opentelemetry.exporter.internal.marshal.UnsafeStringEncoder.enabled=false). Despite these flags being successfully parsed by the JVM on startup, the agent still executes the Unsafe.getByte() path, failing to fall back to safe string encoding and resulting in the exact same fatal crash
Javaagent or library instrumentation version
v2.26.1
Environment
Java Agent Version: 2.26.1
OS: RHEL 9.7 (running in WSL2)
JDK: OpenJDK 64-Bit Server VM Corretto-21.0.10.7.1 (21.0.10+7-LTS, mixed mode, sharing, tiered, compressed oops, compressed class ptrs, g1 gc, linux-amd64)
Application Server: WildFly 34.0.1.Final
Additional context
A fatal error has been detected by the Java Runtime Environment:
SIGSEGV (0xb) at pc=0x00007fe234510bde, pid=280, tid=298
Problematic frame:
V [libjvm.so+0xfc8bde] Unsafe_GetByte+0x8e
Current thread (0x00005561c813a540): JavaThread "BatchSpanProcessor_WorkerThread-1" daemon [_thread_in_vm, id=298, stack(0x00007fe1c7ae8000,0x00007fe1c7be8000) (1024K)]
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V [libjvm.so+0xfc8bde] Unsafe_GetByte+0x8e
J 243 jdk.internal.misc.Unsafe.getByte(Ljava/lang/Object;J)B java.base@21.0.10 (0 bytes) @ 0x00007fe2230703f7 [0x00007fe223070320+0x00000000000000d7]
j sun.misc.Unsafe.getByte(Ljava/lang/Object;J)B+5 jdk.unsupported@21.0.10
j io.opentelemetry.exporter.internal.marshal.UnsafeStringEncoder.isLatin1(Ljava/lang/String;)Z+8
j io.opentelemetry.exporter.internal.marshal.AbstractStringEncoder.getUtf8Size(Ljava/lang/String;)I+2
j io.opentelemetry.exporter.internal.marshal.StatelessMarshalerUtil.getUtf8Size(Ljava/lang/String;Lio/opentelemetry/exporter/internal/marshal/MarshalerContext;)I+12
J 59686 c1 io.opentelemetry.exporter.internal.otlp.StringAnyValueStatelessMarshaler.getBinarySerializedSize(Ljava/lang/Object;Lio/opentelemetry/exporter/internal/marshal/MarshalerContext;)I (10 bytes) @ 0x00007fe21c840884 [0x00007fe21c8406e0+0x00000000000001a4]
J 49171 c2 io.opentelemetry.exporter.internal.marshal.StatelessMarshalerUtil.sizeRepeatedMessageWithContext(Lio/opentelemetry/exporter/internal/marshal/ProtoFieldInfo;Ljava/util/List;Lio/opentelemetry/exporter/internal/marshal/StatelessMarshaler;Lio/opentelemetry/exporter/internal/marshal/MarshalerContext;)I (94 bytes) @ 0x00007fe224e1e2a4 [0x00007fe224e1dec0+0x00000000000003e4]
J 61360 c1 io.opentelemetry.exporter.internal.otlp.AttributeArrayAnyValueStatelessMarshaler.getBinarySerializedSize(Lio/opentelemetry/javaagent/shaded/io/opentelemetry/api/common/AttributeType;Ljava/util/List;Lio/opentelemetry/exporter/internal/marshal/MarshalerContext;)I (98 bytes) @ 0x00007fe21d977124 [0x00007fe21d976fa0+0x0000000000000184]
J 61359 c1 io.opentelemetry.exporter.internal.otlp.AttributeArrayAnyValueStatelessMarshaler.getBinarySerializedSize(Ljava/lang/Object;Ljava/lang/Object;Lio/opentelemetry/exporter/internal/marshal/MarshalerContext;)I (14 bytes) @ 0x00007fe21d03e624 [0x00007fe21d03e540+0x00000000000000e4]
J 39678 c1 io.opentelemetry.exporter.internal.marshal.StatelessMarshalerUtil.sizeMessageWithContext(Lio/opentelemetry/exporter/internal/marshal/ProtoFieldInfo;Ljava/lang/Object;Ljava/lang/Object;Lio/opentelemetry/exporter/internal/marshal/StatelessMarshaler2;Lio/opentelemetry/exporter/internal/marshal/MarshalerContext;)I (46 bytes) @ 0x00007fe21c0e3514 [0x00007fe21c0e3380+0x0000000000000194]
J 60909 c2 io.opentelemetry.exporter.internal.otlp.AttributeKeyValueStatelessMarshaler$ValueStatelessMarshaler.getBinarySerializedSize(Lio/opentelemetry/javaagent/shaded/io/opentelemetry/api/common/AttributeKey;Ljava/lang/Object;Lio/opentelemetry/exporter/internal/marshal/MarshalerContext;)I (155 bytes) @ 0x00007fe22538149c [0x00007fe225381220+0x000000000000027c]
...
J 53197 c2 io.opentelemetry.sdk.trace.export.BatchSpanProcessor$Worker.exportCurrentBatch()V (194 bytes) @ 0x00007fe2237a8234 [0x00007fe2237a7c40+0x00000000000005f4]
j io.opentelemetry.sdk.trace.export.BatchSpanProcessor$Worker.run()V+68
j java.lang.Thread.runWith(Ljava/lang/Object;Ljava/lang/Runnable;)V+5 java.base@21.0.10
j java.lang.Thread.run()V+19 java.base@21.0.10
Tip
React with 👍 to help prioritize this issue. Please use comments to provide useful context, avoiding +1 or me too, to help us triage it. Learn more here.
Describe the bug
The JVM experiences a fatal crash (SIGSEGV) at Unsafe_GetByte when the OpenTelemetry Java agent attempts to export spans via the BatchSpanProcessor. The crash occurs within io.opentelemetry.exporter.internal.marshal.UnsafeStringEncoder.isLatin1.
Additionally, attempting to work around the issue by disabling Unsafe optimizations via system properties (-Dotel.javaagent.experimental.disable-unsafe=true and -Dio.opentelemetry.exporter.internal.marshal.UnsafeStringEncoder.enabled=false) fails. The agent appears to ignore these flags for this specific OTLP attribute marshalling execution path and continues to call sun.misc.Unsafe.getByte, resulting in the same JVM crash.
Steps to reproduce
Run WildFly v34 using OpenTelemetry Java Agent v2.26.1 on JDK 21.
Configure the agent to export via OTLP (-Dotel.metrics.exporter=otlp, -Dotel.logs.exporter=otlp, etc.).
Generate application load to trigger span batch exports.
The JVM crashes during BatchSpanProcessor$Worker.exportCurrentBatch(). Added the following flags to the JVM startup script, but the crash still occurred in the exact same frame:
-Dotel.javaagent.experimental.disable-unsafe=true -Dio.opentelemetry.exporter.internal.marshal.UnsafeStringEncoder.enabled=false
Expected behavior
The agent should safely marshal strings without causing memory segmentation faults. Furthermore, if the disable-unsafe flags are explicitly provided, the agent should strictly fall back to standard String.getBytes() APIs and completely avoid sun.misc.Unsafe calls.
Actual behavior
The JVM terminates abruptly with a SIGSEGV (memory segmentation fault) in libjvm.so at the Unsafe_GetByte frame. This crash occurs on the BatchSpanProcessor_WorkerThread-1 thread while the agent is marshalling OTLP attributes via io.opentelemetry.exporter.internal.marshal.UnsafeStringEncoder.isLatin1.
Crucially, the agent ignores explicit configuration flags intended to disable Unsafe string optimizations (-Dotel.javaagent.experimental.disable-unsafe=true and -Dio.opentelemetry.exporter.internal.marshal.UnsafeStringEncoder.enabled=false). Despite these flags being successfully parsed by the JVM on startup, the agent still executes the Unsafe.getByte() path, failing to fall back to safe string encoding and resulting in the exact same fatal crash
Javaagent or library instrumentation version
v2.26.1
Environment
Java Agent Version: 2.26.1
OS: RHEL 9.7 (running in WSL2)
JDK: OpenJDK 64-Bit Server VM Corretto-21.0.10.7.1 (21.0.10+7-LTS, mixed mode, sharing, tiered, compressed oops, compressed class ptrs, g1 gc, linux-amd64)
Application Server: WildFly 34.0.1.Final
Additional context
A fatal error has been detected by the Java Runtime Environment:
SIGSEGV (0xb) at pc=0x00007fe234510bde, pid=280, tid=298
Problematic frame:
V [libjvm.so+0xfc8bde] Unsafe_GetByte+0x8e
Current thread (0x00005561c813a540): JavaThread "BatchSpanProcessor_WorkerThread-1" daemon [_thread_in_vm, id=298, stack(0x00007fe1c7ae8000,0x00007fe1c7be8000) (1024K)]
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V [libjvm.so+0xfc8bde] Unsafe_GetByte+0x8e
J 243 jdk.internal.misc.Unsafe.getByte(Ljava/lang/Object;J)B java.base@21.0.10 (0 bytes) @ 0x00007fe2230703f7 [0x00007fe223070320+0x00000000000000d7]
j sun.misc.Unsafe.getByte(Ljava/lang/Object;J)B+5 jdk.unsupported@21.0.10
j io.opentelemetry.exporter.internal.marshal.UnsafeStringEncoder.isLatin1(Ljava/lang/String;)Z+8
j io.opentelemetry.exporter.internal.marshal.AbstractStringEncoder.getUtf8Size(Ljava/lang/String;)I+2
j io.opentelemetry.exporter.internal.marshal.StatelessMarshalerUtil.getUtf8Size(Ljava/lang/String;Lio/opentelemetry/exporter/internal/marshal/MarshalerContext;)I+12
J 59686 c1 io.opentelemetry.exporter.internal.otlp.StringAnyValueStatelessMarshaler.getBinarySerializedSize(Ljava/lang/Object;Lio/opentelemetry/exporter/internal/marshal/MarshalerContext;)I (10 bytes) @ 0x00007fe21c840884 [0x00007fe21c8406e0+0x00000000000001a4]
J 49171 c2 io.opentelemetry.exporter.internal.marshal.StatelessMarshalerUtil.sizeRepeatedMessageWithContext(Lio/opentelemetry/exporter/internal/marshal/ProtoFieldInfo;Ljava/util/List;Lio/opentelemetry/exporter/internal/marshal/StatelessMarshaler;Lio/opentelemetry/exporter/internal/marshal/MarshalerContext;)I (94 bytes) @ 0x00007fe224e1e2a4 [0x00007fe224e1dec0+0x00000000000003e4]
J 61360 c1 io.opentelemetry.exporter.internal.otlp.AttributeArrayAnyValueStatelessMarshaler.getBinarySerializedSize(Lio/opentelemetry/javaagent/shaded/io/opentelemetry/api/common/AttributeType;Ljava/util/List;Lio/opentelemetry/exporter/internal/marshal/MarshalerContext;)I (98 bytes) @ 0x00007fe21d977124 [0x00007fe21d976fa0+0x0000000000000184]
J 61359 c1 io.opentelemetry.exporter.internal.otlp.AttributeArrayAnyValueStatelessMarshaler.getBinarySerializedSize(Ljava/lang/Object;Ljava/lang/Object;Lio/opentelemetry/exporter/internal/marshal/MarshalerContext;)I (14 bytes) @ 0x00007fe21d03e624 [0x00007fe21d03e540+0x00000000000000e4]
J 39678 c1 io.opentelemetry.exporter.internal.marshal.StatelessMarshalerUtil.sizeMessageWithContext(Lio/opentelemetry/exporter/internal/marshal/ProtoFieldInfo;Ljava/lang/Object;Ljava/lang/Object;Lio/opentelemetry/exporter/internal/marshal/StatelessMarshaler2;Lio/opentelemetry/exporter/internal/marshal/MarshalerContext;)I (46 bytes) @ 0x00007fe21c0e3514 [0x00007fe21c0e3380+0x0000000000000194]
J 60909 c2 io.opentelemetry.exporter.internal.otlp.AttributeKeyValueStatelessMarshaler$ValueStatelessMarshaler.getBinarySerializedSize(Lio/opentelemetry/javaagent/shaded/io/opentelemetry/api/common/AttributeKey;Ljava/lang/Object;Lio/opentelemetry/exporter/internal/marshal/MarshalerContext;)I (155 bytes) @ 0x00007fe22538149c [0x00007fe225381220+0x000000000000027c]
...
J 53197 c2 io.opentelemetry.sdk.trace.export.BatchSpanProcessor$Worker.exportCurrentBatch()V (194 bytes) @ 0x00007fe2237a8234 [0x00007fe2237a7c40+0x00000000000005f4]
j io.opentelemetry.sdk.trace.export.BatchSpanProcessor$Worker.run()V+68
j java.lang.Thread.runWith(Ljava/lang/Object;Ljava/lang/Runnable;)V+5 java.base@21.0.10
j java.lang.Thread.run()V+19 java.base@21.0.10
Tip
React with 👍 to help prioritize this issue. Please use comments to provide useful context, avoiding
+1orme too, to help us triage it. Learn more here.