1 /* 2 * Copyright (c) 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. 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 8193879 8193801 8129348 27 * @summary Invokes static and instance methods when debugger trace 28 * mode is on. 29 * @library /test/lib 30 * @run build TestScaffold VMConnection TargetListener TargetAdapter 31 * @run compile -g MethodInvokeWithTraceOnTest.java 32 * @run driver MethodInvokeWithTraceOnTest 33 */ 34 35 import com.sun.jdi.*; 36 import com.sun.jdi.event.*; 37 import com.sun.jdi.request.*; 38 39 import java.util.*; 40 41 import static lib.jdb.JdbTest.*; 42 43 /********** target program **********/ 44 45 class MethodInvokeWithTraceOnTestTarg { 46 public static void main(String[] args) { 47 new MethodInvokeWithTraceOnTestTarg().test(); 48 } 49 50 private void test() { 51 Thread thread = Thread.currentThread(); 52 print(thread); // @1 breakpoint 53 String str = "test"; 54 printStatic(str); // @2 breakpoint 55 56 } 57 58 public void print(Object obj) { 59 System.out.println(obj); 60 } 61 62 public static void printStatic(Object obj) { 63 System.out.println(obj); 64 } 65 66 } 67 68 69 /********** test program **********/ 70 71 public class MethodInvokeWithTraceOnTest extends TestScaffold { 72 73 MethodInvokeWithTraceOnTest(String args[]) { 74 super(args); 75 } 76 77 public static void main(String[] args) 78 throws Exception { 79 new MethodInvokeWithTraceOnTest(args).startTests(); 80 } 81 82 /********** test core **********/ 83 84 protected void runTests() throws Exception { 85 init(); 86 87 // Test with suspend policy set to SUSPEND_EVENT_THREAD 88 BreakpointEvent be = resumeToBreakpoint(true, 1); 89 System.out.println("Breakpoint 1 is hit, suspendPolicy:" + be.request().suspendPolicy()); 90 testMethods(be); 91 92 // Test with suspend policy set to SUSPEND_ALL 93 be = resumeToBreakpoint(false, 2); 94 System.out.println("Breakpoint 2 is hit, suspendPolicy:" + be.request().suspendPolicy()); 95 testMethods(be); 96 97 listenUntilVMDisconnect(); 98 } 99 100 private void init() throws Exception { 101 startToMain("MethodInvokeWithTraceOnTestTarg"); 102 vm().setDebugTraceMode(VirtualMachine.TRACE_ALL); 103 } 104 105 private BreakpointEvent resumeToBreakpoint(boolean suspendThread, int breakpointId) throws Exception { 106 int bkpLine = parseBreakpoints(getTestSourcePath("MethodInvokeWithTraceOnTest.java"), breakpointId).get(0); 107 System.out.println("Running to line: " + bkpLine); 108 return resumeTo("MethodInvokeWithTraceOnTestTarg", bkpLine, suspendThread); 109 } 110 111 private void testMethods(BreakpointEvent be) throws Exception { 112 System.out.println("Testing methods..."); 113 ThreadReference thread = be.thread(); 114 StackFrame frame = thread.frame(0); 115 ObjectReference thisObj = frame.thisObject(); 116 LocalVariable threadVar = frame.visibleVariableByName("thread"); 117 ThreadReference threadObj = (ThreadReference) frame.getValue(threadVar); 118 StringReference stringObj = vm().mirrorOf("test string"); 119 int invokeOptions = getMethodInvokeOptions(be); 120 121 testInstanceMethod1(thread, thisObj, stringObj, threadObj, invokeOptions); 122 testStaticMethod1(thread, thisObj, stringObj, threadObj, invokeOptions); 123 testStaticMethod2(thread, invokeOptions); 124 } 125 126 private void testInstanceMethod1(ThreadReference thread, ObjectReference thisObj, StringReference stringObj, 127 ThreadReference threadObj, int invokeOptions) throws Exception { 128 ClassType classType = (ClassType) thisObj.referenceType(); 129 Method printMethod = classType.methodsByName("print", 130 "(Ljava/lang/Object;)V").get(0); 131 132 System.out.println("Passing StringReference to instance method..."); 133 thisObj.invokeMethod(thread, printMethod, Collections.singletonList(stringObj), invokeOptions); 134 135 System.out.println("Passing ThreadReference to instance method..."); 136 thisObj.invokeMethod(thread, printMethod, Collections.singletonList(threadObj), invokeOptions); 137 } 138 139 private void testStaticMethod1(ThreadReference thread, ObjectReference thisObj, StringReference stringObj, 140 ThreadReference threadObj, int invokeOptions) throws Exception { 141 ClassType classType = (ClassType) thisObj.referenceType(); 142 Method printMethod = classType.methodsByName("printStatic", 143 "(Ljava/lang/Object;)V").get(0); 144 145 System.out.println("Passing StringReference to static method..."); 146 classType.invokeMethod(thread, printMethod, Collections.singletonList(stringObj), invokeOptions); 147 148 System.out.println("Passing ThreadReference to static method..."); 149 classType.invokeMethod(thread, printMethod, Collections.singletonList(threadObj), invokeOptions); 150 } 151 152 private void testStaticMethod2(ThreadReference thread, int invokeOptions) throws Exception { 153 ClassType classType = getClassType("java.lang.Class"); 154 Method forNameMethod = classType.methodsByName("forName", 155 "(Ljava/lang/String;)Ljava/lang/Class;").get(0); 156 StringReference classNameParam = vm().mirrorOf("java.lang.String"); 157 classType.invokeMethod(thread, forNameMethod, Collections.singletonList(classNameParam), invokeOptions); 158 } 159 160 private ClassType getClassType(String className) { 161 List classes = vm().classesByName(className); 162 return (ClassType) classes.get(0); 163 } 164 165 private int getMethodInvokeOptions(BreakpointEvent be) { 166 return be.request().suspendPolicy() == EventRequest.SUSPEND_EVENT_THREAD ? 167 ObjectReference.INVOKE_SINGLE_THREADED : 0; 168 } 169 }