Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 25 additions & 1 deletion .gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,15 @@ build:
- if [ $CI_PIPELINE_SOURCE == "schedule" ] ; then ./gradlew resolveAndLockAll --write-locks $GRADLE_ARGS; fi
- ./gradlew --version
- ./gradlew clean :dd-java-agent:shadowJar :dd-java-agent:check :dd-trace-api:jar :dd-trace-ot:shadowJar -PskipTests -x spotlessCheck $GRADLE_ARGS
- echo UPSTREAM_TRACER_VERSION=$(java -jar workspace/dd-java-agent/build/libs/*.jar) >> upstream.env
- |
set -- workspace/dd-java-agent/build/libs/*.jar
if [ "$#" -ne 1 ] || [ ! -f "$1" ]; then
echo "Expected exactly one publishable dd-java-agent jar, found:"
printf ' %s\n' "$@"
exit 1
fi
upstream_tracer_version=$(java -jar "$1")
echo "UPSTREAM_TRACER_VERSION=$upstream_tracer_version" >> upstream.env
- echo "BUILD_JOB_NAME=$CI_JOB_NAME" >> build.env
- echo "BUILD_JOB_ID=$CI_JOB_ID" >> build.env
artifacts:
Expand All @@ -365,6 +373,22 @@ build:
reports:
dotenv: build.env

verify-common-classdata-plan:
extends: .gradle_build
stage: tests
needs: [ build ]
variables:
CACHE_TYPE: "lib"
rules:
- if: '$POPULATE_CACHE'
when: never
- if: '$CI_COMMIT_BRANCH && $CI_COMMIT_BRANCH !~ /^(master|release\/)/'
when: on_success
- when: never
script:
- ./gradlew --version
- ./gradlew :dd-java-agent:verifyCommonClassDataPlan -PskipTests $GRADLE_ARGS

build_tests:
extends: .gradle_build
variables:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -760,6 +760,14 @@ private static synchronized void createAgentClassloader(final URL agentJarURL) {
}
}

/** Releases temporary packed class-data buffers retained during synchronous agent startup. */
public static void releaseClassData() {
ClassLoader classLoader = AGENT_CLASSLOADER;
if (classLoader instanceof DatadogClassLoader) {
((DatadogClassLoader) classLoader).releasePackedClassData();
}
}

private static void maybeStartRemoteConfig(Class<?> scoClass, Object sco) {
if (!remoteConfigEnabled) {
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public final class DatadogClassLoader extends SecureClassLoader {
private final CodeSource agentCodeSource;
private final String agentResourcePrefix;
private final AgentJarIndex agentJarIndex;
private final PackedClassData packedClassData;

private final Object instrumentationClassLoaderLock = new Object();
private volatile WeakReference<InstrumentationClassLoader> instrumentationClassLoader =
Expand All @@ -47,6 +48,7 @@ public DatadogClassLoader(final URL agentJarURL, final ClassLoader parent) throw
// findResource() returns URLs that openStream() cannot read. See APMS-19624 / #6398.
agentResourcePrefix = "jar:" + agentJarURL + "!/";
agentJarIndex = AgentJarIndex.readIndex(agentJarFile);
packedClassData = PackedClassData.from(agentJarFile);
}

/** For testing purposes only. */
Expand All @@ -57,6 +59,7 @@ public DatadogClassLoader() {
agentJarFile = null;
agentResourcePrefix = null;
agentJarIndex = AgentJarIndex.emptyIndex();
packedClassData = null;
}

@Override
Expand All @@ -82,7 +85,7 @@ protected URL findResource(String name) {
}
}
}
return null;
return packedClassData == null ? null : packedClassData.resource(name);
}

@Override
Expand Down Expand Up @@ -135,11 +138,28 @@ private Class<?> loadLocalClass(String name, boolean resolve) throws ClassNotFou

@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
byte[] buf = loadClassBytes(name);
PackedClassData.Slice packed = findPackedClassData(name);
if (packed != null) {
Class<?> defined =
defineClass(name, packed.data, packed.offset, packed.length, agentCodeSource);
return defined;
}
byte[] buf = loadIndividualClassBytes(name);
return defineClass(name, buf, 0, buf.length, agentCodeSource);
}

byte[] loadClassBytes(String name) throws ClassNotFoundException {
PackedClassData.Slice packed = findPackedClassData(name);
if (packed != null) {
byte[] copy = new byte[packed.length];
System.arraycopy(packed.data, packed.offset, copy, 0, packed.length);
// InstrumentationClassLoader defines this copied bytecode in its own unloadable loader.
return copy;
}
return loadIndividualClassBytes(name);
}

private byte[] loadIndividualClassBytes(String name) throws ClassNotFoundException {
String entryName = agentJarIndex.classEntryName(name);
if (null != entryName) {
JarEntry jarEntry = agentJarFile.getJarEntry(entryName);
Expand Down Expand Up @@ -167,6 +187,33 @@ byte[] loadClassBytes(String name) throws ClassNotFoundException {
throw new ClassNotFoundException(name);
}

private PackedClassData.Slice findPackedClassData(String name) {
if (packedClassData != null) {
try {
return packedClassData.find(name);
} catch (IOException e) {
throw new IllegalStateException("Problem reading " + PackedClassData.ENTRY_NAME, e);
}
}
return null;
}

void close() throws IOException {
if (agentJarFile != null) {
agentJarFile.close();
}
}

int retainedPackedClassBytes() {
return packedClassData == null ? 0 : packedClassData.retainedChunkBytes();
}

void releasePackedClassData() {
if (packedClassData != null) {
packedClassData.release();
}
}

@Override
protected Package getPackage(String name) {
synchronized (definedPackages) {
Expand Down
Loading