|
6 | 6 |
|
7 | 7 | import com.datadoghq.profiler.JVMAccess; |
8 | 8 | import com.sun.management.HotSpotDiagnosticMXBean; |
| 9 | +import datadog.environment.JavaVirtualMachine; |
9 | 10 | import datadog.environment.OperatingSystem; |
10 | 11 | import datadog.libs.ddprof.DdprofLibraryLoader; |
11 | 12 | import datadog.trace.api.Platform; |
|
17 | 18 | import java.nio.file.Files; |
18 | 19 | import java.nio.file.Path; |
19 | 20 | import java.nio.file.Paths; |
| 21 | +import java.util.List; |
20 | 22 | import java.util.StringTokenizer; |
21 | 23 | import java.util.function.Predicate; |
22 | 24 | import java.util.stream.Stream; |
@@ -75,6 +77,11 @@ public boolean setValue(String flagName, String value) { |
75 | 77 | } |
76 | 78 |
|
77 | 79 | public static boolean initialize(boolean forceJmx) { |
| 80 | + // J9/OpenJ9 requires different initialization path |
| 81 | + if (JavaVirtualMachine.isJ9()) { |
| 82 | + return initializeJ9(); |
| 83 | + } |
| 84 | + |
78 | 85 | try { |
79 | 86 | FlagAccess access = null; |
80 | 87 | // Native images don't support the native ddprof library, use JMX instead |
@@ -105,6 +112,105 @@ public static boolean initialize(boolean forceJmx) { |
105 | 112 | return false; |
106 | 113 | } |
107 | 114 |
|
| 115 | + /** |
| 116 | + * Initialize crash tracking for J9/OpenJ9 JVMs. |
| 117 | + * |
| 118 | + * <p>Unlike HotSpot, J9's -Xdump option cannot be modified at runtime. This method: |
| 119 | + * |
| 120 | + * <ol> |
| 121 | + * <li>Checks if -Xdump:tool is already configured |
| 122 | + * <li>Deploys the crash uploader script if configured |
| 123 | + * <li>Logs instructions for manual configuration if not configured |
| 124 | + * </ol> |
| 125 | + * |
| 126 | + * @return true if -Xdump is properly configured, false otherwise |
| 127 | + */ |
| 128 | + private static boolean initializeJ9() { |
| 129 | + try { |
| 130 | + String scriptPath = getJ9CrashUploaderScriptPath(); |
| 131 | + |
| 132 | + // Check if -Xdump:tool is already configured via JVM arguments |
| 133 | + boolean xdumpConfigured = isXdumpToolConfigured(); |
| 134 | + // Get custom javacore path if configured |
| 135 | + String javacorePath = getJ9JavacorePath(); |
| 136 | + |
| 137 | + if (xdumpConfigured) { |
| 138 | + LOG.debug("J9 crash tracking: -Xdump:tool already configured, crash uploads enabled"); |
| 139 | + // Initialize the crash uploader script and config manager |
| 140 | + CrashUploaderScriptInitializer.initialize(scriptPath, null, javacorePath); |
| 141 | + // Also set up OOME notifier script |
| 142 | + String oomeScript = getScript("dd_oome_notifier"); |
| 143 | + OOMENotifierScriptInitializer.initialize(oomeScript); |
| 144 | + return true; |
| 145 | + } else { |
| 146 | + // Log instructions for manual configuration |
| 147 | + LOG.info("J9 JVM detected. To enable crash tracking, add this JVM argument at startup:"); |
| 148 | + LOG.info(" -Xdump:tool:events=gpf+abort,exec={}\\ %pid", scriptPath); |
| 149 | + LOG.info( |
| 150 | + "Crash tracking will not be active until this argument is added and JVM is restarted."); |
| 151 | + return false; |
| 152 | + } |
| 153 | + } catch (Throwable t) { |
| 154 | + logInitializationError( |
| 155 | + "Unexpected exception while initializing J9 crash tracking. Crash tracking will not work.", |
| 156 | + t); |
| 157 | + } |
| 158 | + return false; |
| 159 | + } |
| 160 | + |
| 161 | + /** |
| 162 | + * Get the custom javacore file path from -Xdump:java:file=... JVM argument. |
| 163 | + * |
| 164 | + * @return the custom javacore path, or null if not configured |
| 165 | + */ |
| 166 | + private static String getJ9JavacorePath() { |
| 167 | + List<String> vmArgs = JavaVirtualMachine.getVmOptions(); |
| 168 | + for (String arg : vmArgs) { |
| 169 | + if (arg.startsWith("-Xdump:java:file=") || arg.startsWith("-Xdump:java+heap:file=")) { |
| 170 | + int fileIdx = arg.indexOf("file="); |
| 171 | + if (fileIdx >= 0) { |
| 172 | + String path = arg.substring(fileIdx + 5); |
| 173 | + // Handle comma-separated options: -Xdump:java:file=/path,request=exclusive |
| 174 | + int commaIdx = path.indexOf(','); |
| 175 | + if (commaIdx > 0) { |
| 176 | + path = path.substring(0, commaIdx); |
| 177 | + } |
| 178 | + return path; |
| 179 | + } |
| 180 | + } |
| 181 | + } |
| 182 | + return null; |
| 183 | + } |
| 184 | + |
| 185 | + /** |
| 186 | + * Check if -Xdump:tool is configured with our crash uploader script. |
| 187 | + * |
| 188 | + * <p>Looks for JVM arguments matching: -Xdump:tool:events=...,exec=...dd_crash_uploader... |
| 189 | + */ |
| 190 | + private static boolean isXdumpToolConfigured() { |
| 191 | + List<String> vmArgs = JavaVirtualMachine.getVmOptions(); |
| 192 | + for (String arg : vmArgs) { |
| 193 | + if (arg.startsWith("-Xdump:tool") && arg.contains("dd_crash_uploader")) { |
| 194 | + return true; |
| 195 | + } |
| 196 | + } |
| 197 | + return false; |
| 198 | + } |
| 199 | + |
| 200 | + /** |
| 201 | + * Get the path where the crash uploader script should be deployed for J9. |
| 202 | + * |
| 203 | + * <p>Note: The actual script deployment is handled by {@link CrashUploaderScriptInitializer} when |
| 204 | + * initialize() is called with this path. |
| 205 | + * |
| 206 | + * @return the full path for the crash uploader script |
| 207 | + */ |
| 208 | + private static String getJ9CrashUploaderScriptPath() { |
| 209 | + String scriptFileName = getScriptFileName("dd_crash_uploader"); |
| 210 | + Path scriptPath = TempLocationManager.getInstance().getTempDir().resolve(scriptFileName); |
| 211 | + return scriptPath.toString(); |
| 212 | + } |
| 213 | + |
108 | 214 | static InputStream getCrashUploaderTemplate() { |
109 | 215 | String name = OperatingSystem.isWindows() ? "upload_crash.bat" : "upload_crash.sh"; |
110 | 216 | return CrashUploader.class.getResourceAsStream(name); |
|
0 commit comments