Skip to content

Commit 42ae2bd

Browse files
committed
Address review comments: use requireNonNull consistently, fix race condition in MuzzleMatcher, fix SafeServiceLoader.next()
Signed-off-by: Gregor Zeitlinger <gregor.zeitlinger@grafana.com>
1 parent 9891c81 commit 42ae2bd

10 files changed

Lines changed: 49 additions & 54 deletions

File tree

javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/extension/instrumentation/InstrumentationModule.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
import java.util.List;
2020
import java.util.Set;
2121
import java.util.logging.Logger;
22-
import javax.annotation.Nullable;
2322
import net.bytebuddy.matcher.ElementMatcher;
2423

2524
/**
@@ -108,7 +107,7 @@ public boolean defaultEnabled() {
108107
* @deprecated Use {@link #defaultEnabled()} instead.
109108
*/
110109
@Deprecated // will be removed in 3.0.0
111-
public boolean defaultEnabled(@Nullable ConfigProperties config) {
110+
public boolean defaultEnabled(ConfigProperties config) {
112111
return defaultEnabled();
113112
}
114113

javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/AgentExtension.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
99
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
1010
import io.opentelemetry.sdk.autoconfigure.spi.Ordered;
11-
import javax.annotation.Nullable;
1211
import net.bytebuddy.agent.builder.AgentBuilder;
1312

1413
/**
@@ -27,7 +26,7 @@ public interface AgentExtension extends Ordered {
2726
* @return The customized agent. Note that this method MUST return a non-null {@link AgentBuilder}
2827
* instance that contains all customizations defined in this extension.
2928
*/
30-
AgentBuilder extend(AgentBuilder agentBuilder, @Nullable ConfigProperties config);
29+
AgentBuilder extend(AgentBuilder agentBuilder, ConfigProperties config);
3130

3231
/**
3332
* Returns the name of the extension. It does not have to be unique, but it should be

javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/AgentInstaller.java

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import static io.opentelemetry.javaagent.tooling.SafeServiceLoader.load;
1010
import static io.opentelemetry.javaagent.tooling.SafeServiceLoader.loadOrdered;
1111
import static io.opentelemetry.javaagent.tooling.Utils.getResourceName;
12+
import static java.util.Objects.requireNonNull;
1213
import static java.util.logging.Level.FINE;
1314
import static java.util.logging.Level.SEVERE;
1415
import static net.bytebuddy.matcher.ElementMatchers.any;
@@ -161,7 +162,9 @@ private static void installBytebuddyAgent(
161162
AutoConfiguredOpenTelemetrySdk autoConfiguredSdk =
162163
installOpenTelemetrySdk(extensionClassLoader);
163164

164-
ConfigProperties sdkConfig = AutoConfigureUtil.getConfig(autoConfiguredSdk);
165+
ConfigProperties sdkConfig =
166+
requireNonNull(
167+
AutoConfigureUtil.getConfig(autoConfiguredSdk), "SDK config must not be null");
165168

166169
setBootstrapPackages(sdkConfig, extensionClassLoader);
167170
ConfiguredResourceAttributesHolder.initialize(
@@ -261,24 +264,24 @@ private static void installEarlyInstrumentation(
261264

262265
VirtualFieldImplementationInstallerFactory virtualFieldInstallerFactory =
263266
VirtualFieldImplementationInstallerFactory.getInstance();
264-
ClassLoader extensionsClassLoader = Utils.getExtensionsClassLoader();
265-
if (extensionsClassLoader != null) {
266-
for (EarlyInstrumentationModule earlyInstrumentationModule :
267-
loadOrdered(EarlyInstrumentationModule.class, extensionsClassLoader)) {
268-
269-
VirtualFieldImplementationInstaller contextProvider =
270-
virtualFieldInstallerFactory.create(
271-
earlyInstrumentationModule.getInstrumentationModule());
272-
extendableAgentBuilder = contextProvider.injectFields(extendableAgentBuilder);
273-
}
267+
ClassLoader extensionsClassLoader =
268+
requireNonNull(
269+
Utils.getExtensionsClassLoader(), "Extensions class loader must not be null");
270+
for (EarlyInstrumentationModule earlyInstrumentationModule :
271+
loadOrdered(EarlyInstrumentationModule.class, extensionsClassLoader)) {
272+
273+
VirtualFieldImplementationInstaller contextProvider =
274+
virtualFieldInstallerFactory.create(
275+
earlyInstrumentationModule.getInstrumentationModule());
276+
extendableAgentBuilder = contextProvider.injectFields(extendableAgentBuilder);
274277
}
275278

276279
agentBuilder = AgentBuilderUtil.optimize(extendableAgentBuilder);
277280
agentBuilder.installOn(instrumentation);
278281
}
279282

280283
private static void setBootstrapPackages(
281-
@Nullable ConfigProperties config, ClassLoader extensionClassLoader) {
284+
ConfigProperties config, ClassLoader extensionClassLoader) {
282285
BootstrapPackagesBuilderImpl builder = new BootstrapPackagesBuilderImpl();
283286
for (BootstrapPackagesConfigurer configurer :
284287
load(BootstrapPackagesConfigurer.class, extensionClassLoader)) {
@@ -294,13 +297,11 @@ private static void setDefineClassHandler() {
294297
// Need to call deprecated API for backward compatibility with extensions that haven't migrated
295298
@SuppressWarnings("deprecation")
296299
private static AgentBuilder configureIgnoredTypes(
297-
@Nullable ConfigProperties config,
298-
ClassLoader extensionClassLoader,
299-
AgentBuilder agentBuilder) {
300+
ConfigProperties config, ClassLoader extensionClassLoader, AgentBuilder agentBuilder) {
300301
IgnoredTypesBuilderImpl builder = new IgnoredTypesBuilderImpl();
301302
for (IgnoredTypesConfigurer configurer :
302303
loadOrdered(IgnoredTypesConfigurer.class, extensionClassLoader)) {
303-
configurer.configure(builder, config != null ? config : EmptyConfigProperties.INSTANCE);
304+
configurer.configure(builder, config);
304305
}
305306

306307
Trie<Boolean> ignoredTasksTrie = builder.buildIgnoredTasksTrie();

javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/DefineClassHandler.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,7 @@ private static void addSuperNames(Set<String> superNames, Class<?> clazz) {
8686

8787
@Override
8888
public void afterDefineClass(DefineClassContext context) {
89-
if (context != null) {
90-
context.exit();
91-
}
89+
context.exit();
9290
}
9391

9492
/**

javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/SafeServiceLoader.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@
1212
import java.util.Comparator;
1313
import java.util.Iterator;
1414
import java.util.List;
15+
import java.util.NoSuchElementException;
1516
import java.util.ServiceLoader;
1617
import java.util.logging.Logger;
17-
import javax.annotation.Nullable;
1818

1919
public final class SafeServiceLoader {
2020

@@ -35,9 +35,10 @@ public static <T> List<T> load(Class<T> serviceClass, ClassLoader classLoader) {
3535
List<T> result = new ArrayList<>();
3636
ServiceLoader<T> services = ServiceLoader.load(serviceClass, classLoader);
3737
for (Iterator<T> iterator = new SafeIterator<>(services.iterator()); iterator.hasNext(); ) {
38-
T service = iterator.next();
39-
if (service != null) {
40-
result.add(service);
38+
try {
39+
result.add(iterator.next());
40+
} catch (NoSuchElementException ignored) {
41+
// UnsupportedClassVersionError was thrown and handled by SafeIterator
4142
}
4243
}
4344
return result;
@@ -83,15 +84,14 @@ public boolean hasNext() {
8384
}
8485
}
8586

86-
@Nullable
8787
@Override
8888
public T next() {
8989
// jdk8 throws UnsupportedClassVersionError in next()
9090
try {
9191
return delegate.next();
9292
} catch (UnsupportedClassVersionError unsupportedClassVersionError) {
9393
handleUnsupportedClassVersionError(unsupportedClassVersionError);
94-
return null;
94+
throw new NoSuchElementException(unsupportedClassVersionError.getMessage());
9595
}
9696
}
9797
}

javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/bootstrap/BootstrapPackagesConfigurer.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
package io.opentelemetry.javaagent.tooling.bootstrap;
77

88
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
9-
import javax.annotation.Nullable;
109

1110
/**
1211
* This SPI can be used to define which packages/classes belong to the bootstrap class loader: all
@@ -25,5 +24,5 @@ public interface BootstrapPackagesConfigurer {
2524
* Configure the passed {@code builder} and define which classes should always be loaded by the
2625
* bootstrap class loader.
2726
*/
28-
void configure(BootstrapPackagesBuilder builder, @Nullable ConfigProperties config);
27+
void configure(BootstrapPackagesBuilder builder, ConfigProperties config);
2928
}

javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/instrumentation/InstrumentationLoader.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,19 @@
1717
import io.opentelemetry.javaagent.tooling.Utils;
1818
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
1919
import java.util.logging.Logger;
20-
import javax.annotation.Nullable;
2120
import net.bytebuddy.agent.builder.AgentBuilder;
2221

2322
@AutoService(AgentExtension.class)
2423
public class InstrumentationLoader implements AgentExtension {
2524
private static final Logger logger = Logger.getLogger(InstrumentationLoader.class.getName());
2625

2726
private final InstrumentationModuleInstaller instrumentationModuleInstaller =
28-
new InstrumentationModuleInstaller(InstrumentationHolder.getInstrumentation());
27+
new InstrumentationModuleInstaller(
28+
requireNonNull(
29+
InstrumentationHolder.getInstrumentation(), "Instrumentation must not be null"));
2930

3031
@Override
31-
public AgentBuilder extend(AgentBuilder agentBuilder, @Nullable ConfigProperties config) {
32+
public AgentBuilder extend(AgentBuilder agentBuilder, ConfigProperties config) {
3233
int numberOfLoadedModules = 0;
3334
ClassLoader extensionsClassLoader =
3435
requireNonNull(

javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/instrumentation/InstrumentationModuleInstaller.java

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@
4141
import java.util.List;
4242
import java.util.concurrent.atomic.AtomicBoolean;
4343
import java.util.function.Function;
44-
import javax.annotation.Nullable;
4544
import net.bytebuddy.agent.builder.AgentBuilder;
4645
import net.bytebuddy.description.annotation.AnnotationSource;
4746
import net.bytebuddy.description.type.TypeDescription;
@@ -58,20 +57,20 @@ public final class InstrumentationModuleInstaller {
5857
public static final ElementMatcher.Junction<AnnotationSource> NOT_DECORATOR_MATCHER =
5958
not(isAnnotatedWith(named("javax.decorator.Decorator")));
6059

61-
@Nullable private final Instrumentation instrumentation;
60+
private final Instrumentation instrumentation;
6261
private final VirtualFieldImplementationInstallerFactory virtualFieldInstallerFactory =
6362
VirtualFieldImplementationInstallerFactory.getInstance();
6463

65-
public InstrumentationModuleInstaller(@Nullable Instrumentation instrumentation) {
66-
this.instrumentation = instrumentation;
64+
public InstrumentationModuleInstaller(Instrumentation instrumentation) {
65+
this.instrumentation = requireNonNull(instrumentation, "Instrumentation must not be null");
6766
}
6867

6968
// Need to call deprecated API for backward compatibility with modules that haven't migrated
7069
@SuppressWarnings("deprecation")
7170
AgentBuilder install(
7271
InstrumentationModule instrumentationModule,
7372
AgentBuilder parentAgentBuilder,
74-
@Nullable ConfigProperties config) {
73+
ConfigProperties config) {
7574
if (!isInstrumentationEnabled(
7675
instrumentationModule.instrumentationNames(),
7776
instrumentationModule.defaultEnabled(config))) {
@@ -142,7 +141,7 @@ private AgentBuilder installIndyModule(
142141
helperGenerator,
143142
helperResourceBuilder.getResources(),
144143
instrumentationModule.getClass().getClassLoader(),
145-
requireNonNull(instrumentation, "Instrumentation must not be null"));
144+
instrumentation);
146145

147146
VirtualFieldImplementationInstaller contextProvider =
148147
virtualFieldInstallerFactory.create(instrumentationModule);
@@ -193,14 +192,13 @@ private AgentBuilder installInjectingModule(
193192
ClassLoader extensionsClassLoader =
194193
requireNonNull(
195194
Utils.getExtensionsClassLoader(), "Extensions class loader must not be null");
196-
Instrumentation inst = requireNonNull(instrumentation, "Instrumentation must not be null");
197195
AgentBuilder.Transformer helperInjector =
198196
new HelperInjector(
199197
instrumentationModule.instrumentationName(),
200198
helperClassNames,
201199
helperResourceBuilder.getResources(),
202200
extensionsClassLoader,
203-
inst);
201+
instrumentation);
204202
VirtualFieldImplementationInstaller contextProvider =
205203
virtualFieldInstallerFactory.create(instrumentationModule);
206204

@@ -222,7 +220,8 @@ private AgentBuilder installInjectingModule(
222220
.jpmsModulesToOpen()
223221
.forEach(
224222
(javaModule, packages) -> {
225-
ModuleOpener.open(inst, javaModule, classLoader, packages);
223+
ModuleOpener.open(
224+
instrumentation, javaModule, classLoader, packages);
226225
});
227226
openerRun.set(true);
228227
}

javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/instrumentation/MuzzleMatcher.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,9 @@
2121
import io.opentelemetry.javaagent.tooling.muzzle.ReferenceMatcher;
2222
import java.security.ProtectionDomain;
2323
import java.util.List;
24-
import java.util.concurrent.atomic.AtomicBoolean;
24+
import java.util.concurrent.atomic.AtomicReference;
2525
import java.util.logging.Level;
2626
import java.util.logging.Logger;
27-
import javax.annotation.Nullable;
2827
import net.bytebuddy.agent.builder.AgentBuilder;
2928
import net.bytebuddy.description.type.TypeDescription;
3029
import net.bytebuddy.utility.JavaModule;
@@ -41,9 +40,8 @@ class MuzzleMatcher implements AgentBuilder.RawMatcher {
4140
private final TransformSafeLogger instrumentationLogger;
4241
private final InstrumentationModule instrumentationModule;
4342
private final Level muzzleLogLevel;
44-
private final AtomicBoolean initialized = new AtomicBoolean(false);
43+
private final AtomicReference<ReferenceMatcher> referenceMatcher = new AtomicReference<>();
4544
private final Cache<ClassLoader, Boolean> matchCache = Cache.weak();
46-
@Nullable private volatile ReferenceMatcher referenceMatcher;
4745

4846
MuzzleMatcher(
4947
TransformSafeLogger instrumentationLogger, InstrumentationModule instrumentationModule) {
@@ -115,9 +113,11 @@ private boolean doesMatch(ClassLoader classLoader) {
115113
// ReferenceMatcher is lazily created to avoid unnecessarily loading the muzzle references from
116114
// the module during the agent setup
117115
private ReferenceMatcher getReferenceMatcher() {
118-
if (initialized.compareAndSet(false, true)) {
119-
referenceMatcher = ReferenceMatcher.of(instrumentationModule);
116+
ReferenceMatcher result = referenceMatcher.get();
117+
if (result == null) {
118+
referenceMatcher.compareAndSet(null, ReferenceMatcher.of(instrumentationModule));
119+
result = requireNonNull(referenceMatcher.get());
120120
}
121-
return requireNonNull(referenceMatcher);
121+
return result;
122122
}
123123
}

muzzle/src/main/java/io/opentelemetry/javaagent/tooling/HelperInjector.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -222,13 +222,12 @@ public DynamicType.Builder<?> transform(
222222

223223
private void injectHelperResources(
224224
ClassLoader classLoader, Map<String, URL> additionalResources) {
225-
if (helpersSource == null) {
226-
return;
227-
}
225+
ClassLoader source =
226+
requireNonNull(helpersSource, "helpersSource must not be null when injecting resources");
228227
for (HelperResource helperResource : helperResources) {
229228
List<URL> resources;
230229
try {
231-
resources = Collections.list(helpersSource.getResources(helperResource.getAgentPath()));
230+
resources = Collections.list(source.getResources(helperResource.getAgentPath()));
232231
} catch (IOException e) {
233232
logger.log(
234233
SEVERE,

0 commit comments

Comments
 (0)