GetObjectLockCount.java revision 10049:73443d24e529
16627Sjkh/* 26627Sjkh * Copyright (c) 2014 SAP SE. All rights reserved. 36627Sjkh * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 46627Sjkh * 56627Sjkh * This code is free software; you can redistribute it and/or modify it 66627Sjkh * under the terms of the GNU General Public License version 2 only, as 76627Sjkh * published by the Free Software Foundation. 86627Sjkh * 96627Sjkh * This code is distributed in the hope that it will be useful, but WITHOUT 106627Sjkh * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 116627Sjkh * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 126627Sjkh * version 2 for more details (a copy is included in the LICENSE file that 136627Sjkh * accompanied this code). 1489612Smpp * 156627Sjkh * You should have received a copy of the GNU General Public License version 166627Sjkh * 2 along with this work; if not, write to the Free Software Foundation, 176627Sjkh * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 186627Sjkh * 196627Sjkh * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 206627Sjkh * or visit www.oracle.com if you need additional information or have any 216627Sjkh * questions. 226627Sjkh */ 236627Sjkh 246627Sjkhimport java.io.BufferedReader; 256627Sjkhimport java.io.IOException; 266627Sjkhimport java.io.InputStream; 2750476Speterimport java.io.InputStreamReader; 286627Sjkhimport java.util.Iterator; 29177292Sbruefferimport java.util.List; 30203692Sgavinimport java.util.Map; 3179538Sru 326627Sjkhimport com.sun.jdi.AbsentInformationException; 336627Sjkhimport com.sun.jdi.Bootstrap; 346627Sjkhimport com.sun.jdi.LocalVariable; 356627Sjkhimport com.sun.jdi.Location; 36177292Sbruefferimport com.sun.jdi.ObjectReference; 3784877Syokotaimport com.sun.jdi.ReferenceType; 3884877Syokotaimport com.sun.jdi.StackFrame; 3984877Syokotaimport com.sun.jdi.ThreadReference; 4084877Syokotaimport com.sun.jdi.Value; 4184877Syokotaimport com.sun.jdi.VirtualMachine; 426627Sjkhimport com.sun.jdi.connect.Connector; 436627Sjkhimport com.sun.jdi.connect.Connector.Argument; 4468962Sruimport com.sun.jdi.connect.IllegalConnectorArgumentsException; 456627Sjkhimport com.sun.jdi.connect.LaunchingConnector; 46131530Sruimport com.sun.jdi.connect.VMStartException; 47131530Sruimport com.sun.jdi.event.BreakpointEvent; 486627Sjkhimport com.sun.jdi.event.ClassPrepareEvent; 496627Sjkhimport com.sun.jdi.event.Event; 5015128Smppimport com.sun.jdi.event.EventQueue; 5115128Smppimport com.sun.jdi.event.EventSet; 5281622Sruimport com.sun.jdi.event.VMDeathEvent; 5381622Sruimport com.sun.jdi.event.VMDisconnectEvent; 5481622Sruimport com.sun.jdi.event.VMStartEvent; 556627Sjkhimport com.sun.jdi.request.BreakpointRequest; 56107788Sruimport com.sun.jdi.request.ClassPrepareRequest; 5715128Smppimport com.sun.jdi.request.EventRequestManager; 586627Sjkh 5970466Sru 606627Sjkh/* 61143673Sbrueffer * @test GetObjectLockCount.java 62140561Sru * @bug 8036666 63140561Sru * @key regression 64140561Sru * @summary verify jvm returns correct lock recursion count 65140561Sru * @run compile -g RecursiveObjectLock.java 66140561Sru * @run main/othervm GetObjectLockCount 676627Sjkh * @author axel.siebenborn@sap.com 6869027Sru */ 6934504Scharnier 7034504Scharnierpublic class GetObjectLockCount { 7134504Scharnier 7234504Scharnier public static final String CLASS_NAME = "RecursiveObjectLock"; 7334504Scharnier public static final String METHOD_NAME = "breakpoint1"; 7434504Scharnier public static final String ARGUMENTS = ""; 75 76 77 /** 78 * Find a com.sun.jdi.CommandLineLaunch connector 79 */ 80 static LaunchingConnector findLaunchingConnector() { 81 List <Connector> connectors = Bootstrap.virtualMachineManager().allConnectors(); 82 Iterator <Connector> iter = connectors.iterator(); 83 while (iter.hasNext()) { 84 Connector connector = iter.next(); 85 if (connector.name().equals("com.sun.jdi.CommandLineLaunch")) { 86 return (LaunchingConnector)connector; 87 } 88 } 89 throw new Error("No launching connector"); 90 } 91 92 static VirtualMachine launchTarget(String mainArgs) { 93 LaunchingConnector connector = findLaunchingConnector(); 94 Map<String, Argument> arguments = connectorArguments(connector, mainArgs); 95 try { 96 return (VirtualMachine) connector.launch(arguments); 97 } catch (IOException exc) { 98 throw new Error("Unable to launch target VM: " + exc); 99 } catch (IllegalConnectorArgumentsException exc) { 100 throw new Error("Internal error: " + exc); 101 } catch (VMStartException exc) { 102 throw new Error("Target VM failed to initialize: " + 103 exc.getMessage()); 104 } 105 } 106 /** 107 * Return the launching connector's arguments. 108 */ 109 static Map <String,Connector.Argument> connectorArguments(LaunchingConnector connector, String mainArgs) { 110 Map<String,Connector.Argument> arguments = connector.defaultArguments(); 111 112 Connector.Argument mainArg = (Connector.Argument)arguments.get("main"); 113 if (mainArg == null) { 114 throw new Error("Bad launching connector"); 115 } 116 mainArg.setValue(mainArgs); 117 118 Connector.Argument optionsArg = (Connector.Argument)arguments.get("options"); 119 if (optionsArg == null) { 120 throw new Error("Bad launching connector"); 121 } 122 optionsArg.setValue(ARGUMENTS); 123 return arguments; 124 } 125 126 private static void addClassWatch(VirtualMachine vm) { 127 EventRequestManager erm = vm.eventRequestManager(); 128 ClassPrepareRequest classPrepareRequest = erm 129 .createClassPrepareRequest(); 130 classPrepareRequest.addClassFilter(CLASS_NAME); 131 classPrepareRequest.setEnabled(true); 132 } 133 134 private static void addBreakpoint(VirtualMachine vm, ReferenceType refType) { 135 Location breakpointLocation = null; 136 List<Location> locs; 137 try { 138 locs = refType.allLineLocations(); 139 for (Location loc: locs) { 140 if (loc.method().name().equals(METHOD_NAME)) { 141 breakpointLocation = loc; 142 break; 143 } 144 } 145 } catch (AbsentInformationException e) { 146 // TODO Auto-generated catch block 147 e.printStackTrace(); 148 } 149 if (breakpointLocation != null) { 150 EventRequestManager evtReqMgr = vm.eventRequestManager(); 151 BreakpointRequest bReq = evtReqMgr.createBreakpointRequest(breakpointLocation); 152 bReq.setSuspendPolicy(BreakpointRequest.SUSPEND_ALL); 153 bReq.enable(); 154 } 155 } 156 157 /** 158 * @param args 159 * @throws InterruptedException 160 */ 161 public static void main(String[] args) throws InterruptedException { 162 163 VirtualMachine vm = launchTarget(CLASS_NAME); 164 165 // process events 166 EventQueue eventQueue = vm.eventQueue(); 167 // resume the vm 168 boolean launched = false; 169 170 while (!launched) { 171 EventSet eventSet = eventQueue.remove(); 172 for (Event event : eventSet) { 173 if (event instanceof VMStartEvent) { 174 System.out.println("Vm launched"); 175 // set watch field on already loaded classes 176 List<ReferenceType> referenceTypes = vm.classesByName(CLASS_NAME); 177 for (ReferenceType refType : referenceTypes) { 178 System.out.println("Found Class"); 179 addBreakpoint(vm, refType); 180 } 181 182 // watch for loaded classes 183 addClassWatch(vm); 184 vm.resume(); 185 launched = true; 186 } 187 } 188 } 189 190 Process process = vm.process(); 191 192 // Copy target's output and error to our output and error. 193 Thread outThread = new StreamRedirectThread("out reader", process.getInputStream()); 194 Thread errThread = new StreamRedirectThread("error reader", process.getErrorStream()); 195 196 int recursionCount = -1; 197 198 errThread.start(); 199 outThread.start(); 200 boolean connected = true; 201 while (connected) { 202 EventSet eventSet = eventQueue.remove(); 203 for (Event event : eventSet) { 204 if (event instanceof VMDeathEvent || event instanceof VMDisconnectEvent) { 205 // exit 206 connected = false; 207 } 208 else if (event instanceof ClassPrepareEvent) { 209 // watch field on loaded class 210 System.out.println("ClassPrepareEvent"); 211 ClassPrepareEvent classPrepEvent = (ClassPrepareEvent) event; 212 ReferenceType refType = classPrepEvent.referenceType(); 213 addBreakpoint(vm, refType); 214 } else if (event instanceof BreakpointEvent) { 215 recursionCount = getLockRecursions(vm); 216 System.out.println("resume..."); 217 } 218 } 219 eventSet.resume(); 220 } 221 // Shutdown begins when event thread terminates 222 try { 223 errThread.join(); // Make sure output is forwarded 224 outThread.join(); 225 } catch (InterruptedException e) { 226 // we don't interrupt 227 e.printStackTrace(); 228 } 229 if (recursionCount != 3) { 230 throw new AssertionError("recursions: expected 3, but was " + recursionCount); 231 } 232 } 233 234 public static int getLockRecursions(VirtualMachine vm) { 235 List <ThreadReference> threads = vm.allThreads(); 236 for (ThreadReference thread : threads) { 237 if (thread.name().equals("main")) { 238 239 System.out.println("Found main thread."); 240 try{ 241 StackFrame frame = thread.frame(3); 242 return frame.thisObject().entryCount(); 243 } catch (Exception e) { 244 e.printStackTrace(); 245 } 246 } 247 System.out.println("Main thread not found!"); 248 } 249 return -1; 250 } 251} 252 253class StreamRedirectThread extends Thread { 254 255 private final BufferedReader in; 256 257 private static final int BUFFER_SIZE = 2048; 258 259 /** 260 * Set up for copy. 261 * @param name Name of the thread 262 * @param in Stream to copy from 263 */ 264 StreamRedirectThread(String name, InputStream in) { 265 super(name); 266 this.in = new BufferedReader(new InputStreamReader(in)); 267 } 268 269 /** 270 * Copy. 271 */ 272 public void run() { 273 try { 274 String line; 275 while ((line = in.readLine ()) != null) { 276 System.out.println("testvm: " + line); 277 } 278 System.out.flush(); 279 } catch(IOException exc) { 280 System.err.println("Child I/O Transfer - " + exc); 281 exc.printStackTrace(); 282 } 283 } 284} 285