From 50bf3b7bdcb20e4e7b993f9358a7f8eb4277dbe8 Mon Sep 17 00:00:00 2001 From: Dan Xu Date: Mon, 16 Jul 2012 16:30:11 -0700 Subject: [PATCH] 7177045: Rework the TestProviderLeak.java regression test, it is too fragile to low memory errors Increase Xmx to 20 MB and add mechanisms to eat up most of the JVM free memory. Reviewed-by: wetmore --- .../provider/KeyFactory/TestProviderLeak.java | 107 ++++++++++++++---- 1 file changed, 84 insertions(+), 23 deletions(-) diff --git a/jdk/test/com/sun/crypto/provider/KeyFactory/TestProviderLeak.java b/jdk/test/com/sun/crypto/provider/KeyFactory/TestProviderLeak.java index 1c1c0e0de0a..04fa96a9813 100644 --- a/jdk/test/com/sun/crypto/provider/KeyFactory/TestProviderLeak.java +++ b/jdk/test/com/sun/crypto/provider/KeyFactory/TestProviderLeak.java @@ -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(); } } }