1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *
15  *  See the License for the specific language governing permissions and
16  *  limitations under the License.
17  */
18 
19 package org.apache.harmony.jpda.tests.jdwp.share.debuggee;
20 
21 import org.apache.harmony.jpda.tests.jdwp.share.JDWPInvokeMethodWithSuspensionTestCase;
22 import org.apache.harmony.jpda.tests.share.JPDADebuggeeSynchronizer;
23 import org.apache.harmony.jpda.tests.share.SyncDebuggee;
24 
25 /**
26  * Debuggee for subclasses of {@link JDWPInvokeMethodWithSuspensionTestCase}.
27  */
28 public class InvokeMethodWithSuspensionDebuggee extends SyncDebuggee {
29     // Information for the test.
30     public static final String STATIC_METHOD_NAME = "invokedStaticMethod";
31     public static final String INSTANCE_METHOD_NAME = "invokedInstanceMethod";
32     public static final String BREAKPOINT_EVENT_THREAD_METHOD_NAME = "breakpointEventThread";
33     public static final String BREAKPOINT_ALL_THREADS_METHOD_NAME = "breakpointAllThreads";
34 
35     private static volatile boolean testThreadFinished = false;
36     private static Thread testThread = null;
37     private static boolean enableThreadSuspensionForTesting = false;
38 
39     private class TestThread extends Thread {
TestThread()40         public TestThread() {
41             super("TestThread");
42         }
43 
44         @Override
run()45         public void run() {
46             logWriter.println("TestThread starts");
47 
48             // We're going to suspend all threads in the method below.
49             logWriter.println("Breakpoint for event thread #2");
50             breakpointAllThreads();
51 
52             // The test needs to resume us so the invoke in progress in event thread #1 can
53             // complete.
54             testThreadFinished = true;
55 
56             logWriter.println("TestThread ends");
57         }
58     }
59 
60     // Invoked to suspend main thread (event thread #1) on a breakpoint.
breakpointEventThread()61     public void breakpointEventThread() {
62     }
63 
64     // Invoked to suspend test thread (event thread #2) and all others threads on a breakpoint.
breakpointAllThreads()65     public void breakpointAllThreads() {
66     }
67 
68     // Invoked in event thread #1. This will unblock event thread #2 that will suspend all threads
69     // including event thread #1. This helps us check that the debugger is not blocked waiting for
70     // this invoke.
causeEventThreadSuspension()71     private static void causeEventThreadSuspension() {
72         if (enableThreadSuspensionForTesting) {
73             // Start event thread #2. It's going to hit a breakpoint and suspend us.
74             testThread.start();
75 
76             // We don't use wait/notify pattern to be sure our loop is active.
77             while (!testThreadFinished) {
78                 try {
79                     Thread.sleep(100);
80                 } catch (InterruptedException e) {
81                     e.printStackTrace();
82                 }
83             }
84         }
85     }
86 
87     // Static method to test ClassType.InvokeMethod.
invokedStaticMethod()88     public static void invokedStaticMethod() {
89         causeEventThreadSuspension();
90     }
91 
92     // Constructor to test ClassType.NewInstance.
InvokeMethodWithSuspensionDebuggee()93     public InvokeMethodWithSuspensionDebuggee() {
94         causeEventThreadSuspension();
95     }
96 
97     // Instance method to test ObjectReference.InvokeMethod.
invokedInstanceMethod()98     public void invokedInstanceMethod() {
99         causeEventThreadSuspension();
100     }
101 
102     @Override
run()103     public void run() {
104         logWriter.println("InvokeMethodWithThreadSuspensionDebuggee starts");
105 
106         synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_READY);
107 
108         // Create test thread but do not start it now. It will be started by the invoke from
109         // the test through JDWP.
110         testThread = new TestThread();
111 
112         synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE);
113 
114         enableThreadSuspensionForTesting = true;
115 
116         // We want to suspend the main thread on a breakpoint.
117         logWriter.println("Breakpoint for event thread #1");
118         breakpointEventThread();
119 
120         // Ensure tested thread is finished.
121         try {
122             testThread.join();
123         } catch (InterruptedException e) {
124             logWriter.printError("Failed to join tested thread", e);
125         }
126         testThread = null;
127 
128         logWriter.println("InvokeMethodWithThreadSuspensionDebuggee ends");
129     }
130 
main(String[] args)131     public static void main(String[] args) {
132         runDebuggee(InvokeMethodWithSuspensionDebuggee.class);
133     }
134 }
135