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/except011. 30 * VM testbase keywords: [stress, 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 nsk.stress.except.except011 62 */ 63 64 package nsk.stress.except; 65 66 import java.io.PrintStream; 67 68 /** 69 * This checks if various exceptions are thrown (and caught) correctly 70 * when there apparently are no free space in the heap to allocate new 71 * <code>Throwable</code> instance. 72 * <p> 73 * <p>The test tries to occupy all of memory available in the heap by 74 * allocating lots of new <code>Object()</code> instances. Instances of the 75 * type <code>Object</code> are the smallest objects, so they apparently should 76 * occupy most fine-grained fragments in the heap and leave no free space for 77 * new <code>Throwable</code> instance. After that, the test provokes various 78 * exceptions (e.g.: by executing integer division by 0 and so on), and checks 79 * if appropriate exceptions are thrown. 80 * <p> 81 * <p>Note, that memory occupation is terminated if memory allocation slows 82 * down crucially. This is a workaround intended to avoid the HotSpot bug: 83 * <br> 84 * #4248801 (P1/S5) slow memory allocation when heap is almost exhausted 85 * <p> 86 * <p>There is also a workaround involved to avoid the following bugs known 87 * for HotSpot and for classic VM: 88 * <br> 89 * #4239841 (P1/S5) 1.1: poor garbage collector performance 90 * <br> 91 * #4245060 (P4/S5) poor garbage collector performance 92 * <br>However, printing of the test's error messages, warnings, and of 93 * execution trace may fail even so. If the test fails due to poor GC 94 * performance, exit status 96 is returned instead of 97. 95 * <p> 96 * <p>Also note, that the test needs a lot of memory to start up, so it should 97 * not run under older JDK 1.1.x release due to its poor heap utilization. 98 */ 99 public class except011 { 100 /** 101 * Either allow or supress printing of execution trace. 102 */ 103 private static boolean TRACE_ON = false; 104 /** 105 * Either allow or supress printing of warning messages. 106 */ 107 private static final boolean WARN_ON = true; 108 /* 109 * Storage for a lot of tiny objects 110 * "static volatile" keywords are for preventing heap optimization 111 */ 112 private static volatile Object pool[] = null; 113 /** 114 * Temporary <code>log</code> for error messages, warnings and/or execution trace. 115 * 116 * @see #messages 117 */ 118 private static String log[] = new String[1000]; // up to 1000 messages 119 /** 120 * How many <code>messages</code> were submitted to the <code>log</code>. 121 * 122 * @see #log 123 */ 124 private static int messages = 0; 125 126 private static final String className = "nsk.stress.except.except011oops"; 127 128 /** 129 * Re-call to the method <code>run(out)</code> (ignore <code>args[]</code>), 130 * and print the test summary - either test passed of failed. 131 */ 132 public static int run(String args[], PrintStream out) { 133 if (args.length > 0) { 134 if (args[0].toLowerCase().startsWith("-v")) 135 TRACE_ON = true; 136 } 137 138 int exitCode = run(out); 139 pool = null; 140 System.gc(); 141 // Print the log[] and the test summary: 142 try { 143 for (int i = 0; i < messages; i++) 144 out.println(log[i]); 145 if (exitCode == 0) { 146 if (TRACE_ON) 147 out.println("Test passed."); 148 } else 149 out.println("Test failed."); 150 } catch (OutOfMemoryError oome) { 151 // Poor performance of garbage collector: 152 exitCode = 1; 153 } 154 155 return exitCode; 156 } 157 158 /** 159 * Allocate as much <code>Object</code> instances as possible to bring JVM 160 * into stress, and then check if exceptions are correctly thrown accordingly 161 * to various situations like integer division by 0, etc. 162 */ 163 private static int run(PrintStream out) { 164 out.println("# While printing this message, JVM seems to initiate the output"); 165 out.println("# stream, so that it will not need more memory to print later,"); 166 out.println("# when the heap would fail to provide more memory."); 167 out.println("# "); 168 out.println("# Note, that the test maintains especial static log[] field in"); 169 out.println("# order to avoid printing when the heap seems exhausted."); 170 out.println("# Nevertheless, printing could arise OutOfMemoryError even"); 171 out.println("# after all the memory allocated by the test is released."); 172 out.println("# "); 173 out.println("# That problem is caused by the known JDK/HotSpot bugs:"); 174 out.println("# 4239841 (P1/S5) 1.1: poor garbage collector performance"); 175 out.println("# 4245060 (P4/S5) poor garbage collector performance"); 176 out.println("# "); 177 out.println("# This message is just intended to work-around that problem."); 178 out.println("# If printing should fail even so, the test will try to return"); 179 out.println("# the exit status 96 instead of 97 to indicate the problem."); 180 out.println("# However, the test may fail or even crash on some platforms"); 181 out.println("# suffering the bug 4239841 or 4245060."); 182 183 // Sum up exit code: 184 int exitCode = 0; // apparently PASSED 185 int skipped = 0; // some checks may correctly suffer OutOfMemoryError 186 Class oops; 187 // Allocate repository for a lots of tiny objects: 188 for (int size = 1 << 30; size > 0 && pool == null; size >>= 1) 189 try { 190 pool = new Object[size]; 191 } catch (OutOfMemoryError oome) { 192 } 193 if (pool == null) 194 throw new Error("HS bug: cannot allocate new Object[1]"); 195 int poolSize = pool.length; 196 197 int index = 0; 198 pool[index++] = new Object(); 199 200 // Sum up time spent, when it was hard to JVM to allocate next object 201 // (i.e.: when JVM has spent more than 1 second to allocate new object): 202 double totalDelay = 0; 203 long timeMark = System.currentTimeMillis(); 204 try { 205 for (; index < poolSize; index++) { 206 //------------------------- 207 pool[index] = new Object(); 208 long nextTimeMark = System.currentTimeMillis(); 209 long elapsed = nextTimeMark - timeMark; 210 timeMark = nextTimeMark; 211 //---------------------- 212 if (elapsed > 1000) { 213 double seconds = elapsed / 1000.0; 214 if (TRACE_ON) 215 out.println( 216 "pool[" + index + "]=new Object(); // elapsed " + seconds + "s"); 217 totalDelay += seconds; 218 if (totalDelay > 60) { 219 if (TRACE_ON) 220 out.println( 221 "Memory allocation became slow; so, heap seems exhausted."); 222 break; 223 } 224 } 225 } 226 } catch (OutOfMemoryError oome) { 227 if (TRACE_ON) 228 log[messages++] = "Heap seems exhausted - OutOfMemoryError thrown."; 229 } 230 231 if (index > poolSize - 1000) { 232 if (WARN_ON) 233 log[messages++] = "Warning: pool[] is full; so, checks would not be enough hard..."; 234 } 235 236 // Check ExceptionInInitializerError: 237 try { 238 oops = Class.forName(className); 239 log[messages++] = "Failure: ExceptionInInitializerError failed to throw"; 240 exitCode = 2; 241 } catch (ExceptionInInitializerError eiie) { 242 String message = eiie.getException().getMessage(); 243 if (!message.equals("except011oops")) { 244 log[messages++] = 245 "Failure: ExceptionInInitializerError: unexpected target exception"; 246 exitCode = 2; 247 } else if (TRACE_ON) 248 log[messages++] = "Success: ExceptionInInitializerError thrown as expected"; 249 } catch (ClassNotFoundException cnfe) { 250 log[messages++] = "Failure: ExceptionInInitializerError: target class not found"; 251 exitCode = 2; 252 } catch (OutOfMemoryError oome) { 253 if (WARN_ON) 254 log[messages++] = 255 "Skipped: ExceptionInInitializerError: thrown OutOfMemoryError"; 256 skipped++; 257 } 258 259 return exitCode; 260 } 261 262 /** 263 * Re-call to <code>run(args,out)</code>, and return JCK-like exit status. 264 * (The stream <code>out</code> is assigned to <code>System.out</code> here.) 265 * 266 * @see #run(String[], PrintStream) 267 */ 268 public static void main(String args[]) { 269 Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { 270 // Last try. If there is some OOME, test should end correctly 271 @Override 272 public void uncaughtException(Thread t, Throwable e) { 273 try { 274 pool = null; 275 log = null; 276 System.gc(); // Empty memory to be able to write to the output 277 if (e instanceof OutOfMemoryError) { 278 try { 279 System.out.println("OOME : Test Skipped"); 280 System.exit(0); 281 } catch (Throwable ignore) { 282 } // No code in the handler can provoke correct exceptions. 283 } else { 284 e.printStackTrace(); 285 throw (RuntimeException) e; 286 } 287 } catch (OutOfMemoryError oome) { 288 } 289 } 290 }); 291 int exitCode = run(args, System.out); 292 System.exit(exitCode + 95); 293 // JCK-like exit status. 294 } 295 296 }