1 /*
2  * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package sun.tools.jinfo;
27 
28 import java.io.IOException;
29 import java.io.InputStream;
30 import java.util.Collection;
31 
32 import com.sun.tools.attach.VirtualMachine;
33 import com.sun.tools.attach.VirtualMachineDescriptor;
34 
35 import sun.tools.attach.HotSpotVirtualMachine;
36 import sun.tools.common.ProcessArgumentMatcher;
37 
38 /*
39  * This class is the main class for the JInfo utility. It parses its arguments
40  * and decides if the command should be satisfied using the VM attach mechanism
41  * or an SA tool.
42  */
43 final public class JInfo {
44 
main(String[] args)45     public static void main(String[] args) throws Exception {
46         if (args.length == 0) {
47             usage(1); // no arguments
48         }
49         checkForUnsupportedOptions(args);
50 
51         boolean doFlag = false;
52         boolean doFlags = false;
53         boolean doSysprops = false;
54         int flag = -1;
55 
56         // Parse the options (arguments starting with "-" )
57         int optionCount = 0;
58         while (optionCount < args.length) {
59             String arg = args[optionCount];
60             if (!arg.startsWith("-")) {
61                 break;
62             }
63 
64             optionCount++;
65 
66             if (arg.equals("-?") ||
67                 arg.equals("-h") ||
68                 arg.equals("--help") ||
69                 // -help: legacy.
70                 arg.equals("-help")) {
71                 usage(0);
72             }
73 
74             if (arg.equals("-flag")) {
75                 doFlag = true;
76                 // Consume the flag
77                 if (optionCount < args.length) {
78                     flag = optionCount++;
79                     break;
80                 }
81                 usage(1);
82             }
83 
84             if (arg.equals("-flags")) {
85                 doFlags = true;
86                 break;
87             }
88 
89             if (arg.equals("-sysprops")) {
90                 doSysprops = true;
91                 break;
92             }
93         }
94 
95         int paramCount = args.length - optionCount;
96         if (paramCount != 1) {
97             usage(1);
98         }
99 
100         String parg = args[optionCount];
101 
102         ProcessArgumentMatcher ap = new ProcessArgumentMatcher(parg);
103         Collection<String> pids = ap.getVirtualMachinePids(JInfo.class);
104 
105         if (pids.isEmpty()) {
106             System.err.println("Could not find any processes matching : '" + parg + "'");
107             System.exit(1);
108         }
109 
110         for (String pid : pids) {
111             if (pids.size() > 1) {
112                 System.out.println("Pid:" + pid);
113             }
114             if (!doFlag && !doFlags && !doSysprops) {
115                 // Print flags and sysporps if no options given
116                 sysprops(pid);
117                 System.out.println();
118                 flags(pid);
119                 System.out.println();
120                 commandLine(pid);
121             }
122             if (doFlag) {
123                 if (flag < 0) {
124                     System.err.println("Missing flag");
125                     usage(1);
126                 }
127                 flag(pid, args[flag]);
128             }
129             if (doFlags) {
130                 flags(pid);
131             }
132             if (doSysprops) {
133                 sysprops(pid);
134             }
135         }
136     }
137 
flag(String pid, String option)138     private static void flag(String pid, String option) throws IOException {
139         HotSpotVirtualMachine vm = (HotSpotVirtualMachine) attach(pid);
140         String flag;
141         InputStream in;
142         int index = option.indexOf('=');
143         if (index != -1) {
144             flag = option.substring(0, index);
145             String value = option.substring(index + 1);
146             in = vm.setFlag(flag, value);
147         } else {
148             char c = option.charAt(0);
149             switch (c) {
150                 case '+':
151                     flag = option.substring(1);
152                     in = vm.setFlag(flag, "1");
153                     break;
154                 case '-':
155                     flag = option.substring(1);
156                     in = vm.setFlag(flag, "0");
157                     break;
158                 default:
159                     flag = option;
160                     in = vm.printFlag(flag);
161                     break;
162             }
163         }
164 
165         drain(vm, in);
166     }
167 
flags(String pid)168     private static void flags(String pid) throws IOException {
169         HotSpotVirtualMachine vm = (HotSpotVirtualMachine) attach(pid);
170         InputStream in = vm.executeJCmd("VM.flags");
171         System.out.println("VM Flags:");
172         drain(vm, in);
173     }
174 
commandLine(String pid)175     private static void commandLine(String pid) throws IOException {
176         HotSpotVirtualMachine vm = (HotSpotVirtualMachine) attach(pid);
177         InputStream in = vm.executeJCmd("VM.command_line");
178         drain(vm, in);
179     }
180 
sysprops(String pid)181     private static void sysprops(String pid) throws IOException {
182         HotSpotVirtualMachine vm = (HotSpotVirtualMachine) attach(pid);
183         InputStream in = vm.executeJCmd("VM.system_properties");
184         System.out.println("Java System Properties:");
185         drain(vm, in);
186     }
187 
188     // Attach to <pid>, exiting if we fail to attach
attach(String pid)189     private static VirtualMachine attach(String pid) {
190         try {
191             return VirtualMachine.attach(pid);
192         } catch (Exception x) {
193             String msg = x.getMessage();
194             if (msg != null) {
195                 System.err.println(pid + ": " + msg);
196             } else {
197                 x.printStackTrace();
198             }
199             System.exit(1);
200             return null; // keep compiler happy
201         }
202     }
203 
204     // Read the stream from the target VM until EOF, then detach
drain(VirtualMachine vm, InputStream in)205     private static void drain(VirtualMachine vm, InputStream in) throws IOException {
206         // read to EOF and just print output
207         byte b[] = new byte[256];
208         int n;
209         do {
210             n = in.read(b);
211             if (n > 0) {
212                 String s = new String(b, 0, n, "UTF-8");
213                 System.out.print(s);
214             }
215         } while (n > 0);
216         in.close();
217         vm.detach();
218     }
219 
checkForUnsupportedOptions(String[] args)220     private static void checkForUnsupportedOptions(String[] args) {
221         // Check arguments for -F, and non-numeric value
222         // and warn the user that SA is not supported anymore
223         int maxCount = 1;
224         int paramCount = 0;
225 
226         for (String s : args) {
227             if (s.equals("-F")) {
228                 SAOptionError("-F option used");
229             }
230             if (s.equals("-flag")) {
231                 maxCount = 2;
232             }
233             if (! s.startsWith("-")) {
234                 paramCount += 1;
235             }
236         }
237 
238         if (paramCount > maxCount) {
239             SAOptionError("More than " + maxCount + " non-option argument");
240         }
241     }
242 
SAOptionError(String msg)243     private static void SAOptionError(String msg) {
244         System.err.println("Error: " + msg);
245         System.err.println("Cannot connect to core dump or remote debug server. Use jhsdb jinfo instead");
246         System.exit(1);
247     }
248 
249      // print usage message
usage(int exit)250     private static void usage(int exit) {
251         System.err.println("Usage:");
252         System.err.println("    jinfo <option> <pid>");
253         System.err.println("       (to connect to a running process)");
254         System.err.println("");
255         System.err.println("where <option> is one of:");
256         System.err.println("    -flag <name>         to print the value of the named VM flag");
257         System.err.println("    -flag [+|-]<name>    to enable or disable the named VM flag");
258         System.err.println("    -flag <name>=<value> to set the named VM flag to the given value");
259         System.err.println("    -flags               to print VM flags");
260         System.err.println("    -sysprops            to print Java system properties");
261         System.err.println("    <no option>          to print both VM flags and system properties");
262         System.err.println("    -? | -h | --help | -help to print this help message");
263         System.exit(exit);
264     }
265 }
266