Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ plugins {

id("com.diffplug.spotless") version "8.4.0"
id("me.champeau.gradle.japicmp") version "0.4.3"
id("com.github.spotbugs") version "6.5.5"
id("com.github.spotbugs") version "6.5.6"
id("de.thetaphi.forbiddenapis") version "3.10"
id("io.github.gradle-nexus.publish-plugin") version "2.0.0"
alias(libs.plugins.shadow) apply false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,9 @@ public static void shutdown(final boolean sync) {
}
}

@SuppressFBWarnings(
value = "USO_UNSAFE_STATIC_METHOD_SYNCHRONIZATION",
justification = "Agent-internal class; Class lock does not escape to application code")
Comment thread
AlexeyKuznetsov-DD marked this conversation as resolved.
public static synchronized Class<?> installAgentCLI() throws Exception {
if (null == AGENT_CLASSLOADER) {
// in CLI mode we skip installation of instrumentation because we're not running as an agent
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package datadog.trace.bootstrap;

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.util.function.Function;

public interface WeakMap<K, V> {
Expand All @@ -26,6 +27,9 @@ public static <K, V> WeakMap<K, V> newWeakMap() {
return SUPPLIER.get();
}

@SuppressFBWarnings(
value = "USO_UNSAFE_STATIC_METHOD_SYNCHRONIZATION",
justification = "Agent-internal holder; Class lock does not escape to application code")
Comment thread
AlexeyKuznetsov-DD marked this conversation as resolved.
public static synchronized void registerIfAbsent(Supplier supplier) {
if (null == SUPPLIER) {
SUPPLIER = supplier;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package datadog.trace.bootstrap.instrumentation.usm;

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;

public interface UsmExtractor {
void send(UsmMessage message);

Expand All @@ -10,6 +12,9 @@ public static void send(UsmMessage message) {
SUPPLIER.send(message);
}

@SuppressFBWarnings(
value = "USO_UNSAFE_STATIC_METHOD_SYNCHRONIZATION",
justification = "Agent-internal holder; Class lock does not escape to application code")

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@typotter Please confirm that this suppression is correct.

public static synchronized void registerIfAbsent(UsmExtractor supplier) {
if (SUPPLIER == null) {
SUPPLIER = supplier;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package datadog.trace.bootstrap.instrumentation.usm;

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;

public interface UsmMessageFactory {
UsmMessage getCloseMessage(UsmConnection connection);

Expand All @@ -17,6 +19,9 @@ public static UsmMessage getRequestMessage(
return SUPPLIER.getRequestMessage(connection, buffer, bufferOffset, len);
}

@SuppressFBWarnings(
value = "USO_UNSAFE_STATIC_METHOD_SYNCHRONIZATION",
justification = "Agent-internal holder; Class lock does not escape to application code")
Comment on lines +22 to +24

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@typotter Please confirm that this suppression is correct.

public static synchronized void registerIfAbsent(UsmMessageFactory supplier) {
if (null == SUPPLIER) {
SUPPLIER = supplier;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import datadog.trace.bootstrap.instrumentation.api.Tags;
import datadog.trace.core.DDTraceCoreInfo;
import datadog.trace.util.TagsHelper;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.io.IOException;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.Instrumentation;
Expand Down Expand Up @@ -75,6 +76,9 @@ public class DebuggerAgent {
static final AtomicBoolean symDBEnabled = new AtomicBoolean();
private static ClassesToRetransformFinder classesToRetransformFinder;

@SuppressFBWarnings(
value = "USO_UNSAFE_STATIC_METHOD_SYNCHRONIZATION",
justification = "Agent-internal class; Class object does not escape to application code")
Comment on lines +79 to +81

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jpbempel Please confirm that this suppression is correct.

public static synchronized void run(
Config config, Instrumentation inst, SharedCommunicationObjects sco) {
instrumentation = inst;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import datadog.metrics.api.statsd.StatsDClient;
import datadog.metrics.impl.statsd.DDAgentStatsDClientManager;
import datadog.trace.api.Config;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;

/** implements a StatsD client for internal debugger agent metrics */
public class DebuggerMetrics implements StatsDClient {
Expand All @@ -29,6 +30,9 @@ private DebuggerMetrics(Config config) {
}
}

@SuppressFBWarnings(
value = {"USO_UNSAFE_METHOD_SYNCHRONIZATION", "USO_UNSAFE_STATIC_METHOD_SYNCHRONIZATION"},
justification = "Agent-internal singleton; neither Class object nor instance monitor escapes")
Comment on lines +33 to +35

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jpbempel Please confirm that this suppression is correct.

public static synchronized DebuggerMetrics getInstance(Config config) {
if (INSTANCE == null) {
INSTANCE = new DebuggerMetrics(config);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,18 @@
import datadog.trace.core.servicediscovery.ForeignMemoryWriterFactory;
import datadog.trace.core.servicediscovery.ServiceDiscovery;
import datadog.trace.core.servicediscovery.ServiceDiscoveryFactory;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class TracerInstaller {
private static final Logger log = LoggerFactory.getLogger(TracerInstaller.class);

/** Register a global tracer if no global tracer is already registered. */
@SuppressFBWarnings(
value = "USO_UNSAFE_STATIC_METHOD_SYNCHRONIZATION",
justification =
"Agent-internal class; Class object does not escape to app code and lock only guards one-time tracer install.")
Comment thread
AlexeyKuznetsov-DD marked this conversation as resolved.
public static synchronized void installGlobalTracer(
SharedCommunicationObjects sharedCommunicationObjects,
ProfilingContextIntegration profilingContextIntegration) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import datadog.trace.api.profiling.RecordingDataListener;
import datadog.trace.api.profiling.RecordingType;
import datadog.trace.bootstrap.config.provider.ConfigProvider;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.io.IOException;
import java.lang.instrument.Instrumentation;
import java.lang.ref.WeakReference;
Expand Down Expand Up @@ -95,6 +96,10 @@ public void onNewData(RecordingType type, RecordingData data, boolean handleSync
* Main entry point into profiling Note: this must be reentrant because we may want to start
* profiling before any other tool, and then attempt to start it again at normal time
*/
@SuppressFBWarnings(
value = "USO_UNSAFE_STATIC_METHOD_SYNCHRONIZATION",
justification =
"Agent-internal class; Class object does not escape to app code and lock only guards reentrant one-time profiler startup.")
Comment on lines +99 to +102

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jbachorik Please confirm that this suppression is correct.

public static synchronized boolean run(final boolean earlyStart, Instrumentation inst)
throws IllegalArgumentException, IOException {
if (profiler == null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package datadog.trace.agent.tooling;

import datadog.instrument.utils.ClassLoaderValue;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicLongArray;
import org.slf4j.Logger;
Expand Down Expand Up @@ -121,6 +122,15 @@ public static void blockInstrumentation(ClassLoader classLoader, int instrumenta
}

/** Records that the instrumentation is blocked by default. */
// Claude: SpotBugs USO_UNSAFE_ACCESSIBLE_OBJECT_SYNCHRONIZATION: should be reviewed by team.
// The lock object is the non-final 'defaultState' array, which is reassigned in
// resetDefaultState(); a reset racing with this method could leave threads synchronizing on
// different array instances, and reads in currentState/updateState are unsynchronized. The field
// is private so app code can't lock it, but the reassignable-lock smell warrants a look.
@SuppressFBWarnings(
value = "USO_UNSAFE_ACCESSIBLE_OBJECT_SYNCHRONIZATION",
justification =
"Locks the reassignable 'defaultState' array; private to the agent but lock-object identity can change on reset, so flagged for team review.")
Comment on lines +125 to +133

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mcculls Please confirm that this suppression is correct.

@mcculls mcculls Jul 7, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment is overly verbose - basically this is ok because of how it is called.

resetDefaultState() is only called once, before installing the ByteBuddy agent. This is always before any instrumentations might call blockInstrumentation() because those are installed by the same code that installs ByteBuddy. This provides the necessary happens-before relationship.

Also note that this particular blockInstrumentation() method is not used yet - it was added to support blocking instrumentations by default in AgentInstaller during startup (instead of checks like muzzle blocking them, which call the other blockInstrumentation() helper)

So we could also just remove this method...

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @mcculls I will remove comment and update justification.

public static void blockInstrumentation(int instrumentationId) {
int bitIndex = instrumentationId << 1;
int wordIndex = bitIndex >> ADDRESS_BITS_PER_WORD;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import static datadog.trace.agent.tooling.bytebuddy.ClassFileLocators.classFileLocator;

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.lang.instrument.ClassFileTransformer;
import net.bytebuddy.pool.TypePool;

Expand Down Expand Up @@ -40,6 +41,10 @@ public static void clear() {
SUPPLIER.clear();
}

@SuppressFBWarnings(
value = "USO_UNSAFE_STATIC_METHOD_SYNCHRONIZATION",
justification =
"Agent-internal holder; Class object does not escape to app code and lock only guards one-time supplier registration.")
Comment thread
AlexeyKuznetsov-DD marked this conversation as resolved.
public static synchronized void registerIfAbsent(Supplier supplier) {
if (null == SUPPLIER) {
SUPPLIER = supplier;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import datadog.trace.agent.tooling.bytebuddy.SharedTypePools;
import de.thetaphi.forbiddenapis.SuppressForbidden;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import net.bytebuddy.description.ByteCodeElement;
import net.bytebuddy.description.NamedElement;
import net.bytebuddy.description.annotation.AnnotationSource;
Expand Down Expand Up @@ -98,6 +99,10 @@ ElementMatcher.Junction<T> isAnnotatedWith(NameMatchers.OneOf<? super NamedEleme
return ElementMatchers.isAnnotatedWith(matcher);
}

@SuppressFBWarnings(
value = "USO_UNSAFE_STATIC_METHOD_SYNCHRONIZATION",
justification =
"Agent-internal holder; Class object does not escape to app code and lock only guards one-time supplier registration.")
Comment thread
AlexeyKuznetsov-DD marked this conversation as resolved.
public static synchronized void registerIfAbsent(Supplier supplier) {
if (null == SUPPLIER) {
SUPPLIER = supplier;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import datadog.trace.api.civisibility.events.TestSuiteDescriptor;
import datadog.trace.api.civisibility.telemetry.tag.TestFrameworkInstrumentation;
import datadog.trace.util.ConcurrentEnumMap;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.util.Collection;
import java.util.Map;

Expand All @@ -17,6 +18,9 @@ public abstract class TestEventsHandlerHolder {
TestFrameworkInstrumentation, TestEventsHandler<TestSuiteDescriptor, TestDescriptor>>
HANDLERS = new ConcurrentEnumMap<>(TestFrameworkInstrumentation.class);

@SuppressFBWarnings(
value = "USO_UNSAFE_STATIC_METHOD_SYNCHRONIZATION",
justification = "Holder class not exposed to application code; locking on its Class is safe")
Comment on lines +21 to +23

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@daniel-mohedano Please confirm that this suppression is correct.

public static synchronized void start(
TestFrameworkInstrumentation framework, Collection<LibraryCapability> capabilities) {
TestEventsHandler<TestSuiteDescriptor, TestDescriptor> handler = HANDLERS.get(framework);
Expand All @@ -29,6 +33,9 @@ public static synchronized void start(
}

/** Used by instrumentation tests */
@SuppressFBWarnings(
value = "USO_UNSAFE_STATIC_METHOD_SYNCHRONIZATION",
justification = "Holder class not exposed to application code; locking on its Class is safe")
public static synchronized void stop(TestFrameworkInstrumentation framework) {
TestEventsHandler<TestSuiteDescriptor, TestDescriptor> handler = HANDLERS.remove(framework);
if (handler != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import datadog.trace.api.civisibility.config.TestIdentifier;
import datadog.trace.api.civisibility.config.TestSourceData;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
Expand All @@ -24,6 +25,9 @@ private TestDataFactory() {}
private static volatile Map<String, Predicate<TestDescriptor>>
TEST_DESCRIPTOR_FILTER_BY_ENGINE_ID = Collections.emptyMap();

@SuppressFBWarnings(
value = "USO_UNSAFE_STATIC_METHOD_SYNCHRONIZATION",
justification = "Holder class not exposed to application code; locking on its Class is safe")
Comment on lines +28 to +30

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@daniel-mohedano Please confirm that this suppression is correct.

public static synchronized void register(
String engineId,
Function<TestDescriptor, TestIdentifier> testIdentifierFactory,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import datadog.trace.api.civisibility.telemetry.tag.TestFrameworkInstrumentation;
import datadog.trace.bootstrap.ContextStore;
import datadog.trace.util.ConcurrentEnumMap;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.util.Map;
import org.junit.platform.engine.TestDescriptor;
import org.junit.platform.engine.TestEngine;
Expand All @@ -22,6 +23,9 @@ public abstract class TestEventsHandlerHolder {
private static volatile ContextStore<TestDescriptor, TestExecutionTracker>
EXECUTION_TRACKER_STORE;

@SuppressFBWarnings(
value = "USO_UNSAFE_STATIC_METHOD_SYNCHRONIZATION",
justification = "Holder class not exposed to application code; locking on its Class is safe")
Comment on lines +26 to +28

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@daniel-mohedano Please confirm that this suppression is correct.

public static synchronized void setExecutionTrackerStore(
ContextStore<TestDescriptor, TestExecutionTracker> executionTrackerStore) {
if (EXECUTION_TRACKER_STORE == null) {
Expand All @@ -44,6 +48,9 @@ public static TestExecutionTracker getExecutionTracker(TestDescriptor testDescri
}
}

@SuppressFBWarnings(
value = "USO_UNSAFE_STATIC_METHOD_SYNCHRONIZATION",
justification = "Holder class not exposed to application code; locking on its Class is safe")
Comment on lines +51 to +53

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@daniel-mohedano Please confirm that this suppression is correct.

public static synchronized void start(
TestEngine testEngine,
ContextStore<TestDescriptor, DDTestSuite> suiteStore,
Expand All @@ -62,6 +69,9 @@ public static synchronized void start(
}

/** Used by instrumentation tests */
@SuppressFBWarnings(
value = "USO_UNSAFE_STATIC_METHOD_SYNCHRONIZATION",
justification = "Holder class not exposed to application code; locking on its Class is safe")
Comment on lines +72 to +74

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@daniel-mohedano Please confirm that this suppression is correct.

public static synchronized void stop() {
for (TestEventsHandler<TestDescriptor, TestDescriptor> handler : HANDLERS.values()) {
handler.close();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import datadog.trace.api.sampling.SamplingMechanism;
import datadog.trace.bootstrap.instrumentation.api.AgentSpan;
import datadog.trace.bootstrap.instrumentation.api.AgentTracer;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.lang.reflect.Field;
import java.util.Map;
import org.apache.spark.launcher.SparkAppHandle;
Expand All @@ -30,6 +31,10 @@ public class SparkLauncherListener implements SparkAppHandle.Listener {
private static long submittedTimeMs = 0L;
private static long runningTimeMs = 0L;

@SuppressFBWarnings(
value = "USO_UNSAFE_STATIC_METHOD_SYNCHRONIZATION",
justification =
"Listener class not exposed to application code; locking on its Class is safe")
Comment on lines +34 to +37

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@aboitreaud Please confirm that this suppression is correct.

public static synchronized void createLauncherSpan(Object launcher) {
if (launcherSpan != null) {
return;
Expand Down Expand Up @@ -70,6 +75,10 @@ public static synchronized void createLauncherSpan(Object launcher) {
}
}

@SuppressFBWarnings(
value = "USO_UNSAFE_STATIC_METHOD_SYNCHRONIZATION",
justification =
"Listener class not exposed to application code; locking on its Class is safe")
public static synchronized void finishSpan(boolean isError, String errorMessage) {
AgentSpan span = launcherSpan;
if (span == null) {
Expand All @@ -85,6 +94,10 @@ public static synchronized void finishSpan(boolean isError, String errorMessage)
launcherSpan = null;
}

@SuppressFBWarnings(
value = "USO_UNSAFE_STATIC_METHOD_SYNCHRONIZATION",
justification =
"Listener class not exposed to application code; locking on its Class is safe")
public static synchronized void finishSpanWithThrowable(Throwable throwable) {
AgentSpan span = launcherSpan;
if (span == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ public abstract class TestEventsHandlerHolder {

private static ContextStore<ITestResult, DDTest> TEST_STORE;

@SuppressFBWarnings(
value = "USO_UNSAFE_STATIC_METHOD_SYNCHRONIZATION",
justification = "Holder class not exposed to application code; locking on its Class is safe")
Comment on lines +18 to +20

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@daniel-mohedano Please confirm that this suppression is correct.

public static synchronized void setContextStore(ContextStore<ITestResult, DDTest> testStore) {
if (TEST_STORE == null) {
TEST_STORE = testStore;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import datadog.trace.api.civisibility.execution.TestExecutionTracker;
import datadog.trace.api.civisibility.telemetry.tag.TestFrameworkInstrumentation;
import datadog.trace.api.time.SystemTimeSource;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Collections;
Expand All @@ -28,6 +29,10 @@ public class DatadogWeaverReporter {
private static volatile TestEventsHandler<TestSuiteDescriptor, TestDescriptor>
TEST_EVENTS_HANDLER;

@SuppressFBWarnings(
value = "USO_UNSAFE_STATIC_METHOD_SYNCHRONIZATION",
justification =
"Reporter class not exposed to application code; locking on its Class is safe")
Comment on lines +32 to +35

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@daniel-mohedano Please confirm that this suppression is correct.

public static synchronized void start() {
if (TEST_EVENTS_HANDLER == null) {
TEST_EVENTS_HANDLER =
Expand All @@ -37,6 +42,10 @@ public static synchronized void start() {
}

/** Used by instrumentation tests */
@SuppressFBWarnings(
value = "USO_UNSAFE_STATIC_METHOD_SYNCHRONIZATION",
justification =
"Reporter class not exposed to application code; locking on its Class is safe")
Comment on lines +45 to +48

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@daniel-mohedano Please confirm that this suppression is correct.

public static synchronized void stop() {
if (TEST_EVENTS_HANDLER != null) {
TEST_EVENTS_HANDLER.close();
Expand Down
Loading
Loading