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 /* 27 * @test 28 * @key stress 29 * 30 * @summary converted from VM testbase nsk/stress/except/except007. 31 * VM testbase keywords: [stress, diehard, slow, nonconcurrent, quick] 32 * VM testbase readme: 33 * DESCRIPTION 34 * This checks if various exceptions are thrown (and caught) correctly 35 * when there apparently are no free space in the heap to allocate new 36 * Throwable instance. 37 * The test tries to occupy all of memory available in the heap by allocating 38 * lots of new Object() instances. Instances of the type Object are the smallest 39 * objects, so they apparently should occupy most fine-grained fragments in the 40 * heap and leave no free space for new Throwable instance. After that, the test 41 * provokes various exceptions (e.g.: by executing integer division by 0 and so 42 * on), and checks if appropriate exceptions are thrown. 43 * COMMENTS 44 * The test needs a lot of memory to start up, so it should not run under older 45 * JDK 1.1.x release due to its poorer heap utilization. Also, some checks are 46 * skipped when testing classic VM, because OutOfMemoryError is correctly thrown 47 * instead of target exception. 48 * When the test is being self-initiating (i.e.: eating heap), memory occupation 49 * is terminated if memory allocation slows down crucially. This is a workaround 50 * intended to avoid the HotSpot bug: 51 * #4248801 (P1/S5) slow memory allocation when heap is almost exhausted 52 * There is also a workaround involved to avoid the following bugs known 53 * for HotSpot and for classic VM: 54 * #4239841 (P1/S5) 1.1: poor garbage collector performance (HotSpot bug) 55 * #4245060 (P4/S5) poor garbage collector performance (Classic VM bug) 56 * However, printing of the test's error messages, warnings, and of execution 57 * trace fails under JDK 1.2 for Win32 even so. If the test fails due to this 58 * problem, exit status 96 is returned instead of 97. 59 * JDK 1.3 classic VM for Sparc may crash (core dump) due to the known bug: 60 * #4245057 (P2/S3) VM crashes when heap is exhausted 61 * 62 * @run main/othervm -Xms50M -Xmx200M nsk.stress.except.except007 63 */ 64 65 package nsk.stress.except; 66 67 import java.io.PrintStream; 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 except007 { 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 */ run(String args[], PrintStream out)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 = run(out); 138 pool = null; 139 System.gc(); 140 // Print the log[] and the test summary: 141 try { 142 for (int i = 0; i < messages; i++) 143 out.println(log[i]); 144 if (exitCode == 0) { 145 if (TRACE_ON) 146 out.println("Test passed."); 147 } else 148 out.println("Test failed."); 149 } catch (OutOfMemoryError oome) { 150 // Poor performance of garbage collector: 151 exitCode = 1; 152 } 153 154 return exitCode; 155 } 156 157 /** 158 * Allocate as much <code>Object</code> instances as possible to bring JVM 159 * into stress, and then check if exceptions are correctly thrown accordingly 160 * to various situations like integer division by 0, etc. 161 */ run(PrintStream out)162 private static int run(PrintStream out) { 163 out.println("# While printing this message, JVM seems to initiate the output"); 164 out.println("# stream, so that it will not need more memory to print later,"); 165 out.println("# when the heap would fail to provide more memory."); 166 out.println("# "); 167 out.println("# Note, that the test maintains especial static log[] field in"); 168 out.println("# order to avoid printing when the heap seems exhausted."); 169 out.println("# Nevertheless, printing could arise OutOfMemoryError even"); 170 out.println("# after all the memory allocated by the test is released."); 171 out.println("# "); 172 out.println("# That problem is caused by the known JDK/HotSpot bugs:"); 173 out.println("# 4239841 (P1/S5) 1.1: poor garbage collector performance"); 174 out.println("# 4245060 (P4/S5) poor garbage collector performance"); 175 out.println("# "); 176 out.println("# This message is just intended to work-around that problem."); 177 out.println("# If printing should fail even so, the test will try to return"); 178 out.println("# the exit status 96 instead of 97 to indicate the problem."); 179 out.println("# However, the test may fail or even crash on some platforms"); 180 out.println("# suffering the bug 4239841 or 4245060."); 181 182 // Prepare some items, which will be used by the test: 183 Thread rabbit = new Rabbit(); 184 185 // Allocate repository for a lots of tiny objects: 186 for (int size = 1 << 30; size > 0 && pool == null; size >>= 1) 187 try { 188 pool = new Object[size]; 189 } catch (OutOfMemoryError oome) { 190 } 191 if (pool == null) 192 throw new Error("HS bug: cannot allocate new Object[1]"); 193 int poolSize = pool.length; 194 195 int index = 0; 196 pool[index++] = new Object(); 197 198 // Sum up time spent, when it was hard to JVM to allocate next object 199 // (i.e.: when JVM has spent more than 1 second to allocate new object): 200 double totalDelay = 0; 201 long timeMark = System.currentTimeMillis(); 202 try { 203 for (; index < poolSize; index++) { 204 //------------------------- 205 pool[index] = new Object(); 206 long nextTimeMark = System.currentTimeMillis(); 207 long elapsed = nextTimeMark - timeMark; 208 timeMark = nextTimeMark; 209 //---------------------- 210 if (elapsed > 1000) { 211 double seconds = elapsed / 1000.0; 212 if (TRACE_ON) 213 out.println( 214 "pool[" + index + "]=new Object(); // elapsed " + seconds + "s"); 215 totalDelay += seconds; 216 if (totalDelay > 60) { 217 if (TRACE_ON) 218 out.println( 219 "Memory allocation became slow; so, heap seems exhausted."); 220 break; 221 } 222 } 223 } 224 } catch (OutOfMemoryError oome) { 225 if (TRACE_ON) 226 log[messages++] = "Heap seems exhausted - OutOfMemoryError thrown."; 227 } 228 if (index > poolSize - 1000) { 229 if (WARN_ON) 230 log[messages++] = "Warning: pool[] is full; so, checks would not be enough hard..."; 231 } 232 233 // Sum up exit code: 234 int exitCode = 0; // apparently PASSED 235 int skipped = 0; // some checks may correctly suffer OutOfMemoryError 236 237 // Check InterruptedException: 238 try { 239 synchronized (rabbit) { 240 rabbit.start(); 241 rabbit.wait(); 242 } 243 rabbit.interrupt(); 244 while (rabbit.isAlive()) 245 rabbit.join(); 246 Throwable exception = ((Rabbit) rabbit).exception; 247 if (exception == null) { 248 log[messages++] = "Failure: InterruptedException not thrown"; 249 exitCode = 2; 250 } else { 251 if (exception instanceof InterruptedException) { 252 if (TRACE_ON) 253 log[messages++] = 254 "Success: InterruptedException thrown as expected"; 255 } else if (exception instanceof OutOfMemoryError) { 256 if (WARN_ON) 257 log[messages++] = "Skipped: InterruptedException"; 258 skipped++; 259 } else { 260 log[messages++] = 261 "Failure: InterruptedException: unexpected exception thrown"; 262 exitCode = 2; 263 } 264 pool[index++] = exception; 265 } 266 } catch (InterruptedException ie) { 267 log[messages++] = "Failure: InterruptedException thrown unexpectedly"; 268 exitCode = 2; 269 } catch (OutOfMemoryError oome) { 270 if (WARN_ON) 271 log[messages++] = "Skipped: InterruptedException"; 272 skipped++; 273 } 274 275 // Check NegativeArraySizeException: 276 try { 277 int negative = -1; 278 byte array[] = new byte[negative]; 279 log[messages++] = "Failure: NegativeArraySizeException not thrown as expected"; 280 exitCode = 2; 281 } catch (NegativeArraySizeException ie) { 282 if (TRACE_ON) 283 log[messages++] = "Success: NegativeArraySizeException thrown as expected"; 284 pool[index++] = ie; 285 } catch (OutOfMemoryError oome) { 286 if (WARN_ON) 287 log[messages++] = "Skipped: NegativeArraySizeException"; 288 skipped++; 289 } 290 291 // Check NullPointerException: 292 try { 293 Double none = null; 294 double oops = none.doubleValue(); 295 log[messages++] = "Failure: NullPointerException not thrown as expected"; 296 exitCode = 2; 297 } catch (NullPointerException npe) { 298 if (TRACE_ON) 299 log[messages++] = "Success: NullPointerException thrown as expected"; 300 pool[index++] = npe; 301 } catch (OutOfMemoryError oome) { 302 if (WARN_ON) 303 log[messages++] = "Skipped: NullPointerException"; 304 skipped++; 305 } 306 307 // Check NumberFormatException: 308 try { 309 double oops = Double.parseDouble("3.14159D00"); // FORTRAN-like 310 log[messages++] = "Failure: NumberFormatException not thrown as expected"; 311 exitCode = 2; 312 } catch (NumberFormatException nfe) { 313 if (TRACE_ON) 314 log[messages++] = "Success: NumberFormatException thrown as expected"; 315 } catch (OutOfMemoryError oome) { 316 if (WARN_ON) 317 log[messages++] = "Skipped: NumberFormatException"; 318 skipped++; 319 } 320 321 return exitCode; 322 } 323 324 /** 325 * Will shoot a rabbit when it waits -- in order to provoke 326 * InterruptedException. 327 */ 328 private static class Rabbit extends Thread { 329 Throwable exception = null; 330 run()331 public void run() { 332 try { 333 synchronized (this) { 334 this.notify(); 335 this.wait(); 336 } 337 } catch (InterruptedException ie) { 338 exception = ie; 339 } catch (OutOfMemoryError oome) { 340 exception = oome; 341 } 342 } 343 344 } 345 346 /** 347 * Re-call to <code>run(args,out)</code>, and return JCK-like exit status. 348 * (The stream <code>out</code> is assigned to <code>System.out</code> here.) 349 * 350 * @see #run(String[], PrintStream) 351 */ main(String args[])352 public static void main(String args[]) { 353 Thread.currentThread().setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { 354 // Last try. If there is some exception outside the code, test should end correctly 355 @Override 356 public void uncaughtException(Thread t, Throwable e) { 357 try { 358 pool = null; 359 log = null; 360 System.gc(); 361 if (e instanceof OutOfMemoryError) { 362 try { 363 System.out.println("OOME : Test Skipped"); 364 System.exit(0); 365 } catch (Throwable ignore) { 366 } // No code in the handler can provoke correct exceptions. 367 } else { 368 e.printStackTrace(); 369 throw (RuntimeException) e; 370 } 371 } catch (OutOfMemoryError oome) { 372 } 373 } 374 }); 375 int exitCode = run(args, System.out); 376 System.exit(exitCode + 95); 377 // JCK-like exit status. 378 } 379 380 } 381