< prev index next >

src/java.base/share/classes/java/nio/Bits.java

Print this page

        

*** 23,39 **** * questions. */ 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; /** * Access to bits, native and otherwise. */ --- 23,40 ---- * questions. */ package java.nio; import jdk.internal.misc.JavaNioAccess; 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. */
*** 601,677 **** private static final AtomicLong reservedMemory = new AtomicLong(); private static final AtomicLong totalCapacity = new AtomicLong(); 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. static void reserveMemory(long size, int cap) { if (!memoryLimitSet && VM.initLevel() >= 1) { maxMemory = VM.maxDirectMemory(); 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 (!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(); - } } } private static boolean tryReserveMemory(long size, int cap) { --- 602,630 ---- private static final AtomicLong reservedMemory = new AtomicLong(); private static final AtomicLong totalCapacity = new AtomicLong(); private static final AtomicLong count = new AtomicLong(); private static volatile boolean memoryLimitSet; // 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. static void reserveMemory(long size, int cap) { if (!memoryLimitSet && VM.initLevel() >= 1) { maxMemory = VM.maxDirectMemory(); memoryLimitSet = true; } ! if (!CleanerFactory.cleaner().retryWhileHelpingClean( ! new BooleanSupplier() { ! @Override ! public boolean getAsBoolean() { ! return tryReserveMemory(size, cap); } ! })) { // no luck throw new OutOfMemoryError("Direct buffer memory"); } } private static boolean tryReserveMemory(long size, int cap) {
< prev index next >