1 /* 2 * Copyright (c) 2007, 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 * 29 * @author jjh 30 * 31 * @run build TestScaffold VMConnection TargetListener TargetAdapter 32 * @run compile -g PopAndInvokeTest.java 33 * @run main PopAndInvokeTest 34 */ 35 import com.sun.jdi.*; 36 import com.sun.jdi.event.*; 37 import java.util.*; 38 39 class PopAndInvokeTarg { 40 static boolean waiting = false; 41 42 public static void A() { 43 System.out.println(" debuggee: in A"); 44 } 45 46 public static void invokeee() { 47 System.out.println(" debuggee: invokee"); 48 } 49 50 public static void waiter() { 51 if (waiting) { 52 return; 53 } 54 waiting = true; 55 System.out.println(" debuggee: in waiter"); 56 while (true) { 57 } 58 } 59 60 public static void main(String[] args) { 61 System.out.println(" debuggee: Howdy!"); 62 /* 63 * Debugger will bkpt in A, popFrames back to here 64 * and then do an invokeMethod on invokeee. 65 * This should work. 66 */ 67 A(); 68 69 /* 70 * Debugger will resume and we will enter 71 * waiter(). Debugger will then do a suspend, 72 * a popFrames back to here, and an invoke 73 * which should fail. 74 */ 75 waiter(); 76 System.out.println(" debuggee: Goodbye from PopAndInvokeTarg!"); 77 } 78 } 79 80 81 /********** test program **********/ 82 83 public class PopAndInvokeTest extends TestScaffold { 84 ClassType targetClass; 85 ThreadReference mainThread; 86 87 PopAndInvokeTest (String args[]) { 88 super(args); 89 } 90 91 public static void main(String[] args) throws Exception { 92 new PopAndInvokeTest(args).startTests(); 93 } 94 95 StackFrame frameFor(String methodName) throws Exception { 96 Iterator it = mainThread.frames().iterator(); 97 98 while (it.hasNext()) { 99 StackFrame frame = (StackFrame)it.next(); 100 if (frame.location().method().name().equals(methodName)) { 101 return frame; 102 } 103 } 104 failure("FAIL: " + methodName + " not on stack"); 105 return null; 106 } 107 108 /********** test core **********/ 109 110 protected void runTests() throws Exception { 111 /* 112 * Get to the top of main() 113 * to determine targetClass and mainThread 114 */ 115 runOnce(); 116 } 117 118 void runOnce() throws Exception { 119 120 BreakpointEvent bpe = startTo("PopAndInvokeTarg", "A", "()V"); 121 targetClass = (ClassType)bpe.location().declaringType(); 122 mainThread = bpe.thread(); 123 124 /* 125 * Verify that an invokeMethod works ok after a popFrames 126 * in a thread suspended by an event. 127 */ 128 mainThread.popFrames(frameFor("A")); 129 130 System.out.println("Debugger: Popped back to the call to A()"); 131 System.out.println("Debugger: Doing invoke"); 132 133 Method invokeeeMethod = (Method)targetClass.methodsByName("invokeee").get(0); 134 try { 135 targetClass.invokeMethod(mainThread, invokeeeMethod, 136 new ArrayList(), 0); 137 } catch (Exception ex) { 138 failure("failure: invoke got unexpected exception: " + ex); 139 ex.printStackTrace(); 140 } 141 System.out.println("Debugger: invoke done"); 142 143 /* 144 * Verify that an invokeMethod gets an IncompatibleThreadStateException 145 * after a popFrames in a thread that is _not_ suspended by an event. 146 */ 147 System.out.println("Debugger: Resuming debuggee"); 148 vm().resume(); 149 150 Field waiting = targetClass.fieldByName("waiting"); 151 while (true) { 152 // Wait until debuggee enters the 'waiting' method. 153 BooleanValue bv= (BooleanValue)targetClass.getValue(waiting); 154 if (!bv.value()) { 155 try { 156 Thread.sleep(10); 157 } catch (InterruptedException ee) { 158 } 159 continue; 160 } 161 162 // debuggee has entered the waiting method 163 System.out.println("Debugger: Suspending debuggee"); 164 vm().suspend(); 165 System.out.println("Debugger: Popping frame for waiter"); 166 mainThread.popFrames(frameFor("waiter")); 167 System.out.println("Debugger: Invoking method"); 168 try { 169 targetClass.invokeMethod(mainThread, invokeeeMethod, 170 new ArrayList(), 0); 171 } catch (IncompatibleThreadStateException ee) { 172 System.out.println("Debugger: Success: Got expected IncompatibleThreadStateException"); 173 break; 174 } catch (Exception ee) { 175 failure("FAIL: Got unexpected exception: " + ee); 176 break; 177 } 178 failure("FAIL: Did not get IncompatibleThreadStateException " + 179 "when debuggee is not suspended by an event"); 180 } 181 listenUntilVMDisconnect(); 182 if (testFailed) { 183 throw new Exception("PopAndInvokeTest failed"); 184 } 185 System.out.println("Passed:"); 186 } 187 }