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