Path: blob/master/test/hotspot/jtreg/vmTestbase/nsk/stress/except/except007.java
41155 views
/*1* Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/22232425/*26* @test27* @key stress28*29* @summary converted from VM testbase nsk/stress/except/except007.30* VM testbase keywords: [stress, diehard, slow, nonconcurrent, quick]31* VM testbase readme:32* DESCRIPTION33* This checks if various exceptions are thrown (and caught) correctly34* when there apparently are no free space in the heap to allocate new35* Throwable instance.36* The test tries to occupy all of memory available in the heap by allocating37* lots of new Object() instances. Instances of the type Object are the smallest38* objects, so they apparently should occupy most fine-grained fragments in the39* heap and leave no free space for new Throwable instance. After that, the test40* provokes various exceptions (e.g.: by executing integer division by 0 and so41* on), and checks if appropriate exceptions are thrown.42* COMMENTS43* The test needs a lot of memory to start up, so it should not run under older44* JDK 1.1.x release due to its poorer heap utilization. Also, some checks are45* skipped when testing classic VM, because OutOfMemoryError is correctly thrown46* instead of target exception.47* When the test is being self-initiating (i.e.: eating heap), memory occupation48* is terminated if memory allocation slows down crucially. This is a workaround49* intended to avoid the HotSpot bug:50* #4248801 (P1/S5) slow memory allocation when heap is almost exhausted51* There is also a workaround involved to avoid the following bugs known52* 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 execution56* trace fails under JDK 1.2 for Win32 even so. If the test fails due to this57* 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 exhausted60*61* @run main/othervm -Xms50M -Xmx200M nsk.stress.except.except00762*/6364package nsk.stress.except;6566import java.io.PrintStream;6768/**69* This checks if various exceptions are thrown (and caught) correctly70* when there apparently are no free space in the heap to allocate new71* <code>Throwable</code> instance.72* <p>73* <p>The test tries to occupy all of memory available in the heap by74* allocating lots of new <code>Object()</code> instances. Instances of the75* type <code>Object</code> are the smallest objects, so they apparently should76* occupy most fine-grained fragments in the heap and leave no free space for77* new <code>Throwable</code> instance. After that, the test provokes various78* exceptions (e.g.: by executing integer division by 0 and so on), and checks79* if appropriate exceptions are thrown.80* <p>81* <p>Note, that memory occupation is terminated if memory allocation slows82* 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 exhausted85* <p>86* <p>There is also a workaround involved to avoid the following bugs known87* for HotSpot and for classic VM:88* <br> 89* #4239841 (P1/S5) 1.1: poor garbage collector performance90* <br> 91* #4245060 (P4/S5) poor garbage collector performance92* <br>However, printing of the test's error messages, warnings, and of93* execution trace may fail even so. If the test fails due to poor GC94* 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 should97* not run under older JDK 1.1.x release due to its poor heap utilization.98*/99public class except007 {100/**101* Either allow or supress printing of execution trace.102*/103private static boolean TRACE_ON = false;104/**105* Either allow or supress printing of warning messages.106*/107private static final boolean WARN_ON = true;108/*109* Storage for a lot of tiny objects110* "static volatile" keywords are for preventing heap optimization111*/112private static volatile Object pool[] = null;113/**114* Temporary <code>log</code> for error messages, warnings and/or execution trace.115*116* @see #messages117*/118private static String log[] = new String[1000]; // up to 1000 messages119/**120* How many <code>messages</code> were submitted to the <code>log</code>.121*122* @see #log123*/124private static int messages = 0;125126/**127* Re-call to the method <code>run(out)</code> (ignore <code>args[]</code>),128* and print the test summary - either test passed of failed.129*/130public static int run(String args[], PrintStream out) {131if (args.length > 0) {132if (args[0].toLowerCase().startsWith("-v"))133TRACE_ON = true;134}135136int exitCode = run(out);137pool = null;138System.gc();139// Print the log[] and the test summary:140try {141for (int i = 0; i < messages; i++)142out.println(log[i]);143if (exitCode == 0) {144if (TRACE_ON)145out.println("Test passed.");146} else147out.println("Test failed.");148} catch (OutOfMemoryError oome) {149// Poor performance of garbage collector:150exitCode = 1;151}152153return exitCode;154}155156/**157* Allocate as much <code>Object</code> instances as possible to bring JVM158* into stress, and then check if exceptions are correctly thrown accordingly159* to various situations like integer division by 0, etc.160*/161private static int run(PrintStream out) {162out.println("# While printing this message, JVM seems to initiate the output");163out.println("# stream, so that it will not need more memory to print later,");164out.println("# when the heap would fail to provide more memory.");165out.println("# ");166out.println("# Note, that the test maintains especial static log[] field in");167out.println("# order to avoid printing when the heap seems exhausted.");168out.println("# Nevertheless, printing could arise OutOfMemoryError even");169out.println("# after all the memory allocated by the test is released.");170out.println("# ");171out.println("# That problem is caused by the known JDK/HotSpot bugs:");172out.println("# 4239841 (P1/S5) 1.1: poor garbage collector performance");173out.println("# 4245060 (P4/S5) poor garbage collector performance");174out.println("# ");175out.println("# This message is just intended to work-around that problem.");176out.println("# If printing should fail even so, the test will try to return");177out.println("# the exit status 96 instead of 97 to indicate the problem.");178out.println("# However, the test may fail or even crash on some platforms");179out.println("# suffering the bug 4239841 or 4245060.");180181// Prepare some items, which will be used by the test:182Thread rabbit = new Rabbit();183184// Allocate repository for a lots of tiny objects:185for (int size = 1 << 30; size > 0 && pool == null; size >>= 1)186try {187pool = new Object[size];188} catch (OutOfMemoryError oome) {189}190if (pool == null)191throw new Error("HS bug: cannot allocate new Object[1]");192int poolSize = pool.length;193194int index = 0;195pool[index++] = new Object();196197// Sum up time spent, when it was hard to JVM to allocate next object198// (i.e.: when JVM has spent more than 1 second to allocate new object):199double totalDelay = 0;200long timeMark = System.currentTimeMillis();201try {202for (; index < poolSize; index++) {203//-------------------------204pool[index] = new Object();205long nextTimeMark = System.currentTimeMillis();206long elapsed = nextTimeMark - timeMark;207timeMark = nextTimeMark;208//----------------------209if (elapsed > 1000) {210double seconds = elapsed / 1000.0;211if (TRACE_ON)212out.println(213"pool[" + index + "]=new Object(); // elapsed " + seconds + "s");214totalDelay += seconds;215if (totalDelay > 60) {216if (TRACE_ON)217out.println(218"Memory allocation became slow; so, heap seems exhausted.");219break;220}221}222}223} catch (OutOfMemoryError oome) {224if (TRACE_ON)225log[messages++] = "Heap seems exhausted - OutOfMemoryError thrown.";226}227if (index > poolSize - 1000) {228if (WARN_ON)229log[messages++] = "Warning: pool[] is full; so, checks would not be enough hard...";230}231232// Sum up exit code:233int exitCode = 0; // apparently PASSED234int skipped = 0; // some checks may correctly suffer OutOfMemoryError235236// Check InterruptedException:237try {238synchronized (rabbit) {239rabbit.start();240rabbit.wait();241}242rabbit.interrupt();243while (rabbit.isAlive())244rabbit.join();245Throwable exception = ((Rabbit) rabbit).exception;246if (exception == null) {247log[messages++] = "Failure: InterruptedException not thrown";248exitCode = 2;249} else {250if (exception instanceof InterruptedException) {251if (TRACE_ON)252log[messages++] =253"Success: InterruptedException thrown as expected";254} else if (exception instanceof OutOfMemoryError) {255if (WARN_ON)256log[messages++] = "Skipped: InterruptedException";257skipped++;258} else {259log[messages++] =260"Failure: InterruptedException: unexpected exception thrown";261exitCode = 2;262}263pool[index++] = exception;264}265} catch (InterruptedException ie) {266log[messages++] = "Failure: InterruptedException thrown unexpectedly";267exitCode = 2;268} catch (OutOfMemoryError oome) {269if (WARN_ON)270log[messages++] = "Skipped: InterruptedException";271skipped++;272}273274// Check NegativeArraySizeException:275try {276int negative = -1;277byte array[] = new byte[negative];278log[messages++] = "Failure: NegativeArraySizeException not thrown as expected";279exitCode = 2;280} catch (NegativeArraySizeException ie) {281if (TRACE_ON)282log[messages++] = "Success: NegativeArraySizeException thrown as expected";283pool[index++] = ie;284} catch (OutOfMemoryError oome) {285if (WARN_ON)286log[messages++] = "Skipped: NegativeArraySizeException";287skipped++;288}289290// Check NullPointerException:291try {292Double none = null;293double oops = none.doubleValue();294log[messages++] = "Failure: NullPointerException not thrown as expected";295exitCode = 2;296} catch (NullPointerException npe) {297if (TRACE_ON)298log[messages++] = "Success: NullPointerException thrown as expected";299pool[index++] = npe;300} catch (OutOfMemoryError oome) {301if (WARN_ON)302log[messages++] = "Skipped: NullPointerException";303skipped++;304}305306// Check NumberFormatException:307try {308double oops = Double.parseDouble("3.14159D00"); // FORTRAN-like309log[messages++] = "Failure: NumberFormatException not thrown as expected";310exitCode = 2;311} catch (NumberFormatException nfe) {312if (TRACE_ON)313log[messages++] = "Success: NumberFormatException thrown as expected";314} catch (OutOfMemoryError oome) {315if (WARN_ON)316log[messages++] = "Skipped: NumberFormatException";317skipped++;318}319320return exitCode;321}322323/**324* Will shoot a rabbit when it waits -- in order to provoke325* InterruptedException.326*/327private static class Rabbit extends Thread {328Throwable exception = null;329330public void run() {331try {332synchronized (this) {333this.notify();334this.wait();335}336} catch (InterruptedException ie) {337exception = ie;338} catch (OutOfMemoryError oome) {339exception = oome;340}341}342343}344345/**346* Re-call to <code>run(args,out)</code>, and return JCK-like exit status.347* (The stream <code>out</code> is assigned to <code>System.out</code> here.)348*349* @see #run(String[], PrintStream)350*/351public static void main(String args[]) {352Thread.currentThread().setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {353// Last try. If there is some exception outside the code, test should end correctly354@Override355public void uncaughtException(Thread t, Throwable e) {356try {357pool = null;358log = null;359System.gc();360if (e instanceof OutOfMemoryError) {361try {362System.out.println("OOME : Test Skipped");363System.exit(0);364} catch (Throwable ignore) {365} // No code in the handler can provoke correct exceptions.366} else {367e.printStackTrace();368throw (RuntimeException) e;369}370} catch (OutOfMemoryError oome) {371}372}373});374int exitCode = run(args, System.out);375System.exit(exitCode + 95);376// JCK-like exit status.377}378379}380381382