# HG changeset patch # User khazra # Date 1342481411 25200 # Node ID 58f0a08234963d1daeb914b8c6950a7b68eb920f # Parent c342d30b70da6a4243d84162058682e25bba2da9 7177045: Rework the TestProviderLeak.java regression test, it is too fragile to low memory errors. Summary: Increase Xmx to 20 MB and add mechanisms to eat up most of the JVM free memory. Reviewed-by: wetmore Contributed-by: dan.xu@oracle.com diff -r c342d30b70da -r 58f0a0823496 jdk/test/com/sun/crypto/provider/KeyFactory/TestProviderLeak.java --- a/jdk/test/com/sun/crypto/provider/KeyFactory/TestProviderLeak.java Mon Jul 16 22:38:49 2012 +0100 +++ b/jdk/test/com/sun/crypto/provider/KeyFactory/TestProviderLeak.java Mon Jul 16 16:30:11 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,50 +28,111 @@ * LoginContext * @author Brad Wetmore * - * @run main/othervm -Xmx2m -XX:OldSize=1m -XX:NewSize=512k TestProviderLeak + * @run main/othervm -Xmx20m TestProviderLeak * - * The original test invocation is below, but had to use the above - * workaround for bug 6923123. - * - * run main/othervm -Xmx2m TestProviderLeak */ /* - * We force the leak to become a problem by specifying the minimum - * size heap we can (above). In current runs on a server and client - * machine, it took roughly 220-240 iterations to have the memory leak - * shut down other operations. It complained about "Unable to verify - * the SunJCE provider." + * We force the leak to become a problem by eating up most JVM free memory. + * In current runs on a server and client machine, it took roughly 50-150 + * iterations to have the memory leak or time-out shut down other operations. + * It complained about "JCE cannot authenticate the provider SunJCE" or timed + * out. */ import javax.crypto.*; import javax.crypto.spec.*; +import java.util.*; +import java.util.concurrent.*; + public class TestProviderLeak { + private static final int MB = 1024 * 1024; + // Currently, 3MB heap size is reserved for running testing iterations. + // It is tweaked to make sure the test quickly triggers the memory leak + // or throws out TimeoutException. + private static final int RESERVATION = 3; + // The maximum time, 5 seconds, to wait for each iteration. + private static final int TIME_OUT = 5; + + private static Deque eatupMemory() throws Exception { + dumpMemoryStats("Before memory allocation"); + + Deque data = new ArrayDeque(); + boolean hasException = false; + while (!hasException) { + byte [] megaByte; + try { + megaByte = new byte [MB]; + data.add(megaByte); + } catch (OutOfMemoryError e) { + System.out.println("OOME is thrown when allocating " + + data.size() + "MB memory."); + megaByte = null; + + for (int j = 0; j < RESERVATION && !data.isEmpty(); j++) { + data.removeLast(); + } + System.gc(); + hasException = true; + } + } + dumpMemoryStats("After memory allocation"); + + return data; + } + private static void dumpMemoryStats(String s) throws Exception { Runtime rt = Runtime.getRuntime(); - System.out.println(s + ":\t" + - rt.freeMemory() + " bytes free"); + System.out.println(s + ":\t" + + rt.freeMemory() + " bytes free"); } public static void main(String [] args) throws Exception { - SecretKeyFactory skf = + // Eat up memory + Deque dummyData = eatupMemory(); + assert (dummyData != null); + + // Prepare the test + final SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1", "SunJCE"); - PBEKeySpec pbeKS = new PBEKeySpec( + final PBEKeySpec pbeKS = new PBEKeySpec( "passPhrase".toCharArray(), new byte [] { 0 }, 5, 512); - for (int i = 0; i <= 1000; i++) { - try { - skf.generateSecret(pbeKS); + + ExecutorService executor = Executors.newSingleThreadExecutor(); + Callable task = new Callable() { + @Override + public SecretKey call() throws Exception { + return skf.generateSecret(pbeKS); + } + }; + + // Start testing iteration + try { + for (int i = 0; i <= 1000; i++) { if ((i % 20) == 0) { - // Calling gc() isn't dependable, but doesn't hurt. - // Gives better output in leak cases. + // Calling gc() isn't dependable, but doesn't hurt. + // Gives better output in leak cases. System.gc(); dumpMemoryStats("Iteration " + i); } - } catch (Exception e) { - dumpMemoryStats("\nException seen at iteration " + i); - throw e; + + Future future = executor.submit(task); + + try { + future.get(TIME_OUT, TimeUnit.SECONDS); + } catch (Exception e) { + dumpMemoryStats("\nException seen at iteration " + i); + throw e; + } } + } finally { + // JTReg will time out after two minutes. Proactively release + // the memory to avoid JTReg time-out situation. + dummyData = null; + System.gc(); + dumpMemoryStats("Memory dereference"); + executor.shutdownNow(); } } }