@@ -51,6 +51,10 @@ static const char USAGE_STRING[] =
5151 " list list profiling events supported by the target JVM\n "
5252 " collect collect profile for the specified period of time\n "
5353 " and then stop (default action)\n "
54+ " fdtransfer start fdtransfer to serve perf requests on behalf of profiled process\n "
55+ " jattach invoke jattach directly; requires --jattach-cmd,\n "
56+ " ignores all arguments except --lib-prefix\n "
57+ " \n "
5458 " Options:\n "
5559 " -e event profiling event: cpu|alloc|lock|cache-misses etc.\n "
5660 " -d duration run profiling for <duration> seconds\n "
@@ -87,6 +91,12 @@ static const char USAGE_STRING[] =
8791 " --jfrsync config synchronize profiler with JFR recording\n "
8892 " --fdtransfer use fdtransfer to serve perf requests\n "
8993 " from the non-privileged target\n "
94+ " --fd-path string use specified path for fdtransfer to listen at\n "
95+ " --jattach-cmd string\n "
96+ " arguments to use with jattach action\n "
97+ " -L|--lib-prefix string\n "
98+ " path prefix to prepend to shared lib\n "
99+ " --fd-path string socket path for fdtransfer to bind to\n "
90100 " \n "
91101 " <pid> is a numeric process ID of the target JVM\n "
92102 " or 'jps' keyword to find running JVM automatically\n "
@@ -170,6 +180,10 @@ class String {
170180 return strcmp (_str, other._str ) == 0 ;
171181 }
172182
183+ bool operator !=(const String& other) const {
184+ return strcmp (_str, other._str ) != 0 ;
185+ }
186+
173187 String& operator <<(const char * tail) {
174188 size_t len = strlen (_str);
175189 _str = (char *)realloc (_str, len + strlen (tail) + 1 );
@@ -205,7 +219,9 @@ class String {
205219
206220
207221static String action = " collect" ;
208- static const String empty;
222+ static const String kEmpty ;
223+ static const String kJattachLoad = " load" ;
224+ static const String kJattachJcmd = " jcmd" ;
209225static String file, logfile, output, params, format, fdtransfer, libpath;
210226static bool use_tmp_file = false ;
211227static int duration = 60 ;
@@ -333,38 +349,51 @@ static void run_fdtransfer(int pid, String& fdtransfer) {
333349 }
334350}
335351
336- static void run_jattach (int pid, String& cmd) {
352+ static void run_jattach (int pid, const String& verb, String& cmd) {
337353 pid_t child = fork ();
338354 if (child == -1 ) {
339355 error (" fork failed" , errno);
340356 }
341357
342358 if (child == 0 ) {
343- const char * argv[] = {" load" , libpath.str (), libpath.str ()[0 ] == ' /' ? " true" : " false" , cmd.str ()};
344- exit (jattach (pid, 4 , argv));
359+ const char ** argv;
360+ int argc;
361+ int ret;
362+ String pidstr;
363+ pidstr << pid;
364+ if (verb == kJattachLoad ) {
365+ const char * args[] = {kJattachLoad .str (), libpath.str (), libpath.str ()[0 ] == ' /' ? " true" : " false" , cmd.str ()};
366+ ret = jattach (pid, 4 , args);
367+ } else if (verb == kJattachJcmd ) {
368+ const char * args[] = {kJattachJcmd .str (), cmd.str ()};
369+ ret = jattach (pid, 2 , args);
370+ }
371+ exit (ret);
345372 } else {
346373 int ret = wait_for_exit (child);
347374 if (ret != 0 ) {
348375 if (WEXITSTATUS (ret) == 255 ) {
349376 fprintf (stderr, " Target JVM failed to load %s\n " , libpath.str ());
350377 }
351- print_file (logfile, STDERR_FILENO);
378+ if (logfile != kEmpty ) print_file (logfile, STDERR_FILENO);
352379 exit (WEXITSTATUS (ret));
353380 }
354381
355- print_file (logfile, STDERR_FILENO);
382+ if (logfile != kEmpty ) print_file (logfile, STDERR_FILENO);
356383 if (use_tmp_file) print_file (file, STDOUT_FILENO);
357384 }
358385}
359386
360387
361388int main (int argc, const char ** argv) {
362389 Args args (argc, argv);
390+ String jattach_cmd;
363391 while (args.hasNext ()) {
364392 String arg = args.next ();
365393
366394 if (arg == " start" || arg == " resume" || arg == " stop" || arg == " dump" || arg == " check" ||
367- arg == " status" || arg == " meminfo" || arg == " list" || arg == " collect" ) {
395+ arg == " status" || arg == " meminfo" || arg == " list" || arg == " collect" ||
396+ arg == " fdtransfer" || arg == " jattach" || arg == " jcmd" ) {
368397 action = arg;
369398
370399 } else if (arg == " -h" || arg == " --help" ) {
@@ -457,12 +486,20 @@ int main(int argc, const char** argv) {
457486 params << " ," << (arg.str () + 2 ) << " =" << args.next ();
458487 if (action == " collect" ) action = " start" ;
459488
489+ } else if (arg == " --fd-path" ) {
490+ fdtransfer = String (args.next ());
491+
460492 } else if (arg == " --fdtransfer" ) {
461493 char buf[64 ];
462- snprintf (buf, sizeof (buf), " @async-profiler-%d-%08x" , getpid (), (unsigned int )time_micros ());
463- fdtransfer = buf;
494+ if (fdtransfer == kEmpty ) {
495+ snprintf (buf, sizeof (buf), " @async-profiler-%d-%08x" , getpid (), (unsigned int )time_micros ());
496+ fdtransfer = buf;
497+ }
464498 params << " ,fdtransfer=" << fdtransfer;
465499
500+ } else if (arg == " --jattach-cmd" ) {
501+ jattach_cmd = String (args.next ());
502+
466503 } else if (arg.str ()[0 ] >= ' 0' && arg.str ()[0 ] <= ' 9' && pid == 0 ) {
467504 pid = atoi (arg.str ());
468505
@@ -489,14 +526,19 @@ int main(int argc, const char** argv) {
489526 return 1 ;
490527 }
491528
492- setup_output_files (pid);
493- if (libpath == empty) {
529+ if (jattach_cmd == kEmpty ) {
530+ setup_output_files (pid);
531+ } else if (params != kEmpty ) {
532+ fprintf (stderr, " Warning: --jattach-cmd was given, these parameters will be ignored: %s\n " , params.str ());
533+ }
534+
535+ if (libpath == kEmpty ) {
494536 setup_lib_path ();
495537 }
496538
497539 if (action == " collect" ) {
498540 run_fdtransfer (pid, fdtransfer);
499- run_jattach (pid, String (" start,file=" ) << file << " ," << output << format << params << " ,log=" << logfile);
541+ run_jattach (pid, kJattachLoad , String (" start,file=" ) << file << " ," << output << format << params << " ,log=" << logfile);
500542
501543 fprintf (stderr, " Profiling for %d seconds\n " , duration);
502544 end_time = time_micros () + duration * 1000000ULL ;
@@ -514,10 +556,30 @@ int main(int argc, const char** argv) {
514556 signal (SIGINT, SIG_DFL);
515557 fprintf (stderr, " Done\n " );
516558
517- run_jattach (pid, String (" stop,file=" ) << file << " ," << output << format << " ,log=" << logfile);
559+ run_jattach (pid, kJattachLoad , String (" stop,file=" ) << file << " ," << output << format << " ,log=" << logfile);
560+ } else if (action == " fdtransfer" ) {
561+ if (params != kEmpty ) {
562+ fprintf (stderr, " Warning: action fdtransfer was given, these parameters will be ignored: %s\n " , params.str ());
563+ }
564+ run_fdtransfer (pid, fdtransfer);
565+
566+ } else if (action == " jattach" ) {
567+ if (jattach_cmd == kEmpty ) {
568+ fprintf (stderr, " Action jattach was given, missing required --jattach-cmd argument\n " );
569+ return 1 ;
570+ }
571+ run_jattach (pid, kJattachLoad , jattach_cmd);
572+
573+ } else if (action == " jcmd" ) {
574+ if (jattach_cmd == kEmpty ) {
575+ fprintf (stderr, " Action jcmd was given, missing required --jattach-cmd argument\n " );
576+ return 1 ;
577+ }
578+ run_jattach (pid, kJattachJcmd , jattach_cmd);
579+
518580 } else {
519581 if (action == " start" || action == " resume" ) run_fdtransfer (pid, fdtransfer);
520- run_jattach (pid, String (action) << " ,file=" << file << " ," << output << format << params << " ,log=" << logfile);
582+ run_jattach (pid, kJattachLoad , String (action) << " ,file=" << file << " ," << output << format << params << " ,log=" << logfile);
521583 }
522584
523585 return 0 ;
0 commit comments