1 /*
2  * Copyright (c) 2007, 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 package nsk.jvmti.ForceEarlyReturn;
24 
25 import java.io.*;
26 import java.lang.reflect.*;
27 import nsk.share.Wicket;
28 import nsk.share.Consts;
29 
30 interface IA {}
31 interface IB extends IA {}
32 interface IC {}
33 class A implements IA {}
34 class B extends A implements IB, IC {}
35 
36 class EarlyReturnThread002 extends Thread {
37     public volatile int state = Consts.TEST_PASSED;
38     public volatile boolean earlyReturned = true;
39     public volatile boolean stop = false;
40     public volatile Object result = null;
41 
42     private boolean complain = true;
43     private PrintStream out = System.out;
44 
45     public Wicket startingBarrier = new Wicket();
46     public Object barrier = new Object();
47 
48     private Method methodToExecute;
49 
stopThread()50     public void stopThread() {
51         stop = true;
52     }
53 
54 
EarlyReturnThread002( Method _method , PrintStream _out )55     public EarlyReturnThread002 (
56             Method _method
57             , PrintStream _out
58             )
59     {
60         methodToExecute = _method;
61         out = _out;
62     }
63 
setEarlyReturnedStatus(boolean status)64     public void setEarlyReturnedStatus(boolean status) {
65         earlyReturned = status;
66     }
67 
run()68     public void run() {
69         try {
70             out.println("run(): before method invoke");
71             out.println("Method name: "+methodToExecute.getName());
72             result = methodToExecute.invoke(this);
73             out.println("run(): after method invoke");
74         }
75         catch (Throwable e) {
76             out.println(e.getClass().getName()+": "+e.getMessage());
77             state = Consts.TEST_FAILED;
78         }
79     }
80 
checkResults()81     public void checkResults() {
82         if (earlyReturned) {
83             out.println("TEST FAILED: a tested frame wasn't returned");
84             state = Consts.TEST_FAILED;
85             complain = false;
86         }
87     }
88 
method1()89     public Object method1 () {
90         synchronized(barrier) {
91             out.println("Actually invoked method1");
92             startingBarrier.unlock();
93         }
94 
95         // loop until the main thread forces early return
96         int i = 0; int n = 1000;
97         while (!stop) {
98             if (n <= 0) { n = 1000; }
99             if (i > n) { i = 0; n--; }
100             i++;
101         }
102 
103         checkResults();
104         return new Object();
105     }
106 
method2()107     public A method2 () {
108         synchronized(barrier) {
109             out.println("Actually invoked method2");
110             startingBarrier.unlock();
111         }
112 
113         // loop until the main thread forces early return
114         int i = 0; int n = 1000;
115         while (!stop) {
116             if (n <= 0) { n = 1000; }
117             if (i > n) { i = 0; n--; }
118             i++;
119         }
120 
121         checkResults();
122         return new A();
123     }
method3()124     public B method3 () {
125         synchronized(barrier) {
126             out.println("Actually invoked method3");
127             startingBarrier.unlock();
128         }
129 
130         // loop until the main thread forces early return
131         int i = 0; int n = 1000;
132         while (!stop) {
133             if (n <= 0) { n = 1000; }
134             if (i > n) { i = 0; n--; }
135             i++;
136         }
137 
138         checkResults();
139         return new B();
140     }
method4()141     public IA method4 () {
142         synchronized(barrier) {
143             out.println("Actually invoked method4");
144             startingBarrier.unlock();
145         }
146 
147         // loop until the main thread forces early return
148         int i = 0; int n = 1000;
149         while (!stop) {
150             if (n <= 0) { n = 1000; }
151             if (i > n) { i = 0; n--; }
152             i++;
153         }
154 
155         checkResults();
156         return new A();
157     }
method5()158     public IB method5 () {
159         synchronized(barrier) {
160             out.println("Actually invoked method5");
161             startingBarrier.unlock();
162         }
163 
164         // loop until the main thread forces early return
165         int i = 0; int n = 1000;
166         while (!stop) {
167             if (n <= 0) { n = 1000; }
168             if (i > n) { i = 0; n--; }
169             i++;
170         }
171 
172         checkResults();
173         return new B();
174     }
method6()175     public IC method6 () {
176         synchronized(barrier) {
177             out.println("Actually invoked method6");
178             startingBarrier.unlock();
179         }
180 
181         // loop until the main thread forces early return
182         int i = 0; int n = 1000;
183         while (!stop) {
184             if (n <= 0) { n = 1000; }
185             if (i > n) { i = 0; n--; }
186             i++;
187         }
188 
189         checkResults();
190         return new B();
191     }
method7()192     public Object[] method7 () {
193         synchronized(barrier) {
194             out.println("Actually invoked method7");
195             startingBarrier.unlock();
196         }
197 
198         // loop until the main thread forces early return
199         int i = 0; int n = 1000;
200         while (!stop) {
201             if (n <= 0) { n = 1000; }
202             if (i > n) { i = 0; n--; }
203             i++;
204         }
205 
206         checkResults();
207         return new A[0];
208     }
method8()209     public Object[][] method8 () {
210         synchronized(barrier) {
211             out.println("Actually invoked method8");
212             startingBarrier.unlock();
213         }
214 
215         // loop until the main thread forces early return
216         int i = 0; int n = 1000;
217         while (!stop) {
218             if (n <= 0) { n = 1000; }
219             if (i > n) { i = 0; n--; }
220             i++;
221         }
222 
223         checkResults();
224         return new B[0][0];
225     }
226 
method9()227     public IC[] method9 () {
228         synchronized(barrier) {
229             out.println("Actually invoked method9");
230             startingBarrier.unlock();
231         }
232 
233         // loop until the main thread forces early return
234         int i = 0; int n = 1000;
235         while (!stop) {
236             if (n <= 0) { n = 1000; }
237             if (i > n) { i = 0; n--; }
238             i++;
239         }
240 
241         checkResults();
242         return new B[0];
243     }
244 
method10()245     public IC[][] method10 () {
246         synchronized(barrier) {
247             out.println("Actually invoked method10");
248             startingBarrier.unlock();
249         }
250 
251         // loop until the main thread forces early return
252         int i = 0; int n = 1000;
253         while (!stop) {
254             if (n <= 0) { n = 1000; }
255             if (i > n) { i = 0; n--; }
256             i++;
257         }
258 
259         checkResults();
260         return new B[0][0];
261     }
262 
method11()263     public int[] method11 () {
264         synchronized(barrier) {
265             out.println("Actually invoked method11");
266             startingBarrier.unlock();
267         }
268 
269         // loop until the main thread forces early return
270         int i = 0; int n = 1000;
271         while (!stop) {
272             if (n <= 0) { n = 1000; }
273             if (i > n) { i = 0; n--; }
274             i++;
275         }
276 
277         checkResults();
278         return new int[0];
279     }
method12()280     public int[][] method12 () {
281         synchronized(barrier) {
282             out.println("Actually invoked method12");
283             startingBarrier.unlock();
284         }
285 
286         // loop until the main thread forces early return
287         int i = 0; int n = 1000;
288         while (!stop) {
289             if (n <= 0) { n = 1000; }
290             if (i > n) { i = 0; n--; }
291             i++;
292         }
293 
294         checkResults();
295         return new int[0][0];
296     }
method13()297     public A[] method13 () {
298         synchronized(barrier) {
299             out.println("Actually invoked method13");
300             startingBarrier.unlock();
301         }
302 
303         // loop until the main thread forces early return
304         int i = 0; int n = 1000;
305         while (!stop) {
306             if (n <= 0) { n = 1000; }
307             if (i > n) { i = 0; n--; }
308             i++;
309         }
310 
311         checkResults();
312         return new B[0];
313     }
method14()314     public A[][] method14 () {
315         synchronized(barrier) {
316             out.println("Actually invoked method14");
317             startingBarrier.unlock();
318         }
319 
320         // loop until the main thread forces early return
321         int i = 0; int n = 1000;
322         while (!stop) {
323             if (n <= 0) { n = 1000; }
324             if (i > n) { i = 0; n--; }
325             i++;
326         }
327 
328         checkResults();
329         return new B[0][0];
330     }
method15()331     public B[] method15 () {
332         synchronized(barrier) {
333             out.println("Actually invoked method15");
334             startingBarrier.unlock();
335         }
336 
337         // loop until the main thread forces early return
338         int i = 0; int n = 1000;
339         while (!stop) {
340             if (n <= 0) { n = 1000; }
341             if (i > n) { i = 0; n--; }
342             i++;
343         }
344 
345         checkResults();
346         return new B[0];
347     }
method16()348     public B[][] method16 () {
349         synchronized(barrier) {
350             out.println("Actually invoked method16");
351             startingBarrier.unlock();
352         }
353 
354         // loop until the main thread forces early return
355         int i = 0; int n = 1000;
356         while (!stop) {
357             if (n <= 0) { n = 1000; }
358             if (i > n) { i = 0; n--; }
359             i++;
360         }
361 
362         checkResults();
363         return new B[0][0];
364     }
method17()365     public IA[] method17 () {
366         synchronized(barrier) {
367             out.println("Actually invoked method17");
368             startingBarrier.unlock();
369         }
370 
371         // loop until the main thread forces early return
372         int i = 0; int n = 1000;
373         while (!stop) {
374             if (n <= 0) { n = 1000; }
375             if (i > n) { i = 0; n--; }
376             i++;
377         }
378 
379         checkResults();
380         return new B[0];
381     }
method18()382     public IA[][] method18 () {
383         synchronized(barrier) {
384             out.println("Actually invoked method18");
385             startingBarrier.unlock();
386         }
387 
388         // loop until the main thread forces early return
389         int i = 0; int n = 1000;
390         while (!stop) {
391             if (n <= 0) { n = 1000; }
392             if (i > n) { i = 0; n--; }
393             i++;
394         }
395 
396         checkResults();
397         return new A[0][0];
398     }
method19()399     public IB[] method19 () {
400         synchronized(barrier) {
401             out.println("Actually invoked method19");
402             startingBarrier.unlock();
403         }
404 
405         // loop until the main thread forces early return
406         int i = 0; int n = 1000;
407         while (!stop) {
408             if (n <= 0) { n = 1000; }
409             if (i > n) { i = 0; n--; }
410             i++;
411         }
412 
413         checkResults();
414         return new B[0];
415     }
method20()416     public IB[][] method20 () {
417         synchronized(barrier) {
418             out.println("Actually invoked method20");
419             startingBarrier.unlock();
420         }
421 
422         // loop until the main thread forces early return
423         int i = 0; int n = 1000;
424         while (!stop) {
425             if (n <= 0) { n = 1000; }
426             if (i > n) { i = 0; n--; }
427             i++;
428         }
429 
430         checkResults();
431         return new B[0][0];
432     }
433 }
434 
435 public class ForceEarlyReturn002 {
436     private PrintStream out;
437 
runIt(String argv[], PrintStream _out)438     private int runIt(String argv[], PrintStream _out) {
439         out = _out;
440 
441         Object[] params = {
442                 new Object()
443                 , new A()
444                 , new B()
445                 , new Object[1]
446                 , new Object[1][1]
447                 , new int[1]
448                 , new int[1][1]
449                 , new A[1]
450                 , new A[1][1]
451                 , new B[1]
452                 , new B[1][1]
453         };
454 
455         for (Method method : EarlyReturnThread002.class.getMethods()) {
456             if (!method.getName().startsWith("method"))
457                 continue;
458 
459             for (Object param : params) {
460                 out.println("\nITERATION:\n");
461                 out.println("\tOriginal return type: \""+method.getReturnType().getName()+"\"");
462                 out.println("\t  Forced return type: \""+param.getClass().getName()+"\"\n");
463 
464 
465                 EarlyReturnThread002 thread = new EarlyReturnThread002(method, out);
466 
467                 thread.start();
468                 thread.startingBarrier.waitFor();
469 
470                 synchronized(thread.barrier) {
471                 }
472 
473                 out.println("Suspending thread...");
474                 if (!ForceEarlyReturn001.suspendThread(thread)) {
475                     out.println("Failed to suspend the thread.");
476                     return Consts.TEST_FAILED;
477                 }
478                 out.println("Thread is suspended.\n");
479 
480                 out.println("Repeatedly suspending the thread...");
481                 if (ForceEarlyReturn001.suspendThread(thread)) {
482                     out.println("Repeatedly suspended the thread.\n");
483                     return Consts.TEST_FAILED;
484                 }
485                 out.println("Thread is already suspended.\n");
486 
487                 out.println("Forcing thread to early return...");
488                 boolean result = ForceEarlyReturn001.doForceEarlyReturnObject(thread, param);
489                 boolean isAssignable = method.getReturnType().isAssignableFrom(param.getClass());
490 
491                 if (result) {
492                     out.println("Force early return SUCCEEDED.\n");
493                 } else {
494                     out.println("FAILED to force thread to early return.\n");
495                 }
496 
497                 // In case ForceEarlyReturn invocation failed, a thread being
498                 // modified should know about that when it analyses its status
499                 thread.setEarlyReturnedStatus(result);
500 
501                 thread.stopThread();
502 
503                 out.println("Resuming thread...");
504                 if (!ForceEarlyReturn001.resumeThread(thread)) {
505                     out.println("Failed to resume thread.");
506                     return Consts.TEST_FAILED;
507                 }
508                 out.println("Thread is resumed.\n");
509 
510                 try {
511                     thread.join();
512                 } catch (InterruptedException e) {
513                     out.println("TEST INCOMPLETE: caught " + e);
514                     return Consts.TEST_FAILED;
515                 }
516                 out.println("  Original return type: \""+method.getReturnType().getName()+"\"");
517                 out.println("Actually returned type: \""
518                         +(thread.result !=null ? thread.result.getClass().getName() : "null") +"\"\n");
519                 out.println(param.getClass().getName() + (isAssignable ? " => " : " <> ") + method.getReturnType().getName());
520 
521                 if (result ^ isAssignable) {
522                     return Consts.TEST_FAILED;
523                 }
524 
525                 if (thread.state != Consts.TEST_PASSED) {
526                     out.println("Thread execution failed.");
527                     return Consts.TEST_FAILED;
528                 }
529             }
530         }
531 
532         return Consts.TEST_PASSED;
533     }
534 
535     /* */
run(String argv[], PrintStream out)536     public static int run(String argv[], PrintStream out) {
537         if (new ForceEarlyReturn002().runIt(argv, out) == Consts.TEST_PASSED) {
538             out.println("TEST PASSED");
539             return Consts.TEST_PASSED;
540         } else {
541             out.println("TEST FAILED");
542             return Consts.TEST_FAILED;
543         }
544     }
545 
546     /* */
main(String[] argv)547     public static void main(String[] argv) {
548         argv = nsk.share.jvmti.JVMTITest.commonInit(argv);
549 
550         System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE);
551     }
552 }
553