< prev index next >

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

Print this page

        

*** 24,39 **** */ 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. */ --- 24,37 ---- */ package java.nio; import java.util.concurrent.atomic.AtomicLong; + import java.util.concurrent.locks.ReentrantLock; ! import jdk.internal.misc.*; ! import jdk.internal.ref.CleanerFactory; /** * Access to bits, native and otherwise. */
*** 607,616 **** --- 605,616 ---- // 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; + private static final ReentrantLock reservationQueue = new ReentrantLock(true); + // 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) {
*** 622,677 **** // 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) { --- 622,664 ---- // optimist! if (tryReserveMemory(size, cap)) { return; } ! // reservation threads that don't succeed at first must queue so that ! // some of them don't starve while others succeed. ! reservationQueue.lock(); ! try { ! JavaLangRefAccess jlra = SharedSecrets.getJavaLangRefAccess(); ! // retry reservation while helping the Cleaner thread process enqueued ! // Cleanable(s) which includes the ones that free direct buffer memory ! // until the queue drains out ! do { if (tryReserveMemory(size, cap)) { return; } ! } while (jlra.cleanNextPendingCleanable(CleanerFactory.cleaner())); ! // trigger GC's Reference discovery System.gc(); + // make sure all newly discovered Reference(s) are enqueued + jlra.enqueuePendingReferences(); ! // retry reservation while helping the Cleaner thread process enqueued ! // Cleanable(s) which includes the ones that free direct buffer memory ! // until the queue drains out ! do { if (tryReserveMemory(size, cap)) { return; } ! } while (jlra.cleanNextPendingCleanable(CleanerFactory.cleaner())); // no luck throw new OutOfMemoryError("Direct buffer memory"); } finally { ! reservationQueue.unlock(); } } private static boolean tryReserveMemory(long size, int cap) {
< prev index next >