1 /* 2 * Copyright (c) 1999, 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 /* 26 * @test 27 * @key stress 28 * 29 * @summary converted from VM testbase nsk/stress/except/except004. 30 * VM testbase keywords: [stress, diehard, slow, nonconcurrent, quick] 31 * VM testbase readme: 32 * DESCRIPTION 33 * This checks if various exceptions are thrown (and caught) correctly 34 * when there apparently are no free space in the heap to allocate new 35 * Throwable instance. 36 * The test tries to occupy all of memory available in the heap by allocating 37 * lots of new Object() instances. Instances of the type Object are the smallest 38 * objects, so they apparently should occupy most fine-grained fragments in the 39 * heap and leave no free space for new Throwable instance. After that, the test 40 * provokes various exceptions (e.g.: by executing integer division by 0 and so 41 * on), and checks if appropriate exceptions are thrown. 42 * COMMENTS 43 * The test needs a lot of memory to start up, so it should not run under older 44 * JDK 1.1.x release due to its poorer heap utilization. Also, some checks are 45 * skipped when testing classic VM, because OutOfMemoryError is correctly thrown 46 * instead of target exception. 47 * When the test is being self-initiating (i.e.: eating heap), memory occupation 48 * is terminated if memory allocation slows down crucially. This is a workaround 49 * intended to avoid the HotSpot bug: 50 * #4248801 (P1/S5) slow memory allocation when heap is almost exhausted 51 * There is also a workaround involved to avoid the following bugs known 52 * for HotSpot and for classic VM: 53 * #4239841 (P1/S5) 1.1: poor garbage collector performance (HotSpot bug) 54 * #4245060 (P4/S5) poor garbage collector performance (Classic VM bug) 55 * However, printing of the test's error messages, warnings, and of execution 56 * trace fails under JDK 1.2 for Win32 even so. If the test fails due to this 57 * problem, exit status 96 is returned instead of 97. 58 * JDK 1.3 classic VM for Sparc may crash (core dump) due to the known bug: 59 * #4245057 (P2/S3) VM crashes when heap is exhausted 60 * 61 * @run main/othervm -Xms50M -Xmx200M -XX:-UseGCOverheadLimit nsk.stress.except.except004 62 */ 63 64 package nsk.stress.except; 65 66 import java.io.PrintStream; 67 import java.lang.reflect.Field; 68 69 /** 70 * This checks if various exceptions are thrown (and caught) correctly 71 * when there apparently are no free space in the heap to allocate new 72 * <code>Throwable</code> instance. 73 * <p> 74 * <p>The test tries to occupy all of memory available in the heap by 75 * allocating lots of new <code>Object()</code> instances. Instances of the 76 * type <code>Object</code> are the smallest objects, so they apparently should 77 * occupy most fine-grained fragments in the heap and leave no free space for 78 * new <code>Throwable</code> instance. After that, the test provokes various 79 * exceptions (e.g.: by executing integer division by 0 and so on), and checks 80 * if appropriate exceptions are thrown. 81 * <p> 82 * <p>Note, that memory occupation is terminated if memory allocation slows 83 * down crucially. This is a workaround intended to avoid the HotSpot bug: 84 * <br> 85 * #4248801 (P1/S5) slow memory allocation when heap is almost exhausted 86 * <p> 87 * <p>There is also a workaround involved to avoid the following bugs known 88 * for HotSpot and for classic VM: 89 * <br> 90 * #4239841 (P1/S5) 1.1: poor garbage collector performance 91 * <br> 92 * #4245060 (P4/S5) poor garbage collector performance 93 * <br>However, printing of the test's error messages, warnings, and of 94 * execution trace may fail even so. If the test fails due to poor GC 95 * performance, exit status 96 is returned instead of 97. 96 * <p> 97 * <p>Also note, that the test needs a lot of memory to start up, so it should 98 * not run under older JDK 1.1.x release due to its poor heap utilization. 99 */ 100 public class except004 { 101 /** 102 * Either allow or supress printing of execution trace. 103 */ 104 private static boolean TRACE_ON = false; 105 /** 106 * Either allow or supress printing of warning messages. 107 */ 108 private static final boolean WARN_ON = true; 109 /* 110 * Storage for a lot of tiny objects 111 * "static volatile" keywords are for preventing heap optimization 112 */ 113 private static volatile Object pool[] = null; 114 /** 115 * Temporary <code>log</code> for error messages, warnings and/or execution trace. 116 * 117 * @see #messages 118 */ 119 private static String log[] = new String[1000]; // up to 1000 messages 120 /** 121 * How many <code>messages</code> were submitted to the <code>log</code>. 122 * 123 * @see #log 124 */ 125 private static int messages = 0; 126 127 /** 128 * Re-call to the method <code>run(out)</code> (ignore <code>args[]</code>), 129 * and print the test summary - either test passed of failed. 130 */ 131 public static int run(String args[], PrintStream out) { 132 if (args.length > 0) { 133 if (args[0].toLowerCase().startsWith("-v")) 134 TRACE_ON = true; 135 } 136 137 int exitCode; 138 try { 139 exitCode = run(out); 140 } finally { // ensure we have free memory for exception processing 141 pool = null; 142 System.gc(); 143 } 144 if (TRACE_ON) 145 out.println("Test completed."); 146 147 // Print the log[] and the test summary: 148 try { 149 for (int i = 0; i < messages; i++) 150 out.println(log[i]); 151 if (exitCode == 0) { 152 if (TRACE_ON) 153 out.println("Test passed."); 154 } else 155 out.println("Test failed."); 156 } catch (OutOfMemoryError oome) { 157 // Poor performance of garbage collector: 158 exitCode = 1; 159 } 160 161 return exitCode; 162 } 163 164 /** 165 * Allocate as much <code>Object</code> instances as possible to bring JVM 166 * into stress, and then check if exceptions are correctly thrown accordingly 167 * to various situations like integer division by 0, etc. 168 */ 169 private static int run(PrintStream out) { 170 out.println("# While printing this message, JVM seems to initiate the output"); 171 out.println("# stream, so that it will not need more memory to print later,"); 172 out.println("# when the heap would fail to provide more memory."); 173 out.println("# "); 174 out.println("# Note, that the test maintains especial static log[] field in"); 175 out.println("# order to avoid printing when the heap seems exhausted."); 176 out.println("# Nevertheless, printing could cause OutOfMemoryError even"); 177 out.println("# after all the memory allocated by the test is released."); 178 out.println("# "); 179 out.println("# That problem is caused by the known JDK/HotSpot bugs:"); 180 out.println("# 4239841 (P1/S5) 1.1: poor garbage collector performance"); 181 out.println("# 4245060 (P4/S5) poor garbage collector performance"); 182 out.println("# "); 183 out.println("# This message is just intended to work-around that problem."); 184 out.println("# If printing should fail even so, the test will return the"); 185 out.println("# exit status 96 instead of 97 to indicate the problem."); 186 187 // run all tests normally to ensure all needed classes are loaded and 188 // initialized before the heap is exhausted - else we may trigger OOME 189 // in unexpected places. 190 try { 191 if (TRACE_ON) 192 out.println("Running without heap exhaustion"); 193 runTests(out, false); 194 } catch (Throwable unexpected) { 195 out.println("Test pre-initialisation failed: " + unexpected); 196 return 2; 197 } 198 199 if (TRACE_ON) 200 out.println("Running with heap exhaustion"); 201 202 return runTests(out, true); 203 } 204 205 private static int runTests(PrintStream out, boolean exhaustHeap) { 206 // reset message index 207 messages = 0; 208 209 // Prepare some items, which will be used by the test: 210 Object stringArray[] = new String[1]; 211 Object integerValue = new Integer(0); 212 Object doubleValue = new Double(0); 213 Object trash = null; 214 Field abraPrivateField; 215 Field abraIntegerField; 216 Field abraBooleanField; 217 try { 218 abraPrivateField = Abra.class.getDeclaredField("DONT_TOUCH_ME"); 219 abraIntegerField = Abra.class.getDeclaredField("MAIN_CYR_NUMBER"); 220 abraBooleanField = Abra.class.getDeclaredField("NOT_AN_INTEGER"); 221 } catch (NoSuchFieldException nsfe) { 222 out.println("Test initialisation failed: field not found in class Abra"); 223 return 2; 224 } 225 226 Abra abra = new Abra("via public constructor"); 227 Abra.Cadabra cadabra = new Abra.Cadabra(); 228 // Sum up exit code: 229 int exitCode = 0; // apparently PASSED 230 int skipped = 0; // some checks may correctly suffer OutOfMemoryError 231 232 int poolSize = 0; 233 int index = 0; 234 235 if (exhaustHeap) { 236 pool = null; 237 // Allocate repository for lots of tiny objects: 238 for (int size = 1 << 30; size > 0 && pool == null; size >>= 1) { 239 try { 240 pool = new Object[size]; 241 } catch (OutOfMemoryError oome) { 242 } 243 } 244 if (pool == null) 245 throw new Error("HS bug: cannot allocate new Object[1]"); 246 poolSize = pool.length; 247 index = 0; 248 249 // Sum up time spent, when it was hard for JVM to allocate next object 250 // (i.e.: when JVM has spent more than 1 second to allocate new object): 251 double totalDelay = 0; 252 long timeMark = System.currentTimeMillis(); 253 try { 254 for (; index < poolSize; index++) { 255 //------------------------- 256 pool[index] = new Object(); 257 long nextTimeMark = System.currentTimeMillis(); 258 long elapsed = nextTimeMark - timeMark; 259 timeMark = nextTimeMark; 260 //---------------------- 261 if (elapsed > 1000) { 262 double seconds = elapsed / 1000.0; 263 if (TRACE_ON) 264 out.println( 265 "pool[" + index + "]=new Object(); // elapsed " + seconds + "s"); 266 totalDelay += seconds; 267 if (totalDelay > 60) { 268 if (TRACE_ON) 269 out.println( 270 "Memory allocation became slow; so, heap seems exhausted."); 271 break; 272 } 273 } 274 } 275 } catch (OutOfMemoryError oome) { 276 if (TRACE_ON) 277 log[messages++] = "Heap seems exhausted - OutOfMemoryError thrown."; 278 // Do not release any byte once allocated: 279 pool[index++] = oome; 280 } 281 282 if (index > poolSize - 1000) { 283 if (WARN_ON) 284 log[messages++] = "Warning: pool[] is full; so, checks would not be enough hard..."; 285 } 286 } else { 287 // pool gets used for array index tests 288 pool = new Object[3]; 289 poolSize = pool.length; 290 } 291 292 // Check ArithmeticException: 293 try { 294 int x, y, z; 295 x = y = 0; 296 z = x / y; 297 log[messages++] = "Failure: ArithmeticException"; 298 exitCode = 2; // FAILED 299 } catch (ArithmeticException ae) { 300 if (TRACE_ON) 301 log[messages++] = "Success: ArithmeticException"; 302 if (exhaustHeap) 303 pool[index++] = ae; 304 } catch (OutOfMemoryError oome) { 305 if (WARN_ON) 306 log[messages++] = "Skipped: ArithmeticException"; 307 skipped++; 308 } 309 310 // Check ArrayIndexOutOfBoundsException: 311 try { 312 pool[poolSize] = pool[0]; 313 log[messages++] = "Failure: ArrayIndexOutOfBoundsException"; 314 exitCode = 2; // FAILED 315 } catch (ArrayIndexOutOfBoundsException aioobe) { 316 if (TRACE_ON) 317 log[messages++] = "Success: ArrayIndexOutOfBoundsException"; 318 } catch (OutOfMemoryError oome) { 319 if (WARN_ON) 320 log[messages++] = "Skipped: ArrayIndexOutOfBoundsException"; 321 skipped++; 322 } 323 324 // Check ArrayStoreException: 325 try { 326 stringArray[0] = integerValue; 327 log[messages++] = "Failure: ArrayStoreException"; 328 exitCode = 2; // FAILED 329 } catch (ArrayStoreException ase) { 330 if (TRACE_ON) 331 log[messages++] = "Success: ArrayStoreException"; 332 } catch (OutOfMemoryError oome) { 333 if (WARN_ON) 334 log[messages++] = "Skipped: ArrayStoreException"; 335 skipped++; 336 } 337 338 // Check ClassCastException: 339 try { 340 trash = (Double) integerValue; 341 log[messages++] = "Failure: ClassCastException"; 342 exitCode = 2; // FAILED 343 } catch (ClassCastException cce) { 344 if (TRACE_ON) 345 log[messages++] = "Success: ClassCastException"; 346 if (exhaustHeap) 347 pool[index++] = cce; 348 } catch (OutOfMemoryError oome) { 349 if (WARN_ON) 350 log[messages++] = "Skipped: ClassCastException"; 351 skipped++; 352 } 353 354 // Check CloneNotSupportedException: 355 try { 356 trash = abra.clone(); // illegal - should fail 357 // trash = cadabra.clone(); // legal - should pass 358 log[messages++] = "Failure: CloneNotSupportedException"; 359 exitCode = 2; // FAILED 360 } catch (CloneNotSupportedException cnse) { 361 if (TRACE_ON) 362 log[messages++] = "Success: CloneNotSupportedException"; 363 } catch (OutOfMemoryError oome) { 364 if (WARN_ON) 365 log[messages++] = "Skipped: CloneNotSupportedException"; 366 skipped++; 367 } 368 369 // Check IllegalAccessException (positive): 370 try { 371 int junkIt = abraIntegerField.getInt(null); // legal - should pass 372 // int junkIt = abraPrivateField.getInt(null); // illegal - should fail 373 if (TRACE_ON) 374 log[messages++] = "Success: IllegalAccessException (positive)"; 375 } catch (IllegalAccessException iae) { 376 log[messages++] = "Failure: IllegalAccessException (positive)"; 377 exitCode = 2; 378 } catch (OutOfMemoryError oome) { 379 if (WARN_ON) 380 log[messages++] = "Skipped: IllegalAccessException (positive)"; 381 skipped++; 382 } 383 384 // Check IllegalAccessException (negative): 385 try { 386 // int junkIt = abraIntegerField.getInt(null); // legal - should pass 387 int junkIt = abraPrivateField.getInt(null); // illegal - should fail 388 log[messages++] = "Failure: IllegalAccessException (negative)"; 389 exitCode = 2; // FAILED 390 } catch (IllegalAccessException iae) { 391 if (TRACE_ON) 392 log[messages++] = "Success: IllegalAccessException (negative)"; 393 } catch (OutOfMemoryError oome) { 394 if (WARN_ON) 395 log[messages++] = "Skipped: IllegalAccessException (negative)"; 396 skipped++; 397 } 398 399 // Check IllegalArgumentException (positive): 400 try { 401 int junkIt = abraIntegerField.getInt(null); // legal - should pass 402 // int junkIt = abraBooleanField.getInt(null); // illegal - should fail 403 if (TRACE_ON) 404 log[messages++] = "Success: IllegalArgumentException (positive)"; 405 } catch (IllegalAccessException iae) { 406 log[messages++] = 407 "Failure: IllegalArgumentException (positive) incorrectly thrown IllegalAccessException"; 408 exitCode = 2; 409 } catch (IllegalArgumentException iae) { 410 log[messages++] = "Failure: IllegalArgumentException (positive)"; 411 exitCode = 2; 412 } catch (OutOfMemoryError oome) { 413 if (WARN_ON) 414 log[messages++] = "Skipped: IllegalArgumentException (positive)"; 415 skipped++; 416 } 417 418 // Check IllegalArgumentException (negative): 419 try { 420 // int junkIt = abraIntegerField.getInt(null); // legal - should pass 421 int junkIt = abraBooleanField.getInt(null); // illegal - should fail 422 log[messages++] = "Failure: IllegalArgumentException (negative)"; 423 exitCode = 2; // FAILED 424 } catch (IllegalAccessException iae) { 425 log[messages++] = 426 "Failure: IllegalArgumentException (negative) incorrectly thrown IllegalAccessException"; 427 exitCode = 2; 428 } catch (IllegalArgumentException iae) { 429 if (TRACE_ON) 430 log[messages++] = "Success: IllegalArgumentException (negative)"; 431 } catch (OutOfMemoryError oome) { 432 if (WARN_ON) 433 log[messages++] = "Skipped: IllegalArgumentException (negative)"; 434 skipped++; 435 } 436 437 // Check IllegalMonitorStateException (positive): 438 try { 439 synchronized (cadabra) { 440 cadabra.notifyAll(); // legal - should pass 441 } 442 // cadabra.notifyAll(); // illegal - should fail 443 if (TRACE_ON) 444 log[messages++] = "Success: IllegalMonitorStateException (positive)"; 445 } catch (IllegalMonitorStateException imse) { 446 log[messages++] = "Failure: IllegalMonitorStateException (positive)"; 447 exitCode = 2; 448 } catch (OutOfMemoryError oome) { 449 if (WARN_ON) 450 log[messages++] = "Skipped: IllegalMonitorStateException (positive)"; 451 skipped++; 452 } 453 454 // Check IllegalMonitorStateException (negative): 455 try { 456 // synchronized (cadabra) { 457 // cadabra.notifyAll(); // legal - should pass 458 // } 459 cadabra.notifyAll(); // illegal - should fail 460 log[messages++] = "Failure: IllegalMonitorStateException (negative)"; 461 exitCode = 2; 462 } catch (IllegalMonitorStateException imse) { 463 if (TRACE_ON) 464 log[messages++] = "Success: IllegalMonitorStateException (negative)"; 465 } catch (OutOfMemoryError oome) { 466 if (WARN_ON) 467 log[messages++] = "Skipped: IllegalMonitorStateException (negative)"; 468 skipped++; 469 } 470 471 return exitCode; 472 } 473 474 /** 475 * Re-call to <code>run(args,out)</code>, and return JCK-like exit status. 476 * (The stream <code>out</code> is assigned to <code>System.out</code> here.) 477 * 478 * @see #run(String[], PrintStream) 479 */ 480 public static void main(String args[]) { 481 Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { 482 // Last try. If there is some exception outside the code, test should end correctly 483 @Override 484 public void uncaughtException(Thread t, Throwable e) { 485 try { 486 pool = null; 487 log = null; 488 System.gc(); 489 if (e instanceof OutOfMemoryError) { 490 try { 491 System.out.println("OOME : Test Skipped"); 492 System.exit(0); 493 } catch (Throwable ignore) { 494 } // No code in the handler can provoke correct exceptions. 495 } else { 496 e.printStackTrace(); 497 if (e instanceof RuntimeException) 498 throw (RuntimeException) e; 499 else if (e instanceof Error) 500 throw (Error) e; 501 else 502 throw new Error("Unexpected checked exception", e); 503 } 504 } catch (OutOfMemoryError oome) { 505 } 506 } 507 }); 508 int exitCode = run(args, System.out); 509 System.exit(exitCode + 95); 510 // JCK-like exit status. 511 } 512 513 /** 514 * This class should be used to check <code>CloneNotSupportedException</code>, 515 * <code>IllegalAccessException</code>, and <code>IllegalArgumentException</code>. 516 * The class extends <code>except004</code> in order that its (protected) 517 * method <code>clone()</code> be available from <code>except004</code>. 518 */ 519 private static class Abra extends except004 { 520 /** 521 * Will try to incorrectly find this class as <code>Cadabra</code> 522 * instead of <code>Abra$Cadabra</code>. 523 */ 524 public static class Cadabra implements Cloneable { 525 } 526 527 /** 528 * Will try to incorrectly access to this field from outside this class. 529 */ 530 private static final int DONT_TOUCH_ME = 666; 531 /** 532 * Will try to incorrectly access to this field from outside this class. 533 */ 534 public static final int MAIN_CYR_NUMBER = 47; 535 /** 536 * Will try to get this field like <code>int<code> zero. 537 */ 538 public static final boolean NOT_AN_INTEGER = false; 539 540 /** 541 * Will try to correctly instantiate <code>Abra.Cadabra</code>, 542 * not <code>Abra</code>. 543 */ 544 private Abra() { 545 } 546 547 /** 548 * Yet another constructor, which is <code>public</code>. 549 */ 550 public Abra(String nothingSpecial) { 551 } 552 } 553 }