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 { |
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 } |