1 /* 2 * Copyright (c) 2007, 2015, 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. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /** 25 * @test 26 * @bug 6517249 27 * @summary JDWP: Cannot do an invokeMethod after a popFrames operation 28 * @author jjh 29 * 30 * @ignore 6951287 31 * 32 * @run build TestScaffold VMConnection TargetListener TargetAdapter 33 * @run compile -g PopAndInvokeTest.java 34 * @run driver PopAndInvokeTest 35 */ 36 import com.sun.jdi.*; 37 import com.sun.jdi.event.*; 38 import java.util.*; 39 40 class PopAndInvokeTarg { 41 static boolean waiting = false; 42 43 public static void A() { 44 System.out.println(" debuggee: in A"); 45 } 46 47 public static void invokeee() { 48 System.out.println(" debuggee: invokee"); 49 } 50 51 public static void waiter() { 52 if (waiting) { 53 return; 54 } 55 waiting = true; 56 System.out.println(" debuggee: in waiter"); 57 while (true) { 58 } 59 } 60 61 public static void main(String[] args) { 62 System.out.println(" debuggee: Howdy!"); 63 /* 64 * Debugger will bkpt in A, popFrames back to here 65 * and then do an invokeMethod on invokeee. 66 * This should work. 67 */ 68 A(); 69 70 /* 71 * Debugger will resume and we will enter 72 * waiter(). Debugger will then do a suspend, 73 * a popFrames back to here, and an invoke 74 * which should fail. 75 */ 76 waiter(); 77 System.out.println(" debuggee: Goodbye from PopAndInvokeTarg!"); 78 } 79 } 80 81 82 /********** test program **********/ 83 84 public class PopAndInvokeTest extends TestScaffold { 85 ClassType targetClass; 86 ThreadReference mainThread; 87 88 PopAndInvokeTest (String args[]) { 89 super(args); 90 } 91 92 public static void main(String[] args) throws Exception { 93 new PopAndInvokeTest(args).startTests(); 94 } 95 96 StackFrame frameFor(String methodName) throws Exception { 97 Iterator it = mainThread.frames().iterator(); 98 99 while (it.hasNext()) { 100 StackFrame frame = (StackFrame)it.next(); 101 if (frame.location().method().name().equals(methodName)) { 102 return frame; 103 } 104 } 105 failure("FAIL: " + methodName + " not on stack"); 106 return null; 107 } 108 109 /********** test core **********/ 110 111 protected void runTests() throws Exception { 112 /* 113 * Get to the top of main() 114 * to determine targetClass and mainThread 115 */ 116 runOnce(); 117 } 118 119 void runOnce() throws Exception { 120 121 BreakpointEvent bpe = startTo("PopAndInvokeTarg", "A", "()V"); 122 targetClass = (ClassType)bpe.location().declaringType(); 123 mainThread = bpe.thread(); 124 125 /* 126 * Verify that an invokeMethod works ok after a popFrames 127 * in a thread suspended by an event. 128 */ 129 mainThread.popFrames(frameFor("A")); 130 131 System.out.println("Debugger: Popped back to the call to A()"); 132 System.out.println("Debugger: Doing invoke"); 133 134 Method invokeeeMethod = (Method)targetClass.methodsByName("invokeee").get(0); 135 try { 136 targetClass.invokeMethod(mainThread, invokeeeMethod, 137 new ArrayList(), 0); 138 } catch (Exception ex) { 139 failure("failure: invoke got unexpected exception: " + ex); 140 ex.printStackTrace(); 141 } 142 System.out.println("Debugger: invoke done"); 143 144 /* 145 * Verify that an invokeMethod gets an IncompatibleThreadStateException 146 * after a popFrames in a thread that is _not_ suspended by an event. 147 */ 148 System.out.println("Debugger: Resuming debuggee"); 149 vm().resume(); 150 151 Field waiting = targetClass.fieldByName("waiting"); 152 while (true) { 153 // Wait until debuggee enters the 'waiting' method. 154 BooleanValue bv= (BooleanValue)targetClass.getValue(waiting); 155 if (!bv.value()) { 156 try { 157 Thread.sleep(10); 158 } catch (InterruptedException ee) { 159 } 160 continue; 161 } 162 163 // debuggee has entered the waiting method 164 System.out.println("Debugger: Suspending debuggee"); 165 vm().suspend(); 166 System.out.println("Debugger: Popping frame for waiter"); 167 mainThread.popFrames(frameFor("waiter")); 168 System.out.println("Debugger: Invoking method"); 169 try { 170 targetClass.invokeMethod(mainThread, invokeeeMethod, 171 new ArrayList(), 0); 172 } catch (IncompatibleThreadStateException ee) { 173 System.out.println("Debugger: Success: Got expected IncompatibleThreadStateException"); 174 break; 175 } catch (Exception ee) { 176 failure("FAIL: Got unexpected exception: " + ee); 177 break; 178 } 179 failure("FAIL: Did not get IncompatibleThreadStateException " + 180 "when debuggee is not suspended by an event"); 181 } 182 listenUntilVMDisconnect(); 183 if (testFailed) { 184 throw new Exception("PopAndInvokeTest failed"); 185 } 186 System.out.println("Passed:"); 187 } 188 }