@@ -530,7 +530,7 @@ Java_com_datadoghq_profiler_OTelContext_readProcessCtx0(JNIEnv *env, jclass unus
530530#endif
531531}
532532
533- extern " C" DLLEXPORT jobjectArray JNICALL
533+ extern " C" DLLEXPORT jobject JNICALL
534534Java_com_datadoghq_profiler_JavaProfiler_initializeContextTLS0 (JNIEnv* env, jclass unused, jlongArray metadata) {
535535 ProfiledThread* thrd = ProfiledThread::current ();
536536 assert (thrd != nullptr );
@@ -541,35 +541,37 @@ Java_com_datadoghq_profiler_JavaProfiler_initializeContextTLS0(JNIEnv* env, jcla
541541
542542 OtelThreadContextRecord* record = thrd->getOtelContextRecord ();
543543
544+ // Contiguity of record + tag_encodings + LRS is enforced by alignas(8) on _otel_ctx_record
545+ // plus sizeof(OtelThreadContextRecord) being a multiple of 8 (see thread.h).
546+ // Compile-time alignment check always runs; runtime pointer-layout check is debug-only.
547+ static_assert (DD_TAGS_CAPACITY * sizeof (u32 ) % alignof (u64 ) == 0 ,
548+ " tag encodings array size must be aligned to u64 for contiguous sidecar layout" );
549+ #ifdef DEBUG
550+ uint8_t * record_start = reinterpret_cast <uint8_t *>(record);
551+ uint8_t * sidecar_start = reinterpret_cast <uint8_t *>(thrd->getOtelTagEncodingsPtr ());
552+ assert (sidecar_start == record_start + OTEL_MAX_RECORD_SIZE
553+ && " _otel_ctx_record and _otel_tag_encodings must be contiguous" );
554+ #endif
555+
544556 // Fill metadata[6]: [VALID_OFFSET, TRACE_ID_OFFSET, SPAN_ID_OFFSET,
545- // ATTRS_DATA_SIZE_OFFSET, ATTRS_DATA_OFFSET, LRS_SIDECAR_OFFSET]
557+ // ATTRS_DATA_SIZE_OFFSET, ATTRS_DATA_OFFSET, LRS_OFFSET].
558+ // All offsets are absolute within the unified buffer returned below.
546559 if (metadata != nullptr && env->GetArrayLength (metadata) >= 6 ) {
547560 jlong meta[6 ];
548561 meta[0 ] = (jlong)offsetof (OtelThreadContextRecord, valid);
549562 meta[1 ] = (jlong)offsetof (OtelThreadContextRecord, trace_id);
550563 meta[2 ] = (jlong)offsetof (OtelThreadContextRecord, span_id);
551564 meta[3 ] = (jlong)offsetof (OtelThreadContextRecord, attrs_data_size);
552565 meta[4 ] = (jlong)offsetof (OtelThreadContextRecord, attrs_data);
553- meta[5 ] = (jlong)(DD_TAGS_CAPACITY * sizeof (u32 )); // LRS sidecar offset in sidecar buffer
566+ meta[5 ] = (jlong)(OTEL_MAX_RECORD_SIZE + DD_TAGS_CAPACITY * sizeof (u32 ));
554567 env->SetLongArrayRegion (metadata, 0 , 6 , meta);
555568 }
556569
557- // Create 2 DirectByteBuffers: [record, sidecar]
558- jclass bbClass = env->FindClass (" java/nio/ByteBuffer" );
559- jobjectArray result = env->NewObjectArray (2 , bbClass, nullptr );
560-
561- // recordBuffer: 640 bytes over the OtelThreadContextRecord
562- jobject recordBuf = env->NewDirectByteBuffer ((void *)record, (jlong)OTEL_MAX_RECORD_SIZE );
563- env->SetObjectArrayElement (result, 0 , recordBuf);
564-
565- // sidecarBuffer: covers _otel_tag_encodings[DD_TAGS_CAPACITY] + _otel_local_root_span_id (contiguous)
566- static_assert (DD_TAGS_CAPACITY * sizeof (u32 ) % alignof (u64 ) == 0 ,
567- " tag encodings array size must be aligned to u64 for contiguous sidecar layout" );
568- size_t sidecarSize = DD_TAGS_CAPACITY * sizeof (u32 ) + sizeof (u64 );
569- jobject sidecarBuf = env->NewDirectByteBuffer ((void *)thrd->getOtelTagEncodingsPtr (), (jlong)sidecarSize);
570- env->SetObjectArrayElement (result, 1 , sidecarBuf);
571-
572- return result;
570+ // Single contiguous view over [record | tag_encodings | LRS] — used for per-field
571+ // access and for bulk snapshot/restore. All three regions are in one ProfiledThread
572+ // memory block.
573+ size_t totalSize = OTEL_MAX_RECORD_SIZE + DD_TAGS_CAPACITY * sizeof (u32 ) + sizeof (u64 );
574+ return env->NewDirectByteBuffer ((void *)record, (jlong)totalSize);
573575}
574576
575577extern " C" DLLEXPORT jint JNICALL
0 commit comments