Path: blob/master/test/hotspot/jtreg/vmTestbase/nsk/stress/except/except012.java
41155 views
/*1* Copyright (c) 1999, 2020, 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*/222324/*25* @test26* @key stress27*28* @summary converted from VM testbase nsk/stress/except/except012.29* VM testbase keywords: [stress, slow, nonconcurrent, quick]30* VM testbase readme:31* DESCRIPTION32* This checks if various exceptions are thrown (and caught) correctly33* when there apparently are no free space in the heap to allocate new34* Throwable instance.35* The test tries to occupy all of memory available in the heap by allocating36* lots of new Object() instances. Instances of the type Object are the smallest37* objects, so they apparently should occupy most fine-grained fragments in the38* heap and leave no free space for new Throwable instance. After that, the test39* provokes various exceptions (e.g.: by executing integer division by 0 and so40* on), and checks if appropriate exceptions are thrown.41* COMMENTS42* The test needs a lot of memory to start up, so it should not run under older43* JDK 1.1.x release due to its poorer heap utilization. Also, some checks are44* skipped when testing classic VM, because OutOfMemoryError is correctly thrown45* instead of target exception.46* When the test is being self-initiating (i.e.: eating heap), memory occupation47* is terminated if memory allocation slows down crucially. This is a workaround48* intended to avoid the HotSpot bug:49* #4248801 (P1/S5) slow memory allocation when heap is almost exhausted50* There is also a workaround involved to avoid the following bugs known51* for HotSpot and for classic VM:52* #4239841 (P1/S5) 1.1: poor garbage collector performance (HotSpot bug)53* #4245060 (P4/S5) poor garbage collector performance (Classic VM bug)54* However, printing of the test's error messages, warnings, and of execution55* trace fails under JDK 1.2 for Win32 even so. If the test fails due to this56* problem, exit status 96 is returned instead of 97.57* JDK 1.3 classic VM for Sparc may crash (core dump) due to the known bug:58* #4245057 (P2/S3) VM crashes when heap is exhausted59*60* @run main/othervm -Xms50M -Xmx200M nsk.stress.except.except01261*/6263package nsk.stress.except;6465import java.io.PrintStream;66import java.util.Random;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 except012 {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;108109/**110* Temporary <code>log</code> for error messages, warnings and/or execution trace.111*112* @see #messages113*/114private static String log[] = new String[1000]; // up to 1000 messages115/**116* How many <code>messages</code> were submitted to the <code>log</code>.117*118* @see #log119*/120private static int messages = 0;121/*122* Storage for a lot of tiny objects123* "static volatile" keywords are for preventing heap optimization124*/125private static volatile Object pool[] = null;126127/**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*/131public static int run(String args[], PrintStream out) {132if (args.length > 0) {133if (args[0].toLowerCase().startsWith("-v"))134TRACE_ON = true;135}136137int exitCode = run(out);138pool = null;139System.gc();140// Print the log[] and the test summary:141try {142for (int i = 0; i < messages; i++)143out.println(log[i]);144if (exitCode == 0) {145if (TRACE_ON)146out.println("Test passed.");147} else148out.println("Test failed.");149} catch (OutOfMemoryError oome) {150// Poor performance of garbage collector:151exitCode = 1;152}153154return exitCode;155}156157/**158* Allocate as much <code>Object</code> instances as possible to bring JVM159* into stress, and then check if exceptions are correctly thrown accordingly160* to various situations like integer division by 0, etc.161*/162private static int run(PrintStream out) {163out.println("# While printing this message, JVM seems to initiate the output");164out.println("# stream, so that it will not need more memory to print later,");165out.println("# when the heap would fail to provide more memory.");166out.println("# ");167out.println("# Note, that the test maintains especial static log[] field in");168out.println("# order to avoid printing when the heap seems exhausted.");169out.println("# Nevertheless, printing could arise OutOfMemoryError even");170out.println("# after all the memory allocated by the test is released.");171out.println("# ");172out.println("# That problem is caused by the known JDK/HotSpot bugs:");173out.println("# 4239841 (P1/S5) 1.1: poor garbage collector performance");174out.println("# 4245060 (P4/S5) poor garbage collector performance");175out.println("# ");176out.println("# This message is just intended to work-around that problem.");177out.println("# If printing should fail even so, the test will try to return");178out.println("# the exit status 96 instead of 97 to indicate the problem.");179out.println("# However, the test may fail or even crash on some platforms");180out.println("# suffering the bug 4239841 or 4245060.");181182// Allocate items necessary for the test:183CrazyClassLoader crazyClassLoader = new CrazyClassLoader();184MustDie threadToDie = new MustDie();185186// Sum up exit code:187int exitCode = 0; // apparently PASSED188int skipped = 0; // some checks may correctly suffer OutOfMemoryError189// Allocate repository for a lots of tiny objects:190for (int size = 1 << 30; size > 0 && pool == null; size >>= 1)191try {192pool = new Object[size];193} catch (OutOfMemoryError oome) {194}195if (pool == null)196throw new Error("HS bug: cannot allocate new Object[1]");197int poolSize = pool.length;198199int index = 0;200pool[index++] = new Object();201202// Sum up time spent, when it was hard to JVM to allocate next object203// (i.e.: when JVM has spent more than 1 second to allocate new object):204double totalDelay = 0;205long timeMark = System.currentTimeMillis();206try {207for (; index < poolSize; index++) {208//-------------------------209pool[index] = new Object();210long nextTimeMark = System.currentTimeMillis();211long elapsed = nextTimeMark - timeMark;212timeMark = nextTimeMark;213//----------------------214if (elapsed > 1000) {215double seconds = elapsed / 1000.0;216if (TRACE_ON)217out.println(218"pool[" + index + "]=new Object(); // elapsed " + seconds + "s");219totalDelay += seconds;220if (totalDelay > 60) {221if (TRACE_ON)222out.println(223"Memory allocation became slow; so, heap seems exhausted.");224break;225}226}227}228} catch (OutOfMemoryError oome) {229if (TRACE_ON)230log[messages++] = "Heap seems exhausted - OutOfMemoryError thrown.";231}232233if (index > poolSize - 1000) {234if (WARN_ON)235log[messages++] = "Warning: pool[] is full; so, checks would not be enough hard...";236}237238// Check ClassFormatError:239try {240Class oops = crazyClassLoader.loadClass("name doesn't matter");241log[messages++] = "Failure: ClassFormatError failed to throw";242exitCode = 2;243} catch (ClassFormatError cfe) {244if (TRACE_ON)245log[messages++] = "Success: ClassFormatError thrown as expected";246} catch (ClassNotFoundException cnfe) {247log[messages++] =248"Failure: ClassFormatError: unexpectedly thrown ClassNotFoundException";249exitCode = 2;250} catch (OutOfMemoryError oome) {251if (WARN_ON)252log[messages++] =253"Skipped: ClassFormatError: thrown OutOfMemoryError";254skipped++;255}256257// Check ThreadDeath:258try {259threadToDie.start();260while (threadToDie.isAlive())261threadToDie.join();262Throwable exception = threadToDie.exception;263if (exception == null) {264log[messages++] = "Failure: ThreadDeath failed to throw";265exitCode = 2;266} else if (exception instanceof OutOfMemoryError) {267if (WARN_ON)268log[messages++] =269"Skipped: ThreadDeath: thrown OutOfMemoryError instead";270} else if (!(exception instanceof ThreadDeath)) {271log[messages++] =272"Failure: ThreadDeath: unexpected exception thrown";273exitCode = 2;274} else if (TRACE_ON)275log[messages++] = "Success: ThreadDeath thrown as expected";276} catch (InterruptedException ie) {277pool[index++] = ie;278log[messages++] =279"Failure: ThreadDeath: thrown InterruptedException instead";280exitCode = 2;281} catch (OutOfMemoryError oome) {282if (WARN_ON)283log[messages++] =284"Skipped: ThreadDeath: thrown OutOfMemoryError";285skipped++;286}287288return exitCode;289}290291/**292* This class loader provokes <code>ClassFormatError</code>.293*/294private static class CrazyClassLoader extends ClassLoader {295public Class loadClass(String name) throws ClassNotFoundException {296Class crazyClass = defineClass(null, crazyBytecode, 0, crazyBytecode.length);297return crazyClass; // return is unreacable, due to ClassFormatError298}299300private static byte crazyBytecode[];301302static {303crazyBytecode = new byte[1000];304Random random = new Random(42);305for (int i = 0; i < crazyBytecode.length; i++)306crazyBytecode[i] = (byte) random.nextInt(256);307}308309}310311/**312* This thread should die in order to check <code>ThreadDeath</code> error.313*/314private static class MustDie extends Thread {315Throwable exception = null;316317public void run() {318try {319stop();320} catch (Throwable throwable) {321exception = throwable;322if (throwable instanceof ThreadDeath)323throw (ThreadDeath) throwable;324}325}326327}328329/**330* Re-call to <code>run(args,out)</code>, and return JCK-like exit status.331* (The stream <code>out</code> is assigned to <code>System.out</code> here.)332*333* @see #run(String[], PrintStream)334*/335public static void main(String args[]) {336Thread.currentThread().setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {337// Last try. If there is some OOME, test should end correctly338@Override339public void uncaughtException(Thread t, Throwable e) {340try {341pool = null;342System.gc(); // Empty memory to be able to write to the output343if (e instanceof OutOfMemoryError) {344try {345System.out.println("OOME : Test Skipped");346System.exit(0);347} catch (Throwable ignore) {348} // any of the test exceptions are handled in test.#349// No code in the handler can provoke correct exceptions.350} else if (e instanceof ThreadDeath) {351} //ignore since it thrown as expected352else {353e.printStackTrace();354throw (RuntimeException) e;355}356} catch (OutOfMemoryError oome) {357}358}359});360int exitCode = run(args, System.out);361System.exit(exitCode + 95);362// JCK-like exit status.363}364365}366367368