Skip to content

Commit 0fc541f

Browse files
committed
Add NullAway null-safety annotations to javaagent-tooling and javaagent modules
Part of #15991 Enables NullAway for javaagent-tooling, javaagent-tooling-java9, and javaagent modules, and adds required @nullable annotations to AgentInstaller, AgentStarterImpl, DefineClassHandler, ExtensionClassLoader, InputStreamUrlConnection, OpenTelemetryInstaller, RemappingUrlConnection, SafeServiceLoader, Utils, ConfigurationFile, JavaagentDistributionAccessCustomizerProvider, FieldBackedImplementationInstaller, VirtualFieldImplementationsGenerator, InstrumentationLoader, InstrumentationModuleInstaller, MuzzleMatcher, RegexUrlTemplateCustomizerInitializer, IndyBootstrap, InstrumentationModuleClassLoader, ClassLoaderMap, ClassLoaderValue, Trie, and TrieImpl. Signed-off-by: Gregor Zeitlinger <gregor.zeitlinger@grafana.com>
1 parent e285081 commit 0fc541f

26 files changed

Lines changed: 104 additions & 50 deletions

javaagent-tooling/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import net.ltgt.gradle.errorprone.errorprone
22

33
plugins {
44
id("otel.java-conventions")
5+
id("otel.nullaway-conventions")
56
id("otel.publish-conventions")
67
id("otel.jmh-conventions")
78
}

javaagent-tooling/javaagent-tooling-java9/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
plugins {
22
id("otel.java-conventions")
3+
id("otel.nullaway-conventions")
34
id("otel.publish-conventions")
45
}
56

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import static io.opentelemetry.javaagent.tooling.SafeServiceLoader.loadOrdered;
1111
import static io.opentelemetry.javaagent.tooling.Utils.getResourceName;
1212
import static java.util.Collections.emptyList;
13+
import static java.util.Objects.requireNonNull;
1314
import static java.util.logging.Level.FINE;
1415
import static java.util.logging.Level.SEVERE;
1516
import static net.bytebuddy.matcher.ElementMatchers.any;
@@ -153,7 +154,9 @@ private static void installBytebuddyAgent(
153154
AutoConfiguredOpenTelemetrySdk autoConfiguredSdk =
154155
installOpenTelemetrySdk(extensionClassLoader);
155156

156-
ConfigProperties sdkConfig = AutoConfigureUtil.getConfig(autoConfiguredSdk);
157+
ConfigProperties sdkConfig =
158+
requireNonNull(
159+
AutoConfigureUtil.getConfig(autoConfiguredSdk), "SDK config must not be null");
157160

158161
setBootstrapPackages(sdkConfig, extensionClassLoader);
159162
ConfiguredResourceAttributesHolder.initialize(
@@ -287,7 +290,7 @@ private static AgentBuilder configureIgnoredTypes(
287290
IgnoredTypesBuilderImpl builder = new IgnoredTypesBuilderImpl();
288291
for (IgnoredTypesConfigurer configurer :
289292
loadOrdered(IgnoredTypesConfigurer.class, extensionClassLoader)) {
290-
configurer.configure(builder, config != null ? config : EmptyConfigProperties.INSTANCE);
293+
configurer.configure(builder, config);
291294
}
292295

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

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import java.lang.instrument.UnmodifiableClassException;
1919
import java.security.ProtectionDomain;
2020
import java.util.ServiceLoader;
21+
import javax.annotation.Nullable;
2122
import org.objectweb.asm.ClassReader;
2223
import org.objectweb.asm.ClassVisitor;
2324
import org.objectweb.asm.ClassWriter;
@@ -34,7 +35,7 @@ public class AgentStarterImpl implements AgentStarter {
3435
private final Instrumentation instrumentation;
3536
private final File javaagentFile;
3637
private final boolean isSecurityManagerSupportEnabled;
37-
private ClassLoader extensionClassLoader;
38+
@Nullable private ClassLoader extensionClassLoader;
3839

3940
public AgentStarterImpl(
4041
Instrumentation instrumentation,
@@ -142,6 +143,7 @@ private static void logUnrecognizedLoggerImplWarning(String loggerImplementation
142143
+ "'. The agent will use the no-op implementation.");
143144
}
144145

146+
@Nullable
145147
@Override
146148
public ClassLoader getExtensionClassLoader() {
147149
return extensionClassLoader;
@@ -156,6 +158,7 @@ private static class LaunchHelperClassFileTransformer implements ClassFileTransf
156158
boolean hookInserted = false;
157159
boolean transformed = false;
158160

161+
@Nullable
159162
@Override
160163
public byte[] transform(
161164
ClassLoader loader,
@@ -202,6 +205,7 @@ public void visitCode() {
202205
private static class InetAddressClassFileTransformer implements ClassFileTransformer {
203206
boolean hookInserted = false;
204207

208+
@Nullable
205209
@Override
206210
public byte[] transform(
207211
ClassLoader loader,

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

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import io.opentelemetry.javaagent.bootstrap.DefineClassHelper.Handler;
1212
import java.util.HashSet;
1313
import java.util.Set;
14+
import javax.annotation.Nullable;
1415
import org.objectweb.asm.ClassReader;
1516

1617
public class DefineClassHandler implements Handler {
@@ -27,7 +28,7 @@ public DefineClassContext beforeDefineClass(
2728
if (classBytes == null
2829
|| (classBytes.length == 40
2930
&& new String(classBytes, ISO_8859_1).startsWith("J9ROMCLASSCOOKIE"))) {
30-
return null;
31+
return DefineClassContextImpl.NOP;
3132
}
3233

3334
Set<String> superNames = new HashSet<>();
@@ -85,9 +86,7 @@ private static void addSuperNames(Set<String> superNames, Class<?> clazz) {
8586

8687
@Override
8788
public void afterDefineClass(DefineClassContext context) {
88-
if (context != null) {
89-
context.exit();
90-
}
89+
context.exit();
9190
}
9291

9392
/**
@@ -109,15 +108,15 @@ public static Set<String> getSuperTypes() {
109108
private static class DefineClassContextImpl implements DefineClassContext {
110109
private static final DefineClassContextImpl NOP = new DefineClassContextImpl();
111110

112-
private final DefineClassContextImpl previous;
113-
String failedClassDotName;
114-
Set<String> superDotNames;
111+
@Nullable private final DefineClassContextImpl previous;
112+
@Nullable String failedClassDotName;
113+
@Nullable Set<String> superDotNames;
115114

116115
private DefineClassContextImpl() {
117116
previous = null;
118117
}
119118

120-
private DefineClassContextImpl(DefineClassContextImpl previous) {
119+
private DefineClassContextImpl(@Nullable DefineClassContextImpl previous) {
121120
this.previous = previous;
122121
}
123122

@@ -130,7 +129,7 @@ static DefineClassContextImpl enter() {
130129

131130
@Override
132131
public void exit() {
133-
defineClassContext.set(previous);
132+
defineClassContext.set(previous != null ? previous : NOP);
134133
}
135134
}
136135
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ private static void includeEmbeddedExtensionsIfFound(List<URL> extensions, File
109109
}
110110
}
111111

112-
private static File ensureTempDirectoryExists(File tempDirectory) throws IOException {
112+
private static File ensureTempDirectoryExists(@Nullable File tempDirectory) throws IOException {
113113
if (tempDirectory == null) {
114114
tempDirectory = Files.createTempDirectory("otel-extensions").toFile();
115115
tempDirectory.deleteOnExit();

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import java.net.URL;
1010
import java.net.URLConnection;
1111
import java.security.Permission;
12+
import javax.annotation.Nullable;
1213

1314
public class InputStreamUrlConnection extends URLConnection {
1415
private final InputStream inputStream;
@@ -30,6 +31,7 @@ public InputStream getInputStream() {
3031
return inputStream;
3132
}
3233

34+
@Nullable
3335
@Override
3436
public Permission getPermission() {
3537
// No permissions needed because all classes are in memory

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

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

88
import static java.util.Arrays.asList;
9+
import static java.util.Collections.emptyMap;
910

1011
import io.opentelemetry.api.GlobalOpenTelemetry;
1112
import io.opentelemetry.instrumentation.config.bridge.ConfigPropertiesBackedConfigProvider;
@@ -16,6 +17,7 @@
1617
import io.opentelemetry.sdk.autoconfigure.SdkAutoconfigureAccess;
1718
import io.opentelemetry.sdk.autoconfigure.internal.AutoConfigureUtil;
1819
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
20+
import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties;
1921
import io.opentelemetry.sdk.common.CompletableResultCode;
2022

2123
public final class OpenTelemetryInstaller {
@@ -36,15 +38,17 @@ public static AutoConfiguredOpenTelemetrySdk installOpenTelemetrySdk(
3638
.build();
3739
OpenTelemetrySdk sdk = autoConfiguredSdk.getOpenTelemetrySdk();
3840
ConfigProperties configProperties = AutoConfigureUtil.getConfig(autoConfiguredSdk);
39-
boolean declarativeConfigUsed = configProperties == null;
4041

41-
if (!declarativeConfigUsed) {
42+
if (configProperties != null) {
4243
// Provide a fake declarative configuration based on config properties
4344
// so that declarative configuration API can be used everywhere
4445
sdk =
4546
new ExtendedOpenTelemetrySdkWrapper(
4647
sdk, ConfigPropertiesBackedConfigProvider.create(configProperties));
4748
AgentDistributionConfig.set(AgentDistributionConfig.fromConfigProperties(configProperties));
49+
} else {
50+
// Declarative config path: no ConfigProperties available, use empty defaults
51+
configProperties = DefaultConfigProperties.createFromMap(emptyMap());
4852
}
4953

5054
setForceFlush(sdk);

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import java.security.Permission;
1616
import java.util.jar.JarEntry;
1717
import java.util.jar.JarFile;
18+
import javax.annotation.Nullable;
1819
import org.objectweb.asm.ClassReader;
1920
import org.objectweb.asm.ClassWriter;
2021
import org.objectweb.asm.commons.ClassRemapper;
@@ -50,7 +51,7 @@ public class RemappingUrlConnection extends URLConnection {
5051
private final JarFile delegateJarFile;
5152
private final JarEntry entry;
5253

53-
private byte[] cacheClassBytes;
54+
@Nullable private byte[] cacheClassBytes;
5455

5556
public RemappingUrlConnection(URL url, JarFile delegateJarFile, JarEntry entry) {
5657
super(url);
@@ -89,6 +90,7 @@ private static byte[] remapClassBytes(InputStream in) throws IOException {
8990
return cw.toByteArray();
9091
}
9192

93+
@Nullable
9294
@Override
9395
public Permission getPermission() {
9496
// No permissions needed because all classes are in memory

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

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@
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;
18+
import javax.annotation.Nullable;
1719

1820
public final class SafeServiceLoader {
1921

@@ -30,13 +32,14 @@ public final class SafeServiceLoader {
3032
*/
3133
// Because we want to catch exception per iteration
3234
@SuppressWarnings("ForEachIterable")
33-
public static <T> List<T> load(Class<T> serviceClass, ClassLoader classLoader) {
35+
public static <T> List<T> load(Class<T> serviceClass, @Nullable ClassLoader classLoader) {
3436
List<T> result = new ArrayList<>();
3537
ServiceLoader<T> services = ServiceLoader.load(serviceClass, classLoader);
3638
for (Iterator<T> iterator = new SafeIterator<>(services.iterator()); iterator.hasNext(); ) {
37-
T service = iterator.next();
38-
if (service != null) {
39-
result.add(service);
39+
try {
40+
result.add(iterator.next());
41+
} catch (NoSuchElementException ignored) {
42+
// UnsupportedClassVersionError was thrown and handled by SafeIterator
4043
}
4144
}
4245
return result;
@@ -47,7 +50,7 @@ public static <T> List<T> load(Class<T> serviceClass, ClassLoader classLoader) {
4750
* comparing their {@link Ordered#order()}.
4851
*/
4952
public static <T extends Ordered> List<T> loadOrdered(
50-
Class<T> serviceClass, ClassLoader classLoader) {
53+
Class<T> serviceClass, @Nullable ClassLoader classLoader) {
5154
List<T> result = load(serviceClass, classLoader);
5255
result.sort(Comparator.comparing(Ordered::order));
5356
return result;
@@ -89,7 +92,7 @@ public T next() {
8992
return delegate.next();
9093
} catch (UnsupportedClassVersionError unsupportedClassVersionError) {
9194
handleUnsupportedClassVersionError(unsupportedClassVersionError);
92-
return null;
95+
throw new NoSuchElementException(unsupportedClassVersionError.getMessage());
9396
}
9497
}
9598
}

0 commit comments

Comments
 (0)