Use javaagent to determine if logger class is initialized in test
MODIFY
dd-java-agent-ittests/src/test/groovy/datadog/trace/agent/CustomLogManagerTest.groovy
dd-java-agent-ittests/src/test/groovy/datadog/trace/agent/CustomLogManagerTest.groovy
@@ -21,11 +21,12 @@ class CustomLogManagerTest extends Specification {
break
}
}
+ final URL customAgent = IntegrationTestUtils.createJarWithClasses(LogManagerSetter.getName(), LogManagerSetter)
expect:
agentArg != null
IntegrationTestUtils.runOnSeparateJvm(LogManagerSetter.getName()
- , [agentArg, "-Ddd.jmxfetch.enabled=true"] as String[]
+ , [agentArg, "-javaagent:" + customAgent.getPath(), "-Ddd.jmxfetch.enabled=true"] as String[]
, "" as String[]
, true) == 0
}

MODIFY
dd-java-agent-ittests/src/test/java/datadog/trace/agent/test/IntegrationTestUtils.java
dd-java-agent-ittests/src/test/java/datadog/trace/agent/test/IntegrationTestUtils.java
@@ -19,6 +19,7 @@ import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.Callable;
+import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
@@ -77,20 +78,32 @@ public class IntegrationTestUtils {
}
}
+ /** See {@link IntegrationTestUtils#createJarWithClasses(String, Class[])} */
+ public static URL createJarWithClasses(final Class<?>... classes) throws IOException {
+ return createJarWithClasses(null, classes);
+ }
/**
* Create a temporary jar on the filesystem with the bytes of the given classes.
*
* <p>The jar file will be removed when the jvm exits.
*
+ * @param mainClassname The name of the class to use for Main-Class and Premain-Class. May be null
* @param classes classes to package into the jar.
* @return the location of the newly created jar.
* @throws IOException
*/
- public static URL createJarWithClasses(final Class<?>... classes) throws IOException {
+ public static URL createJarWithClasses(final String mainClassname, final Class<?>... classes)
+ throws IOException {
final File tmpJar = File.createTempFile(UUID.randomUUID().toString() + "-", ".jar");
tmpJar.deleteOnExit();
final Manifest manifest = new Manifest();
+ if (mainClassname != null) {
+ Attributes mainAttributes = manifest.getMainAttributes();
+ mainAttributes.put(Attributes.Name.MANIFEST_VERSION, "1.0");
+ mainAttributes.put(Attributes.Name.MAIN_CLASS, mainClassname);
+ mainAttributes.put(new Attributes.Name("Premain-Class"), mainClassname);
+ }
final JarOutputStream target = new JarOutputStream(new FileOutputStream(tmpJar), manifest);
for (final Class<?> clazz : classes) {
addToJar(clazz, target);

MODIFY
dd-java-agent-ittests/src/test/java/jvmbootstraptest/LogManagerSetter.java
dd-java-agent-ittests/src/test/java/jvmbootstraptest/LogManagerSetter.java
package jvmbootstraptest;
-import java.lang.reflect.Method;
+import java.lang.instrument.ClassFileTransformer;
+import java.lang.instrument.IllegalClassFormatException;
+import java.lang.instrument.Instrumentation;
+import java.security.ProtectionDomain;
+import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.LogManager;
public class LogManagerSetter {
@@ -8,22 +12,38 @@ public class LogManagerSetter {
// loggerClassName = java.util.logging.Logger
private static final String loggerClassName =
"java.util.logging.TMP".replaceFirst("TMP", "Logger");
+ private static final String loggerInternalName = loggerClassName.replace('.', '/');
+ private static final AtomicBoolean loggerInitialized = new AtomicBoolean(false);
+
+ public static void premain(final String agentArgs, final Instrumentation inst) throws Exception {
+ inst.addTransformer(
+ new ClassFileTransformer() {
+ @Override
+ public byte[] transform(
+ ClassLoader loader,
+ String className,
+ Class<?> classBeingRedefined,
+ ProtectionDomain protectionDomain,
+ byte[] classfileBuffer)
+ throws IllegalClassFormatException {
+ if (loggerInternalName.equals(className)) {
+ loggerInitialized.compareAndSet(false, true);
+ }
+ return null;
+ }
+ });
+ }
public static void main(String... args) throws Exception {
final ClassLoader systemLoader = ClassLoader.getSystemClassLoader();
// once the logger class has been initialized, we know jmxfetch is running and can proceed with
// the test
- final Method method =
- ClassLoader.class.getDeclaredMethod("findBootstrapClassOrNull", String.class);
- try {
- method.setAccessible(true);
- while (method.invoke(systemLoader, loggerClassName) == null) {
+ while (!loggerInitialized.get()) {
Thread.sleep(1);
}
- } finally {
- method.setAccessible(false);
- }
+ systemLoader.loadClass(loggerClassName);
+ // at this point the logger is loaded and fully initialized
System.setProperty("java.util.logging.manager", CustomLogManager.class.getName());
customAssert(

Use javaagent to determine if logger class is initialized in test