< 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 >