jdk/src/jdk.jcmd/share/classes/sun/tools/jstack/JStack.java
changeset 38360 fb63be22ffa6
parent 36511 9d0388c6b336
child 38361 8ea2d56bfdf3
equal deleted inserted replaced
38359:fd9b36598481 38360:fb63be22ffa6
    28 import java.io.InputStream;
    28 import java.io.InputStream;
    29 
    29 
    30 import com.sun.tools.attach.VirtualMachine;
    30 import com.sun.tools.attach.VirtualMachine;
    31 import com.sun.tools.attach.AttachNotSupportedException;
    31 import com.sun.tools.attach.AttachNotSupportedException;
    32 import sun.tools.attach.HotSpotVirtualMachine;
    32 import sun.tools.attach.HotSpotVirtualMachine;
    33 import jdk.internal.vm.agent.spi.ToolProvider;
       
    34 import jdk.internal.vm.agent.spi.ToolProviderFinder;
       
    35 
    33 
    36 /*
    34 /*
    37  * This class is the main class for the JStack utility. It parses its arguments
    35  * This class is the main class for the JStack utility. It parses its arguments
    38  * and decides if the command should be executed by the SA JStack tool or by
    36  * and decides if the command should be executed by the SA JStack tool or by
    39  * obtained the thread dump from a target process using the VM attach mechanism
    37  * obtained the thread dump from a target process using the VM attach mechanism
    40  */
    38  */
    41 public class JStack {
    39 public class JStack {
    42     private static final String SA_JSTACK_TOOL_NAME = "jstack";
       
    43 
    40 
    44     public static void main(String[] args) throws Exception {
    41     public static void main(String[] args) throws Exception {
    45         if (args.length == 0) {
    42         if (args.length == 0) {
    46             usage(1); // no arguments
    43             usage(1); // no arguments
    47         }
    44         }
    48 
    45 
    49         boolean useSA = false;
    46         checkForUnsupportedOptions(args);
    50         boolean mixed = false;
    47 
    51         boolean locks = false;
    48         boolean locks = false;
    52 
    49 
    53         // Parse the options (arguments starting with "-" )
    50         // Parse the options (arguments starting with "-" )
    54         int optionCount = 0;
    51         int optionCount = 0;
    55         while (optionCount < args.length) {
    52         while (optionCount < args.length) {
    58                 break;
    55                 break;
    59             }
    56             }
    60             if (arg.equals("-help") || arg.equals("-h")) {
    57             if (arg.equals("-help") || arg.equals("-h")) {
    61                 usage(0);
    58                 usage(0);
    62             }
    59             }
    63             else if (arg.equals("-F")) {
       
    64                 useSA = true;
       
    65             }
       
    66             else {
    60             else {
    67                 if (arg.equals("-m")) {
    61                 if (arg.equals("-l")) {
    68                     mixed = true;
    62                     locks = true;
    69                 } else {
    63                 } else {
    70                     if (arg.equals("-l")) {
    64                     usage(1);
    71                        locks = true;
       
    72                     } else {
       
    73                         usage(1);
       
    74                     }
       
    75                 }
    65                 }
    76             }
    66             }
    77             optionCount++;
    67             optionCount++;
    78         }
    68         }
    79 
    69 
    80         // mixed stack implies SA tool
    70         // Next we check the parameter count.
    81         if (mixed) {
    71         int paramCount = args.length - optionCount;
    82             useSA = true;
    72         if (paramCount != 1) {
       
    73             usage(1);
    83         }
    74         }
    84 
    75 
    85         // Next we check the parameter count. If there are two parameters
    76         // pass -l to thread dump operation to get extra lock info
    86         // we assume core file and executable so we use SA.
    77         String pid = args[optionCount];
    87         int paramCount = args.length - optionCount;
    78         String params[];
    88         if (paramCount == 0 || paramCount > 2) {
    79         if (locks) {
    89             usage(1);
    80             params = new String[] { "-l" };
       
    81         } else {
       
    82             params = new String[0];
    90         }
    83         }
    91         if (paramCount == 2) {
    84         runThreadDump(pid, params);
    92             useSA = true;
       
    93         } else {
       
    94             // If we can't parse it as a pid then it must be debug server
       
    95             if (!args[optionCount].matches("[0-9]+")) {
       
    96                 useSA = true;
       
    97             }
       
    98         }
       
    99 
       
   100         // now execute using the SA JStack tool or the built-in thread dumper
       
   101         if (useSA) {
       
   102             // parameters (<pid> or <exe> <core>
       
   103             String params[] = new String[paramCount];
       
   104             for (int i=optionCount; i<args.length; i++ ){
       
   105                 params[i-optionCount] = args[i];
       
   106             }
       
   107             runJStackTool(mixed, locks, params);
       
   108         } else {
       
   109             // pass -l to thread dump operation to get extra lock info
       
   110             String pid = args[optionCount];
       
   111             String params[];
       
   112             if (locks) {
       
   113                 params = new String[] { "-l" };
       
   114             } else {
       
   115                 params = new String[0];
       
   116             }
       
   117             runThreadDump(pid, params);
       
   118         }
       
   119     }
    85     }
   120 
       
   121     // SA JStack tool
       
   122     private static boolean isAgentToolPresent() {
       
   123         return ToolProviderFinder.find(SA_JSTACK_TOOL_NAME) != null;
       
   124     }
       
   125 
       
   126     private static void runJStackTool(boolean mixed, boolean locks, String args[]) throws Exception {
       
   127         ToolProvider tool = ToolProviderFinder.find(SA_JSTACK_TOOL_NAME);
       
   128         if (tool == null) {
       
   129             usage(1);            // SA not available
       
   130         }
       
   131 
       
   132         // JStack tool also takes -m and -l arguments
       
   133         if (mixed) {
       
   134             args = prepend("-m", args);
       
   135         }
       
   136         if (locks) {
       
   137             args = prepend("-l", args);
       
   138         }
       
   139 
       
   140         tool.run(args);
       
   141     }
       
   142 
       
   143 
    86 
   144     // Attach to pid and perform a thread dump
    87     // Attach to pid and perform a thread dump
   145     private static void runThreadDump(String pid, String args[]) throws Exception {
    88     private static void runThreadDump(String pid, String args[]) throws Exception {
   146         VirtualMachine vm = null;
    89         VirtualMachine vm = null;
   147         try {
    90         try {
   150             String msg = x.getMessage();
    93             String msg = x.getMessage();
   151             if (msg != null) {
    94             if (msg != null) {
   152                 System.err.println(pid + ": " + msg);
    95                 System.err.println(pid + ": " + msg);
   153             } else {
    96             } else {
   154                 x.printStackTrace();
    97                 x.printStackTrace();
   155             }
       
   156             if ((x instanceof AttachNotSupportedException) && isAgentToolPresent()) {
       
   157                 System.err.println("The -F option can be used when the target " +
       
   158                     "process is not responding");
       
   159             }
    98             }
   160             System.exit(1);
    99             System.exit(1);
   161         }
   100         }
   162 
   101 
   163         // Cast to HotSpotVirtualMachine as this is implementation specific
   102         // Cast to HotSpotVirtualMachine as this is implementation specific
   176         } while (n > 0);
   115         } while (n > 0);
   177         in.close();
   116         in.close();
   178         vm.detach();
   117         vm.detach();
   179     }
   118     }
   180 
   119 
   181     // return a new string array with arg as the first element
   120     private static void checkForUnsupportedOptions(String[] args) {
   182     private static String[] prepend(String arg, String args[]) {
   121         // Check arguments for -F, -m, and non-numeric value
   183         String[] newargs = new String[args.length+1];
   122         // and warn the user that SA is not supported anymore
   184         newargs[0] = arg;
   123 
   185         System.arraycopy(args, 0, newargs, 1, args.length);
   124         int paramCount = 0;
   186         return newargs;
   125 
       
   126         for (String s : args) {
       
   127             if (s.equals("-F")) {
       
   128                 SAOptionError("-F option used");
       
   129             }
       
   130 
       
   131             if (s.equals("-m")) {
       
   132                 SAOptionError("-m option used");
       
   133             }
       
   134 
       
   135             if (! s.startsWith("-")) {
       
   136                 if (! s.matches("[0-9]+")) {
       
   137                     SAOptionError("non PID argument");
       
   138                 }
       
   139                 paramCount += 1;
       
   140             }
       
   141         }
       
   142 
       
   143         if (paramCount > 1) {
       
   144             SAOptionError("More than one non-option argument");
       
   145         }
       
   146     }
       
   147 
       
   148     private static void SAOptionError(String msg) {
       
   149         System.err.println("Error: " + msg);
       
   150         System.err.println("Cannot connect to core dump or remote debug server. Use jhsdb jstack instead");
       
   151         System.exit(1);
   187     }
   152     }
   188 
   153 
   189     // print usage message
   154     // print usage message
   190     private static void usage(int exit) {
   155     private static void usage(int exit) {
   191         System.err.println("Usage:");
   156         System.err.println("Usage:");
   192         System.err.println("    jstack [-l] <pid>");
   157         System.err.println("    jstack [-l] <pid>");
   193         System.err.println("        (to connect to running process)");
   158         System.err.println("        (to connect to running process)");
   194 
       
   195         if (isAgentToolPresent()) {
       
   196             System.err.println("    jstack -F [-m] [-l] <pid>");
       
   197             System.err.println("        (to connect to a hung process)");
       
   198             System.err.println("    jstack [-m] [-l] <executable> <core>");
       
   199             System.err.println("        (to connect to a core file)");
       
   200             System.err.println("    jstack [-m] [-l] [server_id@]<remote server IP or hostname>");
       
   201             System.err.println("        (to connect to a remote debug server)");
       
   202         }
       
   203 
       
   204         System.err.println("");
   159         System.err.println("");
   205         System.err.println("Options:");
   160         System.err.println("Options:");
   206 
       
   207         if (isAgentToolPresent()) {
       
   208             System.err.println("    -F  to force a thread dump. Use when jstack <pid> does not respond" +
       
   209                 " (process is hung)");
       
   210             System.err.println("    -m  to print both java and native frames (mixed mode)");
       
   211         }
       
   212 
       
   213         System.err.println("    -l  long listing. Prints additional information about locks");
   161         System.err.println("    -l  long listing. Prints additional information about locks");
   214         System.err.println("    -h or -help to print this help message");
   162         System.err.println("    -h or -help to print this help message");
   215         System.exit(exit);
   163         System.exit(exit);
   216     }
   164     }
   217 }
   165 }