--- old/src/java.base/share/classes/java/nio/Bits.java 2016-03-28 16:44:46.497080164 +0200 +++ new/src/java.base/share/classes/java/nio/Bits.java 2016-03-28 16:44:46.398081878 +0200 @@ -25,13 +25,14 @@ package java.nio; -import java.util.concurrent.atomic.AtomicLong; - import jdk.internal.misc.JavaNioAccess; -import jdk.internal.misc.JavaLangRefAccess; import jdk.internal.misc.SharedSecrets; import jdk.internal.misc.Unsafe; import jdk.internal.misc.VM; +import jdk.internal.ref.CleanerFactory; + +import java.util.concurrent.atomic.AtomicLong; +import java.util.function.BooleanSupplier; /** * Access to bits, native and otherwise. @@ -603,12 +604,6 @@ private static final AtomicLong count = new AtomicLong(); private static volatile boolean memoryLimitSet; - // max. number of sleeps during try-reserving with exponentially - // increasing delay before throwing OutOfMemoryError: - // 1, 2, 4, 8, 16, 32, 64, 128, 256 (total 511 ms ~ 0.5 s) - // which means that OOME will be thrown after 0.5 s of trying - private static final int MAX_SLEEPS = 9; - // These methods should be called whenever direct memory is allocated or // freed. They allow the user to control the amount of direct memory // which a process may access. All sizes are specified in bytes. @@ -619,57 +614,15 @@ memoryLimitSet = true; } - // optimist! - if (tryReserveMemory(size, cap)) { - return; - } - - final JavaLangRefAccess jlra = SharedSecrets.getJavaLangRefAccess(); - - // retry while helping enqueue pending Reference objects - // which includes executing pending Cleaner(s) which includes - // Cleaner(s) that free direct buffer memory - while (jlra.tryHandlePendingReference()) { - if (tryReserveMemory(size, cap)) { - return; - } - } - - // trigger VM's Reference processing - System.gc(); - - // a retry loop with exponential back-off delays - // (this gives VM some time to do it's job) - boolean interrupted = false; - try { - long sleepTime = 1; - int sleeps = 0; - while (true) { - if (tryReserveMemory(size, cap)) { - return; - } - if (sleeps >= MAX_SLEEPS) { - break; + if (!CleanerFactory.cleaner().retryWhileHelpingClean( + new BooleanSupplier() { + @Override + public boolean getAsBoolean() { + return tryReserveMemory(size, cap); } - if (!jlra.tryHandlePendingReference()) { - try { - Thread.sleep(sleepTime); - sleepTime <<= 1; - sleeps++; - } catch (InterruptedException e) { - interrupted = true; - } - } - } - + })) { // no luck throw new OutOfMemoryError("Direct buffer memory"); - - } finally { - if (interrupted) { - // don't swallow interrupts - Thread.currentThread().interrupt(); - } } }