test/gc/TestSoftReferencesBehaviorOnOOME.java

Print this page
rev 7996 : 8073669: gc/TestSoftReferencesBehaviorOnOOME.java times out in nightlies
Summary: changed test scenario to more straight-forward one,
         added tricks to prevent compiler optimizations and
         added checks when OOME didn't thrown as expected.
Reviewed-by:

*** 24,105 **** /** * @test TestSoftReferencesBehaviorOnOOME * @key gc * @summary Tests that all SoftReferences has been cleared at time of OOM. * @library /testlibrary - * @ignore 8073669 * @build TestSoftReferencesBehaviorOnOOME * @run main/othervm -Xmx128m TestSoftReferencesBehaviorOnOOME 512 2k * @run main/othervm -Xmx128m TestSoftReferencesBehaviorOnOOME 128k 256k ! * @run main/othervm -Xmx128m TestSoftReferencesBehaviorOnOOME 2k 32k 10 */ import com.oracle.java.testlibrary.Utils; import java.lang.ref.SoftReference; import java.util.LinkedList; import java.util.Random; public class TestSoftReferencesBehaviorOnOOME { ! private static final Random rndGenerator = Utils.getRandomInstance(); ! public static void main(String[] args) { ! int semiRefAllocFrequency = DEFAULT_FREQUENCY; ! long minSize = DEFAULT_MIN_SIZE, ! maxSize = DEFAULT_MAX_SIZE; ! ! if ( args.length >= 3 ) { ! semiRefAllocFrequency = Integer.parseInt(args[2]); ! } if ( args.length >= 2) { maxSize = getBytesCount(args[1]); } if ( args.length >= 1) { minSize = getBytesCount(args[0]); } ! new TestSoftReferencesBehaviorOnOOME().softReferencesOom(minSize, maxSize, semiRefAllocFrequency); } /** * Test that all SoftReferences has been cleared at time of OOM. */ ! void softReferencesOom(long minSize, long maxSize, int semiRefAllocFrequency) { ! System.out.format( "minSize = %d, maxSize = %d, freq = %d%n", minSize, maxSize, semiRefAllocFrequency ); ! long counter = 0; - long multiplier = maxSize - minSize; LinkedList<SoftReference> arrSoftRefs = new LinkedList(); LinkedList arrObjects = new LinkedList(); long numberOfNotNulledObjects = 0; - long oomSoftArraySize = 0; try { - while (true) { - // Keep every Xth object to make sure we hit OOM pretty fast - if (counter % semiRefAllocFrequency != 0) { - long allocationSize = ((int) (rndGenerator.nextDouble() * multiplier)) - + minSize; - arrObjects.add(new byte[(int)allocationSize]); - } else { - arrSoftRefs.add(new SoftReference(new Object())); - } ! counter++; ! if (counter == Long.MAX_VALUE) { ! counter = 0; } } } catch (OutOfMemoryError oome) { - // Clear allocated ballast, so we don't get another OOM. arrObjects = null; ! ! // Get the number of soft refs first, so we don't trigger ! // another OOM. ! oomSoftArraySize = arrSoftRefs.size(); for (SoftReference sr : arrSoftRefs) { Object o = sr.get(); if (o != null) { --- 24,109 ---- /** * @test TestSoftReferencesBehaviorOnOOME * @key gc * @summary Tests that all SoftReferences has been cleared at time of OOM. * @library /testlibrary * @build TestSoftReferencesBehaviorOnOOME * @run main/othervm -Xmx128m TestSoftReferencesBehaviorOnOOME 512 2k * @run main/othervm -Xmx128m TestSoftReferencesBehaviorOnOOME 128k 256k ! * @run main/othervm -Xmx128m TestSoftReferencesBehaviorOnOOME 2k 32k */ import com.oracle.java.testlibrary.Utils; + import com.oracle.java.testlibrary.Asserts; import java.lang.ref.SoftReference; import java.util.LinkedList; import java.util.Random; public class TestSoftReferencesBehaviorOnOOME { ! /** ! * Test generates a lot of soft references to objects with random payloads. ! * Then it provokes OOME and checks that all SoftReferences has been gone ! * @param args - [minSize] [maxSize] [freq] ! * where ! * - minSize - min size of random objects ! * - maxSize - max size of random objects ! */ public static void main(String[] args) { ! long minSize = DEFAULT_MIN_SIZE; ! long maxSize = DEFAULT_MAX_SIZE; if ( args.length >= 2) { maxSize = getBytesCount(args[1]); } if ( args.length >= 1) { minSize = getBytesCount(args[0]); } ! new TestSoftReferencesBehaviorOnOOME().softReferencesOom(minSize, maxSize); } /** * Test that all SoftReferences has been cleared at time of OOM. */ ! void softReferencesOom(long minSize, long maxSize) { ! System.out.format( "minSize = %d, maxSize = %d%n", minSize, maxSize ); LinkedList<SoftReference> arrSoftRefs = new LinkedList(); + staticRef = arrSoftRefs; LinkedList arrObjects = new LinkedList(); + staticRef = arrObjects; + + long multiplier = maxSize - minSize; long numberOfNotNulledObjects = 0; try { ! // Lets allocate as many as we can - taking size of all SoftRerefences ! // by minimum. So it can provoke some GC but we surely will allocate enough. ! long numSofts = (long) ((0.95 * Runtime.getRuntime().totalMemory()) / minSize); ! System.out.println("num Soft: " + numSofts); ! ! while (numSofts-- > 0) { ! int allocationSize = ((int) (RND_GENERATOR.nextDouble() * multiplier)) ! + (int)minSize; ! arrSoftRefs.add(new SoftReference(new byte[allocationSize])); } + + System.out.println("free: " + Runtime.getRuntime().freeMemory()); + + // provoke OOME. + while (true) { + arrObjects.add(new byte[(int) Runtime.getRuntime().totalMemory()]); } + } catch (OutOfMemoryError oome) { + // Clear allocated ballast, so we don't get another OOM. + staticRef = null; arrObjects = null; ! long oomSoftArraySize = arrSoftRefs.size(); for (SoftReference sr : arrSoftRefs) { Object o = sr.get(); if (o != null) {
*** 107,136 **** } } // Make sure we clear all refs before we return failure arrSoftRefs = null; ! ! if (numberOfNotNulledObjects > 0) { ! throw new RuntimeException(numberOfNotNulledObjects + " out of " + oomSoftArraySize + " SoftReferences was not " ! + "null at time of OutOfMemoryError"); ! } } finally { ! arrSoftRefs = null; ! arrObjects = null; } } private static final long getBytesCount(String arg) { String postfixes = "kMGT"; long mod = 1; if (arg.trim().length() >= 2) { ! mod = postfixes.indexOf( ! arg.trim().charAt(arg.length() - 1) ! ); if (mod != -1) { mod = (long) Math.pow(1024, mod+1); arg = arg.substring(0, arg.length() - 1); } else { --- 111,137 ---- } } // Make sure we clear all refs before we return failure arrSoftRefs = null; ! Asserts.assertFalse(numberOfNotNulledObjects > 0, ! "" + numberOfNotNulledObjects + " out of " + oomSoftArraySize + " SoftReferences was not " ! + "null at time of OutOfMemoryError" ! ); } finally { ! Asserts.assertTrue(arrObjects == null, "OOME hasn't been provoked"); ! Asserts.assertTrue(arrSoftRefs == null, "OOME hasn't been provoked"); } } private static final long getBytesCount(String arg) { String postfixes = "kMGT"; long mod = 1; if (arg.trim().length() >= 2) { ! mod = postfixes.indexOf(arg.trim().charAt(arg.length() - 1)); if (mod != -1) { mod = (long) Math.pow(1024, mod+1); arg = arg.substring(0, arg.length() - 1); } else {
*** 139,147 **** } return Long.parseLong(arg) * mod; } private static final long DEFAULT_MIN_SIZE = 512; private static final long DEFAULT_MAX_SIZE = 1024; ! private static final int DEFAULT_FREQUENCY = 4; } --- 140,149 ---- } return Long.parseLong(arg) * mod; } + private static final Random RND_GENERATOR = Utils.getRandomInstance(); private static final long DEFAULT_MIN_SIZE = 512; private static final long DEFAULT_MAX_SIZE = 1024; ! private static Object staticRef; // to prevent compile optimisations }