agent/test/jdi/VMConnection.java

Mon, 28 Jul 2014 15:06:38 -0700

author
fzhinkin
date
Mon, 28 Jul 2014 15:06:38 -0700
changeset 6997
dbb05f6d93c4
parent 1907
c18cbe5936b8
child 6876
710a3c8b516e
permissions
-rw-r--r--

8051344: JVM crashed in Compile::start() during method parsing w/ UseRTMDeopt turned on
Summary: call rtm_deopt() only if there were no compilation bailouts before.
Reviewed-by: kvn

duke@435 1 /*
trims@1907 2 * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
duke@435 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@435 4 *
duke@435 5 * This code is free software; you can redistribute it and/or modify it
duke@435 6 * under the terms of the GNU General Public License version 2 only, as
duke@435 7 * published by the Free Software Foundation.
duke@435 8 *
duke@435 9 * This code is distributed in the hope that it will be useful, but WITHOUT
duke@435 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@435 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@435 12 * version 2 for more details (a copy is included in the LICENSE file that
duke@435 13 * accompanied this code).
duke@435 14 *
duke@435 15 * You should have received a copy of the GNU General Public License version
duke@435 16 * 2 along with this work; if not, write to the Free Software Foundation,
duke@435 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@435 18 *
trims@1907 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
trims@1907 20 * or visit www.oracle.com if you need additional information or have any
trims@1907 21 * questions.
duke@435 22 *
duke@435 23 */
duke@435 24
duke@435 25 import com.sun.jdi.*;
duke@435 26 import com.sun.jdi.connect.*;
duke@435 27 import com.sun.jdi.request.EventRequestManager;
duke@435 28
duke@435 29 import java.util.*;
duke@435 30 import java.io.*;
duke@435 31
duke@435 32
duke@435 33 /**
duke@435 34 * Manages a VM conection for the JDI test framework.
duke@435 35 */
duke@435 36 class VMConnection {
duke@435 37 private VirtualMachine vm;
duke@435 38 private Process process = null;
duke@435 39 private int outputCompleteCount = 0;
duke@435 40
duke@435 41 private final Connector connector;
duke@435 42 private final Map connectorArgs;
duke@435 43 private final int traceFlags;
duke@435 44
duke@435 45 /**
duke@435 46 * Return a String containing VM Options to pass to the debugee
duke@435 47 * or an empty string if there are none.
duke@435 48 * These are read from the first non-comment line
duke@435 49 * in file test/com/sun/jdi/@debuggeeVMOptions.
duke@435 50 */
duke@435 51 static public String getDebuggeeVMOptions() {
duke@435 52
duke@435 53 // When we run under jtreg, test.src contains the pathname of
duke@435 54 // the test/com/sun/jdi dir.
duke@435 55 BufferedReader reader;
duke@435 56 final String filename = "@debuggeeVMOptions";
duke@435 57 String srcDir = System.getProperty("test.src");
duke@435 58
duke@435 59 if (srcDir == null) {
duke@435 60 srcDir = System.getProperty("user.dir");
duke@435 61 }
duke@435 62 srcDir = srcDir + File.separator;
duke@435 63
duke@435 64 File myDir = new File(srcDir);
duke@435 65
duke@435 66 File myFile = new File(myDir, filename);
duke@435 67 if (!myFile.canRead()) {
duke@435 68 try {
duke@435 69 // We have some subdirs of test/com/sun/jdi so in case we
duke@435 70 // are in one of them, look in our parent dir for the file.
duke@435 71 myFile = new File(myDir.getCanonicalFile().getParent(),
duke@435 72 filename);
duke@435 73 if (!myFile.canRead()) {
duke@435 74 return "";
duke@435 75 }
duke@435 76 } catch (IOException ee) {
duke@435 77 System.out.println("-- Error 1 trying to access file " +
duke@435 78 myFile.getPath() + ": " + ee);
duke@435 79 return "";
duke@435 80 }
duke@435 81 }
duke@435 82 String wholePath = myFile.getPath();
duke@435 83 try {
duke@435 84 reader = new BufferedReader(new FileReader(myFile));
duke@435 85 } catch (FileNotFoundException ee) {
duke@435 86 System.out.println("-- Error 2 trying to access file " +
duke@435 87 wholePath + ": " + ee);
duke@435 88 return "";
duke@435 89 }
duke@435 90
duke@435 91 String line;
duke@435 92 String retVal = "";
duke@435 93 while (true) {
duke@435 94 try {
duke@435 95 line = reader.readLine();
duke@435 96 } catch (IOException ee) {
duke@435 97 System.out.println("-- Error reading options from file " +
duke@435 98 wholePath + ": " + ee);
duke@435 99 break;
duke@435 100 }
duke@435 101 if (line == null) {
duke@435 102 System.out.println("-- No debuggee VM options found in file " +
duke@435 103 wholePath);
duke@435 104 break;
duke@435 105 }
duke@435 106 line = line.trim();
duke@435 107 if (line.length() != 0 && !line.startsWith("#")) {
duke@435 108 System.out.println("-- Added debuggeeVM options from file " +
duke@435 109 wholePath + ": " + line);
duke@435 110 retVal = line;
duke@435 111 break;
duke@435 112 }
duke@435 113 // Else, read he next line.
duke@435 114 }
duke@435 115 try {
duke@435 116 reader.close();
duke@435 117 } catch (IOException ee) {
duke@435 118 }
duke@435 119 return retVal;
duke@435 120 }
duke@435 121
duke@435 122 private Connector findConnector(String name) {
duke@435 123 List connectors = Bootstrap.virtualMachineManager().allConnectors();
duke@435 124 Iterator iter = connectors.iterator();
duke@435 125 while (iter.hasNext()) {
duke@435 126 Connector connector = (Connector)iter.next();
duke@435 127 if (connector.name().equals(name)) {
duke@435 128 return connector;
duke@435 129 }
duke@435 130 }
duke@435 131 return null;
duke@435 132 }
duke@435 133
duke@435 134 private Map parseConnectorArgs(Connector connector, String argString) {
duke@435 135 StringTokenizer tokenizer = new StringTokenizer(argString, ",");
duke@435 136 Map arguments = connector.defaultArguments();
duke@435 137
duke@435 138 while (tokenizer.hasMoreTokens()) {
duke@435 139 String token = tokenizer.nextToken();
duke@435 140 int index = token.indexOf('=');
duke@435 141 if (index == -1) {
duke@435 142 throw new IllegalArgumentException("Illegal connector argument: " +
duke@435 143 token);
duke@435 144 }
duke@435 145 String name = token.substring(0, index);
duke@435 146 String value = token.substring(index + 1);
duke@435 147 Connector.Argument argument = (Connector.Argument)arguments.get(name);
duke@435 148 if (argument == null) {
duke@435 149 throw new IllegalArgumentException("Argument " + name +
duke@435 150 "is not defined for connector: " +
duke@435 151 connector.name());
duke@435 152 }
duke@435 153 argument.setValue(value);
duke@435 154 }
duke@435 155 return arguments;
duke@435 156 }
duke@435 157
duke@435 158 VMConnection(String connectSpec, int traceFlags) {
duke@435 159 String nameString;
duke@435 160 String argString;
duke@435 161 int index = connectSpec.indexOf(':');
duke@435 162 if (index == -1) {
duke@435 163 nameString = connectSpec;
duke@435 164 argString = "";
duke@435 165 } else {
duke@435 166 nameString = connectSpec.substring(0, index);
duke@435 167 argString = connectSpec.substring(index + 1);
duke@435 168 }
duke@435 169
duke@435 170 connector = findConnector(nameString);
duke@435 171 if (connector == null) {
duke@435 172 throw new IllegalArgumentException("No connector named: " +
duke@435 173 nameString);
duke@435 174 }
duke@435 175
duke@435 176 connectorArgs = parseConnectorArgs(connector, argString);
duke@435 177 this.traceFlags = traceFlags;
duke@435 178 }
duke@435 179
duke@435 180 synchronized VirtualMachine open() {
duke@435 181 if (connector instanceof LaunchingConnector) {
duke@435 182 vm = launchTarget();
duke@435 183 } else if (connector instanceof AttachingConnector) {
duke@435 184 vm = attachTarget();
duke@435 185 } else if (connector instanceof ListeningConnector) {
duke@435 186 vm = listenTarget();
duke@435 187 } else {
duke@435 188 throw new InternalError("Invalid connect type");
duke@435 189 }
duke@435 190 vm.setDebugTraceMode(traceFlags);
duke@435 191 System.out.println("JVM version:" + vm.version());
duke@435 192 System.out.println("JDI version: " + Bootstrap.virtualMachineManager().majorInterfaceVersion() +
duke@435 193 "." + Bootstrap.virtualMachineManager().minorInterfaceVersion());
duke@435 194 System.out.println("JVM description: " + vm.description());
duke@435 195
duke@435 196 return vm;
duke@435 197 }
duke@435 198
duke@435 199 boolean setConnectorArg(String name, String value) {
duke@435 200 /*
duke@435 201 * Too late if the connection already made
duke@435 202 */
duke@435 203 if (vm != null) {
duke@435 204 return false;
duke@435 205 }
duke@435 206
duke@435 207 Connector.Argument argument = (Connector.Argument)connectorArgs.get(name);
duke@435 208 if (argument == null) {
duke@435 209 return false;
duke@435 210 }
duke@435 211 argument.setValue(value);
duke@435 212 return true;
duke@435 213 }
duke@435 214
duke@435 215 String connectorArg(String name) {
duke@435 216 Connector.Argument argument = (Connector.Argument)connectorArgs.get(name);
duke@435 217 if (argument == null) {
duke@435 218 return "";
duke@435 219 }
duke@435 220 return argument.value();
duke@435 221 }
duke@435 222
duke@435 223 public synchronized VirtualMachine vm() {
duke@435 224 if (vm == null) {
duke@435 225 throw new InternalError("VM not connected");
duke@435 226 } else {
duke@435 227 return vm;
duke@435 228 }
duke@435 229 }
duke@435 230
duke@435 231 boolean isOpen() {
duke@435 232 return (vm != null);
duke@435 233 }
duke@435 234
duke@435 235 boolean isLaunch() {
duke@435 236 return (connector instanceof LaunchingConnector);
duke@435 237 }
duke@435 238
duke@435 239 Connector connector() {
duke@435 240 return connector;
duke@435 241 }
duke@435 242
duke@435 243 boolean isListen() {
duke@435 244 return (connector instanceof ListeningConnector);
duke@435 245 }
duke@435 246
duke@435 247 boolean isAttach() {
duke@435 248 return (connector instanceof AttachingConnector);
duke@435 249 }
duke@435 250
duke@435 251 private synchronized void notifyOutputComplete() {
duke@435 252 outputCompleteCount++;
duke@435 253 notifyAll();
duke@435 254 }
duke@435 255
duke@435 256 private synchronized void waitOutputComplete() {
duke@435 257 // Wait for stderr and stdout
duke@435 258 if (process != null) {
duke@435 259 while (outputCompleteCount < 2) {
duke@435 260 try {wait();} catch (InterruptedException e) {}
duke@435 261 }
duke@435 262 }
duke@435 263 }
duke@435 264
duke@435 265 public void disposeVM() {
duke@435 266 try {
duke@435 267 if (vm != null) {
duke@435 268 vm.dispose();
duke@435 269 vm = null;
duke@435 270 }
duke@435 271 } finally {
duke@435 272 if (process != null) {
duke@435 273 process.destroy();
duke@435 274 process = null;
duke@435 275 }
duke@435 276 waitOutputComplete();
duke@435 277 }
duke@435 278 }
duke@435 279
duke@435 280 private void dumpStream(InputStream stream) throws IOException {
duke@435 281 PrintStream outStream = System.out;
duke@435 282 BufferedReader in =
duke@435 283 new BufferedReader(new InputStreamReader(stream));
duke@435 284 String line;
duke@435 285 while ((line = in.readLine()) != null) {
duke@435 286 outStream.println(line);
duke@435 287 }
duke@435 288 }
duke@435 289
duke@435 290 /**
duke@435 291 * Create a Thread that will retrieve and display any output.
duke@435 292 * Needs to be high priority, else debugger may exit before
duke@435 293 * it can be displayed.
duke@435 294 */
duke@435 295 private void displayRemoteOutput(final InputStream stream) {
duke@435 296 Thread thr = new Thread("output reader") {
duke@435 297 public void run() {
duke@435 298 try {
duke@435 299 dumpStream(stream);
duke@435 300 } catch (IOException ex) {
duke@435 301 System.err.println("IOException reading output of child java interpreter:"
duke@435 302 + ex.getMessage());
duke@435 303 } finally {
duke@435 304 notifyOutputComplete();
duke@435 305 }
duke@435 306 }
duke@435 307 };
duke@435 308 thr.setPriority(Thread.MAX_PRIORITY-1);
duke@435 309 thr.start();
duke@435 310 }
duke@435 311
duke@435 312 private void dumpFailedLaunchInfo(Process process) {
duke@435 313 try {
duke@435 314 dumpStream(process.getErrorStream());
duke@435 315 dumpStream(process.getInputStream());
duke@435 316 } catch (IOException e) {
duke@435 317 System.err.println("Unable to display process output: " +
duke@435 318 e.getMessage());
duke@435 319 }
duke@435 320 }
duke@435 321
duke@435 322 /* launch child target vm */
duke@435 323 private VirtualMachine launchTarget() {
duke@435 324 LaunchingConnector launcher = (LaunchingConnector)connector;
duke@435 325 try {
duke@435 326 VirtualMachine vm = launcher.launch(connectorArgs);
duke@435 327 process = vm.process();
duke@435 328 displayRemoteOutput(process.getErrorStream());
duke@435 329 displayRemoteOutput(process.getInputStream());
duke@435 330 return vm;
duke@435 331 } catch (IOException ioe) {
duke@435 332 ioe.printStackTrace();
duke@435 333 System.err.println("\n Unable to launch target VM.");
duke@435 334 } catch (IllegalConnectorArgumentsException icae) {
duke@435 335 icae.printStackTrace();
duke@435 336 System.err.println("\n Internal debugger error.");
duke@435 337 } catch (VMStartException vmse) {
duke@435 338 System.err.println(vmse.getMessage() + "\n");
duke@435 339 dumpFailedLaunchInfo(vmse.process());
duke@435 340 System.err.println("\n Target VM failed to initialize.");
duke@435 341 }
duke@435 342 return null; // Shuts up the compiler
duke@435 343 }
duke@435 344
duke@435 345 /* attach to running target vm */
duke@435 346 private VirtualMachine attachTarget() {
duke@435 347 AttachingConnector attacher = (AttachingConnector)connector;
duke@435 348 try {
duke@435 349 return attacher.attach(connectorArgs);
duke@435 350 } catch (IOException ioe) {
duke@435 351 ioe.printStackTrace();
duke@435 352 System.err.println("\n Unable to attach to target VM.");
duke@435 353 } catch (IllegalConnectorArgumentsException icae) {
duke@435 354 icae.printStackTrace();
duke@435 355 System.err.println("\n Internal debugger error.");
duke@435 356 }
duke@435 357 return null; // Shuts up the compiler
duke@435 358 }
duke@435 359
duke@435 360 /* listen for connection from target vm */
duke@435 361 private VirtualMachine listenTarget() {
duke@435 362 ListeningConnector listener = (ListeningConnector)connector;
duke@435 363 try {
duke@435 364 String retAddress = listener.startListening(connectorArgs);
duke@435 365 System.out.println("Listening at address: " + retAddress);
duke@435 366 vm = listener.accept(connectorArgs);
duke@435 367 listener.stopListening(connectorArgs);
duke@435 368 return vm;
duke@435 369 } catch (IOException ioe) {
duke@435 370 ioe.printStackTrace();
duke@435 371 System.err.println("\n Unable to attach to target VM.");
duke@435 372 } catch (IllegalConnectorArgumentsException icae) {
duke@435 373 icae.printStackTrace();
duke@435 374 System.err.println("\n Internal debugger error.");
duke@435 375 }
duke@435 376 return null; // Shuts up the compiler
duke@435 377 }
duke@435 378 }

mercurial