diff --git a/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/DatadogClassLoader.java b/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/DatadogClassLoader.java index 55c1b55ca6..5427834156 100644 --- a/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/DatadogClassLoader.java +++ b/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/DatadogClassLoader.java @@ -51,7 +51,7 @@ public class DatadogClassLoader extends URLClassLoader { null, 0, "/", - new InternalJarURLHandler(internalJarFileName, bootstrapProxy)); + new InternalJarURLHandler(internalJarFileName, bootstrapJarLocation)); addURL(internalJarURL); } catch (final MalformedURLException e) { diff --git a/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/InternalJarURLHandler.java b/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/InternalJarURLHandler.java index fb1c46204f..d645b8c722 100644 --- a/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/InternalJarURLHandler.java +++ b/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/InternalJarURLHandler.java @@ -2,58 +2,63 @@ package datadog.trace.bootstrap; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; +import java.io.File; import java.io.IOException; import java.io.InputStream; +import java.net.URISyntaxException; import java.net.URL; import java.net.URLConnection; import java.net.URLStreamHandler; import java.nio.file.NoSuchFileException; import java.security.Permission; +import java.util.Enumeration; import java.util.HashMap; import java.util.Map; import java.util.jar.JarEntry; -import java.util.jar.JarInputStream; +import java.util.jar.JarFile; import lombok.extern.slf4j.Slf4j; @Slf4j public class InternalJarURLHandler extends URLStreamHandler { - private final Map filenameToBytes = new HashMap<>(); + private final Map filenameToEntry = new HashMap<>(); + private JarFile bootstrapJarFile; - InternalJarURLHandler( - final String internalJarFileName, final ClassLoader classloaderForJarResource) { + InternalJarURLHandler(final String internalJarFileName, final URL bootstrapJarLocation) { + try { + if (bootstrapJarLocation != null) { + bootstrapJarFile = new JarFile(new File(bootstrapJarLocation.toURI())); + final Enumeration entries = bootstrapJarFile.entries(); + while (entries.hasMoreElements()) { + final JarEntry entry = entries.nextElement(); - // "/" is used as the default url of the jar - // This is called by the SecureClassLoader trying to obtain permissions - filenameToBytes.put("/", new byte[] {}); - - final InputStream jarStream = - internalJarFileName == null - ? null - : classloaderForJarResource.getResourceAsStream(internalJarFileName); - - if (jarStream != null) { - try (final JarInputStream inputStream = new JarInputStream(jarStream)) { - JarEntry entry = inputStream.getNextJarEntry(); - - while (entry != null) { - filenameToBytes.put("/" + entry.getName(), getBytes(inputStream)); - - entry = inputStream.getNextJarEntry(); + if (!entry.isDirectory() && entry.getName().startsWith(internalJarFileName + "/")) { + filenameToEntry.put(entry.getName().substring(internalJarFileName.length()), entry); + } } - - } catch (final IOException e) { - log.error("Unable to read internal jar", e); } - } else { - log.error("Internal jar not found"); + } catch (final URISyntaxException | IOException e) { + log.error("Unable to read internal jar", e); + } + + if (filenameToEntry.isEmpty()) { + log.warn("Internal jar entries found"); } } @Override protected URLConnection openConnection(final URL url) throws IOException { - final byte[] bytes = filenameToBytes.get(url.getFile()); - if (bytes == null) { + final byte[] bytes; + + final String filename = url.getFile().replaceAll("\\.class$", ".classdata"); + if ("/".equals(filename)) { + // "/" is used as the default url of the jar + // This is called by the SecureClassLoader trying to obtain permissions + bytes = new byte[0]; + } else if (filenameToEntry.containsKey(filename)) { + final JarEntry entry = filenameToEntry.get(filename); + bytes = getBytes(bootstrapJarFile.getInputStream(entry)); + } else { throw new NoSuchFileException(url.getFile(), null, url.getFile() + " not in internal jar"); } diff --git a/dd-java-agent/dd-java-agent.gradle b/dd-java-agent/dd-java-agent.gradle index a3a4381129..ed33f225b9 100644 --- a/dd-java-agent/dd-java-agent.gradle +++ b/dd-java-agent/dd-java-agent.gradle @@ -26,13 +26,12 @@ def includeShadowJar(subproject, jarname) { def agent_project = project subproject.afterEvaluate { agent_project.processResources { - from(subproject.tasks.shadowJar) - rename { - it.equals(subproject.shadowJar.archivePath.getName()) ? - jarname : - it + from(zipTree(subproject.tasks.shadowJar.archivePath)) { + into jarname + rename '(^.*)\\.class$', '$1.classdata' } } + agent_project.processResources.dependsOn subproject.tasks.shadowJar subproject.shadowJar { classifier null @@ -59,8 +58,8 @@ def includeShadowJar(subproject, jarname) { } } -includeShadowJar(project(':dd-java-agent:instrumentation'), 'agent-tooling-and-instrumentation.jar.zip') -includeShadowJar(project(':dd-java-agent:agent-jmxfetch'), 'agent-jmxfetch.jar.zip') +includeShadowJar(project(':dd-java-agent:instrumentation'), 'agent-tooling-and-instrumentation.isolated') +includeShadowJar(project(':dd-java-agent:agent-jmxfetch'), 'agent-jmxfetch.isolated') jar { classifier = 'unbundled' diff --git a/dd-java-agent/src/main/java/datadog/trace/agent/TracingAgent.java b/dd-java-agent/src/main/java/datadog/trace/agent/TracingAgent.java index aa8aadefe8..280e53fa9e 100644 --- a/dd-java-agent/src/main/java/datadog/trace/agent/TracingAgent.java +++ b/dd-java-agent/src/main/java/datadog/trace/agent/TracingAgent.java @@ -94,7 +94,7 @@ public class TracingAgent { if (AGENT_CLASSLOADER == null) { final ClassLoader agentClassLoader = - createDatadogClassLoader("agent-tooling-and-instrumentation.jar.zip", bootstrapURL); + createDatadogClassLoader("agent-tooling-and-instrumentation.isolated", bootstrapURL); final ClassLoader contextLoader = Thread.currentThread().getContextClassLoader(); try { Thread.currentThread().setContextClassLoader(agentClassLoader); @@ -126,7 +126,7 @@ public class TracingAgent { throws Exception { if (JMXFETCH_CLASSLOADER == null) { final ClassLoader jmxFetchClassLoader = - createDatadogClassLoader("agent-jmxfetch.jar.zip", bootstrapURL); + createDatadogClassLoader("agent-jmxfetch.isolated", bootstrapURL); final ClassLoader contextLoader = Thread.currentThread().getContextClassLoader(); try { Thread.currentThread().setContextClassLoader(jmxFetchClassLoader);