8000 Added special lightweight pre-main class that skips installation on incompatible JVMs. by AlexeyKuznetsov-DD · Pull Request #8855 · DataDog/dd-trace-java · GitHub
[go: up one dir, main page]

Skip to content

Added special lightweight pre-main class that skips installation on incompatible JVMs. #8855

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 21 commits into from
May 28, 2025
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
5e9b6ba
Added special lightweight pre-main class to enable SSI inject for Jav…
AlexeyKuznetsov-DD May 20, 2025
c40db79
Fixed SuppressForbidden test.
AlexeyKuznetsov-DD May 20, 2025
125a148
Refactored pre-check logic.
AlexeyKuznetsov-DD May 23, 2025
1e7ecd1
Merge branch 'master' into ssi-inject-java-6
AlexeyKuznetsov-DD May 23, 2025
99abf99
Refactored build.gradle to reuse existing functions.
AlexeyKuznetsov-DD May 23, 2025
2eb2753
Minor cleanup.
AlexeyKuznetsov-DD May 23, 2025
0c2e817
Added missing `@SuppressForbidden`.
AlexeyKuznetsov-DD May 23, 2025
45fb91f
Merge branch 'master' into ssi-inject-java-6
AlexeyKuznetsov-DD May 23, 2025
78dc42b
Merge branch 'master' into ssi-inject-java-6
AlexeyKuznetsov-DD May 23, 2025
ea5bea7
Added 'java.home' to warning. That would help to identify problematic…
AlexeyKuznetsov-DD May 23, 2025
5695279
Merge branch 'master' into ssi-inject-java-6
AlexeyKuznetsov-DD May 23, 2025
9238f7d
Added test to ensure Java 6 & 8 compilation.
AlexeyKuznetsov-DD May 24, 2025
10d60a0
Merge branch 'master' into ssi-inject-java-6
AlexeyKuznetsov-DD May 24, 2025
5f61b62
Fixed test.
AlexeyKuznetsov-DD May 24, 2025
5fa1bb6
Drop support for 0.x version.
AlexeyKuznetsov-DD May 27, 2025
985412f
Merge branch 'master' into ssi-inject-java-6
AlexeyKuznetsov-DD May 27, 2025
be58d6b
Fixed small typo.
AlexeyKuznetsov-DD May 27, 2025
7c2a597
Fixed test.
AlexeyKuznetsov-DD May 27, 2025
8192ac4
Update dd-java-agent/src/main/java6/datadog/trace/bootstrap/AgentPreC…
AlexeyKuznetsov-DD May 28, 2025
1037295
Merge branch 'master' into ssi-inject-java-6
AlexeyKuznetsov-DD May 28, 2025
e1df6fe
Fixed test.
AlexeyKuznetsov-DD May 28, 2025
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
34 changes: 30 additions & 4 deletions dd-java-agent/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,34 @@ configurations {
traceShadowInclude
}

sourceCompatibility = JavaVersion.VERSION_1_7
targetCompatibility = JavaVersion.VERSION_1_7
// Support SSI inject for Java 7.
tasks.named("compileJava", JavaCompile).configure {
sourceCompatibility = JavaVersion.VERSION_1_7
targetCompatibility = JavaVersion.VERSION_1_7
}

// Support SSI inject for Java 6.
sourceSets {
java6 {
java {
srcDirs = ['src/main/java6']
}
}
}

tasks.register('compileJava6', JavaCompile) {
classpath = sourceSets.main.compileClasspath
source = sourceSets.java6.java
destinationDirectory = layout.buildDirectory.dir("classes/java/main")
sourceCompatibility = JavaVersion.VERSION_1_6
targetCompatibility = JavaVersion.VERSION_1_6
}

dependencies {
java6CompileOnly 'de.thetaphi:forbiddenapis:3.4'
}

tasks.compileJava.dependsOn compileJava6

/*
* Several shadow jars are created
Expand Down Expand Up @@ -68,7 +94,7 @@ ext.generalShadowJarConfig = {
if (!projectName.equals('instrumentation')) {
relocate 'org.yaml.snakeyaml', 'datadog.snakeyaml'
relocate 'okhttp3', 'datadog.okhttp3'
relocate 'okio', 'datadog.okio'
relocate 'okio', 'datadog.okio'
}

if (!project.hasProperty("disableShadowRelocate") || !disableShadowRelocate) {
Expand Down Expand Up @@ -176,7 +202,7 @@ shadowJar generalShadowJarConfig >> {
attributes(
"Main-Class": "datadog.trace.bootstrap.AgentBootstrap",
"Agent-Class": "datadog.trace.bootstrap.AgentBootstrap",
"Premain-Class": "datadog.trace.bootstrap.AgentBootstrap",
"Premain-Class": "datadog.trace.bootstrap.AgentBootstrapJava6",
"Can-Redefine-Classes": true,
"Can-Retransform-Classes": true,
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
package datadog.trace.bootstrap;

import de.thetaphi.forbiddenapis.SuppressForbidden;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.lang.instrument.Instrumentation;
import java.lang.reflect.Method;

/** Special lightweight pre-main class to enable SSI inject for Java 6. */
public class AgentBootstrapJava6 {
public static void premain(final String agentArgs, final Instrumentation inst) {
agentmain(agentArgs, inst);
}

public static void agentmain(final String agentArgs, final Instrumentation inst) {
try {
String version = System.getProperty("java.version");
// Found Java 6
if (version.startsWith("1.6")) {
reportUnsupportedJava6(version);
} else {
continueBootstrap(agentArgs, inst);
}
} catch (Throwable e) {
error("Agent pre-main function failed", e);
}
}

private static void error(String msg, Throwable e) {
log(msg + ": " + e.getMessage());
}

@SuppressForbidden
private static void log(String msg) {
// We don't have a log manager here, so just print.
System.out.println(msg);
}

public static void reportUnsupportedJava6(String javaVersion) {
try {
String agentVersion = getAgentVersion();
log(
"Warning: "
+ agentVersion
+ " of dd-java-agent is not compatible with Java "
+ javaVersion
+ " and will not be installed.");
log("Please upgrade your Java version to 8+");
String forwarderPath = null;
try {
forwarderPath = System.getenv("DD_TELEMETRY_FORWARDER_PATH");
} catch (SecurityException e) {
log("Failed to get DD_TELEMETRY_FORWARDER_PATH: " + e.getMessage());
}
if (forwarderPath == null) {
log("Telemetry forwarder path is null.");
return;
}
String payload =
"{\"metadata\":{"
+ "\"runtime_name\":\"jvm\","
+ "\"language_name\":\"jvm\","
+ "\"runtime_version\":\""
+ javaVersion
+ "\","
+ "\"language_version\":\""
+ javaVersion
+ "\","
+ "\"tracer_version\":\""
+ agentVersion
+ "\"},"
+ "\"points\":\"[{"
+ "\"name\":\"library_entrypoint.abort\","
+ "\"tags\":[\"reason:incompatible_runtime\"]"
+ "}]"
+ "}";

ForwarderJsonSenderThread t = new ForwarderJsonSenderThread(forwarderPath, payload);
t.start();

try {
t.join(1000);
} catch (InterruptedException e) {
// just for hygiene, reset the interrupt status
Thread.currentThread().interrupt();
}
} catch (Throwable e) {
error("Failed to report telemetry", e);
}
}

public static String getAgentVersion() {
try {
// Get the resource as an InputStream
InputStream is = AgentBootstrapJava6.class.getResourceAsStream("/dd-java-agent.version");
if (is == null) {
return "n/a";
}

BufferedReader reader = new BufferedReader(new InputStreamReader(is));
final StringBuilder sb = new StringBuilder();
for (int c = reader.read(); c != -1; c = reader.read()) {
sb.append((char) c);
}
reader.close();

return sb.toString().trim();
} catch (Throwable e) {
return "unknown";
}
}

@SuppressForbidden
private static void continueBootstrap(final String agentArgs, final Instrumentation inst) {
try {
Class<?> clazz = Class.forName("datadog.trace.bootstrap.AgentBootstrap");
Method agentMain = clazz.getMethod("agentmain", String.class, Instrumentation.class);
agentMain.invoke(null, agentArgs, inst);
} catch (Throwable e) {
System.err.println("Failed to install dd-java-agent: " + e.getMessage());
}
}

public static final class ForwarderJsonSenderThread extends Thread {
private final String forwarderPath;
private final String payload;

public ForwarderJsonSenderThread(String forwarderPath, String payload) {
super("dd-forwarder-json-sender");
setDaemon(true);
this.forwarderPath = forwarderPath;
this.payload = payload;
}

@Override
public void run() {
ProcessBuilder builder = new ProcessBuilder(forwarderPath, "library_entrypoint");
try {
Process process = builder.start();
OutputStream out = null;
try {
out = process.getOutputStream();
out.write(payload.getBytes());
} finally {
if (out != null) {
out.close();
}
}
} catch (Throwable e) {
error("Failed to send telemetry", e);
}
}
}
}
Loading
0