From 09cb446b23b75bb25eeb25c004b50e0c2b7e567d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Serkan=20=C3=96ZAL?= Date: Fri, 9 Aug 2024 23:54:25 +0300 Subject: [PATCH 1/5] Initialize `java.net.InetAddress` after VM and agent are initialized --- .../javaagent/bootstrap/AgentInitializer.java | 8 + .../javaagent/tooling/AgentStarterImpl.java | 139 ++++++++++++++++++ 2 files changed, 147 insertions(+) diff --git a/javaagent-bootstrap/src/main/java/io/opentelemetry/javaagent/bootstrap/AgentInitializer.java b/javaagent-bootstrap/src/main/java/io/opentelemetry/javaagent/bootstrap/AgentInitializer.java index 5410c883c722..1c5184eeb579 100644 --- a/javaagent-bootstrap/src/main/java/io/opentelemetry/javaagent/bootstrap/AgentInitializer.java +++ b/javaagent-bootstrap/src/main/java/io/opentelemetry/javaagent/bootstrap/AgentInitializer.java @@ -26,6 +26,7 @@ public final class AgentInitializer { @Nullable private static ClassLoader agentClassLoader = null; @Nullable private static AgentStarter agentStarter = null; private static boolean isSecurityManagerSupportEnabled = false; + private static boolean agentStarted = false; public static void initialize(Instrumentation inst, File javaagentFile, boolean fromPremain) throws Exception { @@ -51,6 +52,7 @@ public Void run() throws Exception { agentStarter = createAgentStarter(agentClassLoader, inst, javaagentFile); if (!fromPremain || !delayAgentStart()) { agentStarter.start(); + agentStarted = true; } return null; } @@ -149,11 +151,17 @@ public static void delayedStartHook() throws Exception { @Override public Void run() { agentStarter.start(); + agentStarted = true; return null; } }); } + @SuppressWarnings("unused") + public static boolean isAgentStarted() { + return agentStarted; + } + public static ClassLoader getExtensionsClassLoader() { // agentStarter can be null when running tests return agentStarter != null ? agentStarter.getExtensionClassLoader() : null; diff --git a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/AgentStarterImpl.java b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/AgentStarterImpl.java index 7f12889be6b7..69730a66ae8e 100644 --- a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/AgentStarterImpl.java +++ b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/AgentStarterImpl.java @@ -20,6 +20,7 @@ import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.Label; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; @@ -68,6 +69,8 @@ public boolean delayStart() { @Override public void start() { + init(); + EarlyInitAgentConfig earlyConfig = EarlyInitAgentConfig.create(); extensionClassLoader = createExtensionClassLoader(getClass().getClassLoader(), earlyConfig); @@ -115,6 +118,29 @@ public void start() { } } + private void init() { + instrumentInetAddress(); + } + + private void instrumentInetAddress() { + InetAddressClassFileTransformer transformer = new InetAddressClassFileTransformer(); + instrumentation.addTransformer(transformer, true); + + try { + Class clazz = Class.forName("java.net.InetAddress", false, null); + if (transformer.transformed) { + // InetAddress was loaded and got transformed + return; + } + // InetAddress was already loaded before we set up transformer + instrumentation.retransformClasses(clazz); + } catch (ClassNotFoundException | UnmodifiableClassException ignore) { + // ignore + } finally { + instrumentation.removeTransformer(transformer); + } + } + @SuppressWarnings("SystemOut") private static void logUnrecognizedLoggerImplWarning(String loggerImplementationName) { System.err.println( @@ -180,4 +206,117 @@ public void visitCode() { return hookInserted ? cw.toByteArray() : null; } } + + private static class InetAddressClassFileTransformer implements ClassFileTransformer { + boolean hookInserted = false; + boolean transformed = false; + boolean wrapperMethodCreated = false; + + private static void createWrapperMethod(ClassWriter cw) { + /* + private static boolean isAgentAndVmBooted(); + Code: + 0: invokestatic #X // Method io/opentelemetry/javaagent/bootstrap/AgentInitializer/isAgentStarted:()Z + 3: ifeq 16 + 6: invokestatic #Y // Method jdk/internal/misc/VM.isBooted:()Z + 9: ifeq 16 + 12: iconst_1 + 13: goto 17 + 16: iconst_0 + 17: ireturn + */ + + String descriptor = Type.getMethodDescriptor(Type.BOOLEAN_TYPE); + Label elseLabel = new Label(); + Label endLabel = new Label(); + + MethodVisitor mv = + cw.visitMethod( + Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC, + "isAgentAndVmBooted", + descriptor, + null, + null); + mv.visitCode(); + + mv.visitMethodInsn( + Opcodes.INVOKESTATIC, + Type.getInternalName(AgentInitializer.class), + "isAgentStarted", + descriptor, + false); + mv.visitJumpInsn(Opcodes.IFEQ, elseLabel); + mv.visitMethodInsn( + Opcodes.INVOKESTATIC, "jdk/internal/misc/VM", "isBooted", descriptor, false); + mv.visitJumpInsn(Opcodes.IFEQ, elseLabel); + mv.visitInsn(Opcodes.ICONST_1); + mv.visitJumpInsn(Opcodes.GOTO, endLabel); + mv.visitLabel(elseLabel); + mv.visitInsn(Opcodes.ICONST_0); + mv.visitLabel(endLabel); + mv.visitInsn(Opcodes.IRETURN); + + mv.visitMaxs(0, 0); + mv.visitEnd(); + } + + @Override + public byte[] transform( + ClassLoader loader, + String className, + Class classBeingRedefined, + ProtectionDomain protectionDomain, + byte[] classfileBuffer) { + if (!"java/net/InetAddress".equals(className)) { + return null; + } + transformed = true; + ClassReader cr = new ClassReader(classfileBuffer); + ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES); + ClassVisitor cv = + new ClassVisitor(AsmApi.VERSION, cw) { + @Override + public MethodVisitor visitMethod( + int access, String name, String descriptor, String signature, String[] exceptions) { + MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions); + // We don't want to patch "jdk.internal.misc.VM.isBooted" call in our wrapper + if ("isAgentAndVmBooted".equals(name)) { + return mv; + } + return new MethodVisitor(api, mv) { + @Override + public void visitMethodInsn( + int opcode, + String ownerClassName, + String methodName, + String descriptor, + boolean isInterface) { + if ("jdk/internal/misc/VM".equals(ownerClassName) + && "isBooted".equals(methodName)) { + // Create wrapper method only once + if (!wrapperMethodCreated) { + createWrapperMethod(cw); + wrapperMethodCreated = true; + } + super.visitMethodInsn( + Opcodes.INVOKESTATIC, + "java/net/InetAddress", + "isAgentAndVmBooted", + "()Z", + isInterface); + hookInserted = true; + } else { + super.visitMethodInsn( + opcode, ownerClassName, methodName, descriptor, isInterface); + } + } + }; + } + }; + + cr.accept(cv, 0); + + return hookInserted ? cw.toByteArray() : null; + } + } } From ee09b8774cf552ca91b11117c8227401b7435860 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Serkan=20=C3=96ZAL?= Date: Mon, 12 Aug 2024 14:24:24 +0300 Subject: [PATCH 2/5] Fix review comments --- .../javaagent/bootstrap/AgentInitializer.java | 16 +++- .../javaagent/tooling/AgentStarterImpl.java | 89 ++----------------- 2 files changed, 21 insertions(+), 84 deletions(-) diff --git a/javaagent-bootstrap/src/main/java/io/opentelemetry/javaagent/bootstrap/AgentInitializer.java b/javaagent-bootstrap/src/main/java/io/opentelemetry/javaagent/bootstrap/AgentInitializer.java index 1c5184eeb579..adb7668fa79b 100644 --- a/javaagent-bootstrap/src/main/java/io/opentelemetry/javaagent/bootstrap/AgentInitializer.java +++ b/javaagent-bootstrap/src/main/java/io/opentelemetry/javaagent/bootstrap/AgentInitializer.java @@ -26,7 +26,7 @@ public final class AgentInitializer { @Nullable private static ClassLoader agentClassLoader = null; @Nullable private static AgentStarter agentStarter = null; private static boolean isSecurityManagerSupportEnabled = false; - private static boolean agentStarted = false; + private static volatile boolean agentStarted = false; public static void initialize(Instrumentation inst, File javaagentFile, boolean fromPremain) throws Exception { @@ -157,9 +157,19 @@ public Void run() { }); } + /** + * Check whether agent has started or not along with VM. + * + *

This method is used by + * io.opentelemetry.javaagent.tooling.AgentStarterImpl#InetAddressClassFileTransformer internally + * to check whether agent has started. + * + * @param vmStarted flag about whether VM has started or not. + * @return {@code true} if agent has started or not along with VM, {@code false} otherwise. + */ @SuppressWarnings("unused") - public static boolean isAgentStarted() { - return agentStarted; + public static boolean isAgentStarted(boolean vmStarted) { + return vmStarted && agentStarted; } public static ClassLoader getExtensionsClassLoader() { diff --git a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/AgentStarterImpl.java b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/AgentStarterImpl.java index 69730a66ae8e..eb5a6a697574 100644 --- a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/AgentStarterImpl.java +++ b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/AgentStarterImpl.java @@ -20,7 +20,6 @@ import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.ClassWriter; -import org.objectweb.asm.Label; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; @@ -125,20 +124,6 @@ private void init() { private void instrumentInetAddress() { InetAddressClassFileTransformer transformer = new InetAddressClassFileTransformer(); instrumentation.addTransformer(transformer, true); - - try { - Class clazz = Class.forName("java.net.InetAddress", false, null); - if (transformer.transformed) { - // InetAddress was loaded and got transformed - return; - } - // InetAddress was already loaded before we set up transformer - instrumentation.retransformClasses(clazz); - } catch (ClassNotFoundException | UnmodifiableClassException ignore) { - // ignore - } finally { - instrumentation.removeTransformer(transformer); - } } @SuppressWarnings("SystemOut") @@ -209,56 +194,6 @@ public void visitCode() { private static class InetAddressClassFileTransformer implements ClassFileTransformer { boolean hookInserted = false; - boolean transformed = false; - boolean wrapperMethodCreated = false; - - private static void createWrapperMethod(ClassWriter cw) { - /* - private static boolean isAgentAndVmBooted(); - Code: - 0: invokestatic #X // Method io/opentelemetry/javaagent/bootstrap/AgentInitializer/isAgentStarted:()Z - 3: ifeq 16 - 6: invokestatic #Y // Method jdk/internal/misc/VM.isBooted:()Z - 9: ifeq 16 - 12: iconst_1 - 13: goto 17 - 16: iconst_0 - 17: ireturn - */ - - String descriptor = Type.getMethodDescriptor(Type.BOOLEAN_TYPE); - Label elseLabel = new Label(); - Label endLabel = new Label(); - - MethodVisitor mv = - cw.visitMethod( - Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC, - "isAgentAndVmBooted", - descriptor, - null, - null); - mv.visitCode(); - - mv.visitMethodInsn( - Opcodes.INVOKESTATIC, - Type.getInternalName(AgentInitializer.class), - "isAgentStarted", - descriptor, - false); - mv.visitJumpInsn(Opcodes.IFEQ, elseLabel); - mv.visitMethodInsn( - Opcodes.INVOKESTATIC, "jdk/internal/misc/VM", "isBooted", descriptor, false); - mv.visitJumpInsn(Opcodes.IFEQ, elseLabel); - mv.visitInsn(Opcodes.ICONST_1); - mv.visitJumpInsn(Opcodes.GOTO, endLabel); - mv.visitLabel(elseLabel); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitLabel(endLabel); - mv.visitInsn(Opcodes.IRETURN); - - mv.visitMaxs(0, 0); - mv.visitEnd(); - } @Override public byte[] transform( @@ -270,17 +205,15 @@ public byte[] transform( if (!"java/net/InetAddress".equals(className)) { return null; } - transformed = true; ClassReader cr = new ClassReader(classfileBuffer); - ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES); + ClassWriter cw = new ClassWriter(cr, 0); ClassVisitor cv = new ClassVisitor(AsmApi.VERSION, cw) { @Override public MethodVisitor visitMethod( int access, String name, String descriptor, String signature, String[] exceptions) { MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions); - // We don't want to patch "jdk.internal.misc.VM.isBooted" call in our wrapper - if ("isAgentAndVmBooted".equals(name)) { + if (!"resolver".equals(name)) { return mv; } return new MethodVisitor(api, mv) { @@ -291,23 +224,17 @@ public void visitMethodInsn( String methodName, String descriptor, boolean isInterface) { + super.visitMethodInsn( + opcode, ownerClassName, methodName, descriptor, isInterface); if ("jdk/internal/misc/VM".equals(ownerClassName) && "isBooted".equals(methodName)) { - // Create wrapper method only once - if (!wrapperMethodCreated) { - createWrapperMethod(cw); - wrapperMethodCreated = true; - } super.visitMethodInsn( Opcodes.INVOKESTATIC, - "java/net/InetAddress", - "isAgentAndVmBooted", - "()Z", - isInterface); + Type.getInternalName(AgentInitializer.class), + "isAgentStarted", + "(Z)Z", + false); hookInserted = true; - } else { - super.visitMethodInsn( - opcode, ownerClassName, methodName, descriptor, isInterface); } } }; From 8b93008b27164f9c64b15abbb9f70a918179119b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Serkan=20=C3=96ZAL?= Date: Tue, 13 Aug 2024 18:21:14 +0300 Subject: [PATCH 3/5] Add test --- .../testing-java18/build.gradle.kts | 13 +++++++ .../inetaddress/InetAddressResolverTest.java | 26 +++++++++++++ .../inetaddress/TestAddressResolver.java | 39 +++++++++++++++++++ .../TestAddressResolverProvider.java | 22 +++++++++++ .../java.net.spi.InetAddressResolverProvider | 1 + settings.gradle.kts | 1 + 6 files changed, 102 insertions(+) create mode 100644 javaagent-tooling/testing-java18/build.gradle.kts create mode 100644 javaagent-tooling/testing-java18/src/test/java/io/opentelemetry/javaagent/tooling/inetaddress/InetAddressResolverTest.java create mode 100644 javaagent-tooling/testing-java18/src/test/java/io/opentelemetry/javaagent/tooling/inetaddress/TestAddressResolver.java create mode 100644 javaagent-tooling/testing-java18/src/test/java/io/opentelemetry/javaagent/tooling/inetaddress/TestAddressResolverProvider.java create mode 100644 javaagent-tooling/testing-java18/src/test/resources/META-INF/services/java.net.spi.InetAddressResolverProvider diff --git a/javaagent-tooling/testing-java18/build.gradle.kts b/javaagent-tooling/testing-java18/build.gradle.kts new file mode 100644 index 000000000000..328ab3aae5ce --- /dev/null +++ b/javaagent-tooling/testing-java18/build.gradle.kts @@ -0,0 +1,13 @@ +plugins { + id("otel.javaagent-instrumentation") +} + +dependencies { + // To be able to have it as part of agent, + // this dependency needs to be added as "testInstrumentation", not as "testImplementation" + testInstrumentation(project(":instrumentation:resources:library")) +} + +otelJava { + minJavaVersionSupported.set(JavaVersion.VERSION_18) +} diff --git a/javaagent-tooling/testing-java18/src/test/java/io/opentelemetry/javaagent/tooling/inetaddress/InetAddressResolverTest.java b/javaagent-tooling/testing-java18/src/test/java/io/opentelemetry/javaagent/tooling/inetaddress/InetAddressResolverTest.java new file mode 100644 index 000000000000..f5ca2847ed29 --- /dev/null +++ b/javaagent-tooling/testing-java18/src/test/java/io/opentelemetry/javaagent/tooling/inetaddress/InetAddressResolverTest.java @@ -0,0 +1,26 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.tooling.inetaddress; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.net.InetAddress; +import org.junit.jupiter.api.Test; + +public class InetAddressResolverTest { + + @Test + void agentStartShouldNotTriggerLoadingCustomInetAddressResolvers() throws Exception { + // Agent start should not trigger loading (and instantiating) custom InetAddress resolvers + assertThat(TestAddressResolver.isInstantiated()).isFalse(); + + // Trigger loading (and instantiating) custom InetAddress resolvers manually + InetAddress.getAllByName("test"); + + // Verify that custom InetAddress resolver loaded and instantiated + assertThat(TestAddressResolver.isInstantiated()).isTrue(); + } +} diff --git a/javaagent-tooling/testing-java18/src/test/java/io/opentelemetry/javaagent/tooling/inetaddress/TestAddressResolver.java b/javaagent-tooling/testing-java18/src/test/java/io/opentelemetry/javaagent/tooling/inetaddress/TestAddressResolver.java new file mode 100644 index 000000000000..9c0df5aad70b --- /dev/null +++ b/javaagent-tooling/testing-java18/src/test/java/io/opentelemetry/javaagent/tooling/inetaddress/TestAddressResolver.java @@ -0,0 +1,39 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.tooling.inetaddress; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.net.spi.InetAddressResolver; +import java.util.stream.Stream; + +public class TestAddressResolver implements InetAddressResolver { + + private static volatile boolean instantiated = false; + + @SuppressWarnings("StaticAssignmentInConstructor") + public TestAddressResolver() { + TestAddressResolver.instantiated = true; + } + + public static boolean isInstantiated() { + return instantiated; + } + + @Override + public Stream lookupByName(String host, LookupPolicy lookupPolicy) + throws UnknownHostException { + if (host.equals("test")) { + return Stream.of(InetAddress.getByAddress(new byte[] {127, 0, 0, 1})); + } + throw new UnknownHostException(); + } + + @Override + public String lookupByAddress(byte[] addr) { + throw new UnsupportedOperationException(); + } +} diff --git a/javaagent-tooling/testing-java18/src/test/java/io/opentelemetry/javaagent/tooling/inetaddress/TestAddressResolverProvider.java b/javaagent-tooling/testing-java18/src/test/java/io/opentelemetry/javaagent/tooling/inetaddress/TestAddressResolverProvider.java new file mode 100644 index 000000000000..f1af2597e5c0 --- /dev/null +++ b/javaagent-tooling/testing-java18/src/test/java/io/opentelemetry/javaagent/tooling/inetaddress/TestAddressResolverProvider.java @@ -0,0 +1,22 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.tooling.inetaddress; + +import java.net.spi.InetAddressResolver; +import java.net.spi.InetAddressResolverProvider; + +public class TestAddressResolverProvider extends InetAddressResolverProvider { + + @Override + public InetAddressResolver get(Configuration configuration) { + return new TestAddressResolver(); + } + + @Override + public String name() { + return "Test Internet Address Resolver Provider"; + } +} diff --git a/javaagent-tooling/testing-java18/src/test/resources/META-INF/services/java.net.spi.InetAddressResolverProvider b/javaagent-tooling/testing-java18/src/test/resources/META-INF/services/java.net.spi.InetAddressResolverProvider new file mode 100644 index 000000000000..c4d2e7912b78 --- /dev/null +++ b/javaagent-tooling/testing-java18/src/test/resources/META-INF/services/java.net.spi.InetAddressResolverProvider @@ -0,0 +1 @@ +io.opentelemetry.javaagent.tooling.inetaddress.TestAddressResolverProvider diff --git a/settings.gradle.kts b/settings.gradle.kts index 2c2cf4072c94..6ab62f9c9f55 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -121,6 +121,7 @@ include(":javaagent-bootstrap") include(":javaagent-extension-api") include(":javaagent-tooling") include(":javaagent-tooling:javaagent-tooling-java9") +include(":javaagent-tooling:testing-java18") include(":javaagent-internal-logging-application") include(":javaagent-internal-logging-simple") include(":javaagent") From 2927bf67b49377798003f772994f901425a552b7 Mon Sep 17 00:00:00 2001 From: Lauri Tulmin Date: Fri, 16 Aug 2024 09:37:31 +0300 Subject: [PATCH 4/5] rename testing module and a few other changes --- .../jdk18-testing/build.gradle.kts | 11 +++++++ .../java/testing/TestResourceProvider.java | 30 +++++++++++++++++++ .../inetaddress/InetAddressResolverTest.java | 2 ++ .../inetaddress/TestAddressResolver.java | 1 + .../TestAddressResolverProvider.java | 0 .../java.net.spi.InetAddressResolverProvider | 0 .../javaagent/tooling/AgentStarterImpl.java | 12 ++++---- .../testing-java18/build.gradle.kts | 13 -------- settings.gradle.kts | 2 +- 9 files changed, 51 insertions(+), 20 deletions(-) create mode 100644 javaagent-tooling/jdk18-testing/build.gradle.kts create mode 100644 javaagent-tooling/jdk18-testing/src/main/java/testing/TestResourceProvider.java rename javaagent-tooling/{testing-java18 => jdk18-testing}/src/test/java/io/opentelemetry/javaagent/tooling/inetaddress/InetAddressResolverTest.java (84%) rename javaagent-tooling/{testing-java18 => jdk18-testing}/src/test/java/io/opentelemetry/javaagent/tooling/inetaddress/TestAddressResolver.java (96%) rename javaagent-tooling/{testing-java18 => jdk18-testing}/src/test/java/io/opentelemetry/javaagent/tooling/inetaddress/TestAddressResolverProvider.java (100%) rename javaagent-tooling/{testing-java18 => jdk18-testing}/src/test/resources/META-INF/services/java.net.spi.InetAddressResolverProvider (100%) delete mode 100644 javaagent-tooling/testing-java18/build.gradle.kts diff --git a/javaagent-tooling/jdk18-testing/build.gradle.kts b/javaagent-tooling/jdk18-testing/build.gradle.kts new file mode 100644 index 000000000000..ab1bf712d97f --- /dev/null +++ b/javaagent-tooling/jdk18-testing/build.gradle.kts @@ -0,0 +1,11 @@ +plugins { + id("otel.javaagent-testing") +} + +dependencies { + compileOnly("io.opentelemetry:opentelemetry-sdk-common") +} + +otelJava { + minJavaVersionSupported.set(JavaVersion.VERSION_18) +} diff --git a/javaagent-tooling/jdk18-testing/src/main/java/testing/TestResourceProvider.java b/javaagent-tooling/jdk18-testing/src/main/java/testing/TestResourceProvider.java new file mode 100644 index 000000000000..9db4d5df5006 --- /dev/null +++ b/javaagent-tooling/jdk18-testing/src/main/java/testing/TestResourceProvider.java @@ -0,0 +1,30 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package testing; + +import com.google.auto.service.AutoService; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; +import io.opentelemetry.sdk.autoconfigure.spi.ResourceProvider; +import io.opentelemetry.sdk.resources.Resource; +import java.net.InetAddress; +import java.net.UnknownHostException; + +@AutoService(ResourceProvider.class) +public class TestResourceProvider implements ResourceProvider { + + @Override + public Resource createResource(ConfigProperties config) { + // used in test to determine whether this method was called + System.setProperty("test.resource.provider.called", "true"); + // this call trigger loading InetAddressResolverProvider SPI on jdk 18 + try { + InetAddress.getLocalHost(); + } catch (UnknownHostException e) { + throw new IllegalStateException(e); + } + return Resource.empty(); + } +} diff --git a/javaagent-tooling/testing-java18/src/test/java/io/opentelemetry/javaagent/tooling/inetaddress/InetAddressResolverTest.java b/javaagent-tooling/jdk18-testing/src/test/java/io/opentelemetry/javaagent/tooling/inetaddress/InetAddressResolverTest.java similarity index 84% rename from javaagent-tooling/testing-java18/src/test/java/io/opentelemetry/javaagent/tooling/inetaddress/InetAddressResolverTest.java rename to javaagent-tooling/jdk18-testing/src/test/java/io/opentelemetry/javaagent/tooling/inetaddress/InetAddressResolverTest.java index f5ca2847ed29..f21e494b5f0a 100644 --- a/javaagent-tooling/testing-java18/src/test/java/io/opentelemetry/javaagent/tooling/inetaddress/InetAddressResolverTest.java +++ b/javaagent-tooling/jdk18-testing/src/test/java/io/opentelemetry/javaagent/tooling/inetaddress/InetAddressResolverTest.java @@ -14,6 +14,8 @@ public class InetAddressResolverTest { @Test void agentStartShouldNotTriggerLoadingCustomInetAddressResolvers() throws Exception { + // This system property is set in TestResourceProvider + assertThat(System.getProperty("test.resource.provider.called")).isEqualTo("true"); // Agent start should not trigger loading (and instantiating) custom InetAddress resolvers assertThat(TestAddressResolver.isInstantiated()).isFalse(); diff --git a/javaagent-tooling/testing-java18/src/test/java/io/opentelemetry/javaagent/tooling/inetaddress/TestAddressResolver.java b/javaagent-tooling/jdk18-testing/src/test/java/io/opentelemetry/javaagent/tooling/inetaddress/TestAddressResolver.java similarity index 96% rename from javaagent-tooling/testing-java18/src/test/java/io/opentelemetry/javaagent/tooling/inetaddress/TestAddressResolver.java rename to javaagent-tooling/jdk18-testing/src/test/java/io/opentelemetry/javaagent/tooling/inetaddress/TestAddressResolver.java index 9c0df5aad70b..e4a6aec0b77a 100644 --- a/javaagent-tooling/testing-java18/src/test/java/io/opentelemetry/javaagent/tooling/inetaddress/TestAddressResolver.java +++ b/javaagent-tooling/jdk18-testing/src/test/java/io/opentelemetry/javaagent/tooling/inetaddress/TestAddressResolver.java @@ -16,6 +16,7 @@ public class TestAddressResolver implements InetAddressResolver { @SuppressWarnings("StaticAssignmentInConstructor") public TestAddressResolver() { + new Exception().printStackTrace(); TestAddressResolver.instantiated = true; } diff --git a/javaagent-tooling/testing-java18/src/test/java/io/opentelemetry/javaagent/tooling/inetaddress/TestAddressResolverProvider.java b/javaagent-tooling/jdk18-testing/src/test/java/io/opentelemetry/javaagent/tooling/inetaddress/TestAddressResolverProvider.java similarity index 100% rename from javaagent-tooling/testing-java18/src/test/java/io/opentelemetry/javaagent/tooling/inetaddress/TestAddressResolverProvider.java rename to javaagent-tooling/jdk18-testing/src/test/java/io/opentelemetry/javaagent/tooling/inetaddress/TestAddressResolverProvider.java diff --git a/javaagent-tooling/testing-java18/src/test/resources/META-INF/services/java.net.spi.InetAddressResolverProvider b/javaagent-tooling/jdk18-testing/src/test/resources/META-INF/services/java.net.spi.InetAddressResolverProvider similarity index 100% rename from javaagent-tooling/testing-java18/src/test/resources/META-INF/services/java.net.spi.InetAddressResolverProvider rename to javaagent-tooling/jdk18-testing/src/test/resources/META-INF/services/java.net.spi.InetAddressResolverProvider diff --git a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/AgentStarterImpl.java b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/AgentStarterImpl.java index eb5a6a697574..ab5cb93c22ed 100644 --- a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/AgentStarterImpl.java +++ b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/AgentStarterImpl.java @@ -68,7 +68,7 @@ public boolean delayStart() { @Override public void start() { - init(); + installTransformers(); EarlyInitAgentConfig earlyConfig = EarlyInitAgentConfig.create(); extensionClassLoader = createExtensionClassLoader(getClass().getClassLoader(), earlyConfig); @@ -117,11 +117,10 @@ public void start() { } } - private void init() { - instrumentInetAddress(); - } - - private void instrumentInetAddress() { + private void installTransformers() { + // prevents loading InetAddressResolverProvider SPI before agent has started + // https://github.com/open-telemetry/opentelemetry-java-instrumentation/issues/7130 + // https://github.com/open-telemetry/opentelemetry-java-instrumentation/issues/10921 InetAddressClassFileTransformer transformer = new InetAddressClassFileTransformer(); instrumentation.addTransformer(transformer, true); } @@ -226,6 +225,7 @@ public void visitMethodInsn( boolean isInterface) { super.visitMethodInsn( opcode, ownerClassName, methodName, descriptor, isInterface); + // rewrite Vm.isBooted() to AgentInitializer.isAgentStarted(Vm.isBooted()) if ("jdk/internal/misc/VM".equals(ownerClassName) && "isBooted".equals(methodName)) { super.visitMethodInsn( diff --git a/javaagent-tooling/testing-java18/build.gradle.kts b/javaagent-tooling/testing-java18/build.gradle.kts deleted file mode 100644 index 328ab3aae5ce..000000000000 --- a/javaagent-tooling/testing-java18/build.gradle.kts +++ /dev/null @@ -1,13 +0,0 @@ -plugins { - id("otel.javaagent-instrumentation") -} - -dependencies { - // To be able to have it as part of agent, - // this dependency needs to be added as "testInstrumentation", not as "testImplementation" - testInstrumentation(project(":instrumentation:resources:library")) -} - -otelJava { - minJavaVersionSupported.set(JavaVersion.VERSION_18) -} diff --git a/settings.gradle.kts b/settings.gradle.kts index 9eb0b1d825ca..0c09461583a5 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -121,7 +121,7 @@ include(":javaagent-bootstrap") include(":javaagent-extension-api") include(":javaagent-tooling") include(":javaagent-tooling:javaagent-tooling-java9") -include(":javaagent-tooling:testing-java18") +include(":javaagent-tooling:jdk18-testing") include(":javaagent-internal-logging-application") include(":javaagent-internal-logging-simple") include(":javaagent") From 31de46a9b0b7c9862b3c1a434c651946c4c22fab Mon Sep 17 00:00:00 2001 From: Lauri Tulmin Date: Fri, 16 Aug 2024 10:09:22 +0300 Subject: [PATCH 5/5] remove acceidentally added line --- .../javaagent/tooling/inetaddress/TestAddressResolver.java | 1 - 1 file changed, 1 deletion(-) diff --git a/javaagent-tooling/jdk18-testing/src/test/java/io/opentelemetry/javaagent/tooling/inetaddress/TestAddressResolver.java b/javaagent-tooling/jdk18-testing/src/test/java/io/opentelemetry/javaagent/tooling/inetaddress/TestAddressResolver.java index e4a6aec0b77a..9c0df5aad70b 100644 --- a/javaagent-tooling/jdk18-testing/src/test/java/io/opentelemetry/javaagent/tooling/inetaddress/TestAddressResolver.java +++ b/javaagent-tooling/jdk18-testing/src/test/java/io/opentelemetry/javaagent/tooling/inetaddress/TestAddressResolver.java @@ -16,7 +16,6 @@ public class TestAddressResolver implements InetAddressResolver { @SuppressWarnings("StaticAssignmentInConstructor") public TestAddressResolver() { - new Exception().printStackTrace(); TestAddressResolver.instantiated = true; }