23
23
24
24
package openj9 .internal .tools .attach .target ;
25
25
26
+ import java .io .File ;
26
27
import java .io .PrintWriter ;
27
28
import java .io .StringWriter ;
29
+ import java .nio .file .InvalidPathException ;
30
+ import java .nio .file .Path ;
31
+ import java .nio .file .Paths ;
28
32
import java .util .Arrays ;
29
33
import java .util .HashMap ;
30
34
import java .util .Map ;
@@ -144,6 +148,9 @@ public class DiagnosticUtils {
144
148
private static final String DIAGNOSTICS_JFR_START = "JFR.start" ;
145
149
private static final String DIAGNOSTICS_JFR_DUMP = "JFR.dump" ;
146
150
private static final String DIAGNOSTICS_JFR_STOP = "JFR.stop" ;
151
+
152
+ private static final int ERROR_NO_TIME_UNIT = -1 ;
153
+ private static final int ERROR_NO_TIME_DURATION = -2 ;
147
154
/*[ENDIF] JFR_SUPPORT */
148
155
149
156
/**
@@ -209,7 +216,39 @@ public static String makeThreadPrintCommand(boolean lockedSynchronizers) {
209
216
* @return formatted string
210
217
*/
211
218
public static String makeJcmdCommand (String [] options , int skip ) {
212
- String cmd = String .join (DIAGNOSTICS_OPTION_SEPARATOR , Arrays .asList (options ).subList (skip , options .length ));
219
+ int optionsLength = options .length ;
220
+ /*[IF JFR_SUPPORT]*/
221
+ if (optionsLength >= 2 ) {
222
+ // there is a jcmd command
223
+ if (DIAGNOSTICS_JFR_START .equalsIgnoreCase (options [1 ])) {
224
+ // search JFR.start options
225
+ for (int i = 2 ; i < optionsLength ; i ++) {
226
+ String option = options [i ];
227
+ IPC .logMessage ("makeJcmdCommand: option = " , option );
228
+ if (option .startsWith ("filename=" )) {
229
+ String fileName = option .substring (option .indexOf ("=" ) + 1 );
230
+ try {
231
+ Path filePath = Paths .get (fileName );
232
+ if (!filePath .isAbsolute ()) {
233
+ // default recording file path is jcmd current working directory
234
+ String jcmdPWD = Paths .get ("" ).toAbsolutePath ().toString ();
235
+ fileName = jcmdPWD + File .separator + fileName ;
236
+ IPC .logMessage ("makeJcmdCommand: absolute filename = " , fileName );
237
+ // replace existing entry with an absolute jcmd pwd path for the target VM
238
+ options [i ] = "filename=" + fileName ;
239
+ }
240
+ } catch (InvalidPathException ipe ) {
241
+ // ignore this exception and keep the original entry
242
+ IPC .logMessage ("makeJcmdCommand: ipe = " , ipe .getMessage ());
243
+ }
244
+ // only one filename is allowed
245
+ break ;
246
+ }
247
+ }
248
+ }
249
+ }
250
+ /*[ENDIF] JFR_SUPPORT */
251
+ String cmd = String .join (DIAGNOSTICS_OPTION_SEPARATOR , Arrays .asList (options ).subList (skip , optionsLength ));
213
252
return cmd ;
214
253
}
215
254
@@ -415,13 +454,25 @@ private static long convertToMilliseconds(String timeValue) {
415
454
timeInMilli = TimeUnit .DAYS .toMillis (time );
416
455
break ;
417
456
default :
418
- // no unit or unrecognized unit, assume milliseconds
419
- timeInMilli = time ;
457
+ // no unit or unrecognized unit, return ERROR_NO_TIME_UNIT
458
+ timeInMilli = ERROR_NO_TIME_UNIT ;
420
459
break ;
421
460
}
422
461
return timeInMilli ;
423
462
}
424
463
464
+ /**
465
+ * Parse a time parameter, and return the duration in milliseconds.
466
+ * If the time unit is missing, ERROR_NO_TIME_UNIT is returned.
467
+ * If the paramName is not in parameters, ERROR_NO_TIME_DURATION is returned.
468
+ *
469
+ * @param paramName the parameter name
470
+ * @param parameters the parameter array
471
+ *
472
+ * @return the duration in milliseconds,
473
+ * ERROR_NO_TIME_UNIT if no time unit,
474
+ * ERROR_NO_TIME_DURATION if paramName wasn't found.
475
+ */
425
476
private static long parseTimeParameter (String paramName , String [] parameters ) {
426
477
for (String param : parameters ) {
427
478
if (param .startsWith (paramName + "=" )) {
@@ -431,7 +482,7 @@ private static long parseTimeParameter(String paramName, String[] parameters) {
431
482
}
432
483
}
433
484
}
434
- return - 1 ;
485
+ return ERROR_NO_TIME_DURATION ;
435
486
}
436
487
437
488
private static String parseStringParameter (String paramName , String [] parameters , String defaultValue ) {
@@ -475,9 +526,12 @@ private static DiagnosticProperties doJFR(String diagnosticCommand) {
475
526
jfrRecordingFileName = fileName ;
476
527
}
477
528
}
478
- VM .startJFR ();
479
529
long duration = parseTimeParameter ("duration" , parameters );
480
530
IPC .logMessage ("doJFR: duration = " + duration );
531
+ if (duration == ERROR_NO_TIME_UNIT ) {
532
+ return DiagnosticProperties .makeErrorProperties ("The duration doesn't have a time unit." );
533
+ }
534
+ VM .startJFR ();
481
535
if (duration > 0 ) {
482
536
Timer timer = new Timer ();
483
537
TimerTask jfrDumpTask = new TimerTask () {
0 commit comments