8344882: (bf) Temporary direct buffers should not count against the upper limit on direct buffer memory
Reviewed-by: alanb
This commit is contained in:
parent
75f3ec77e4
commit
0312694c46
@ -847,6 +847,11 @@ public abstract sealed class Buffer
|
||||
return new HeapByteBuffer(hb, -1, 0, capacity, capacity, offset, segment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer newDirectByteBuffer(long addr, int cap) {
|
||||
return new DirectByteBuffer(addr, cap);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
@Override
|
||||
public Object getBufferBase(Buffer buffer) {
|
||||
|
@ -159,9 +159,10 @@ class Direct$Type$Buffer$RW$$BO$
|
||||
}
|
||||
|
||||
// Invoked only by JNI: NewDirectByteBuffer(void*, long)
|
||||
// and JavaNioAccess.newDirectByteBuffer(int).
|
||||
// The long-valued capacity is restricted to int range.
|
||||
//
|
||||
private Direct$Type$Buffer(long addr, long cap) {
|
||||
Direct$Type$Buffer(long addr, long cap) {
|
||||
super(-1, 0, checkCapacity(cap), (int)cap, null);
|
||||
address = addr;
|
||||
cleaner = null;
|
||||
|
@ -67,6 +67,11 @@ public interface JavaNioAccess {
|
||||
*/
|
||||
ByteBuffer newHeapByteBuffer(byte[] hb, int offset, int capacity, MemorySegment segment);
|
||||
|
||||
/**
|
||||
* Used by {@code sun.nio.ch.Util}.
|
||||
*/
|
||||
ByteBuffer newDirectByteBuffer(long addr, int cap);
|
||||
|
||||
/**
|
||||
* Used by {@code jdk.internal.foreign.Utils}.
|
||||
*/
|
||||
|
@ -36,11 +36,15 @@ import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
import jdk.internal.access.JavaNioAccess;
|
||||
import jdk.internal.access.SharedSecrets;
|
||||
import jdk.internal.misc.TerminatingThreadLocal;
|
||||
import jdk.internal.misc.Unsafe;
|
||||
|
||||
public class Util {
|
||||
|
||||
private static final JavaNioAccess NIO_ACCESS = SharedSecrets.getJavaNioAccess();
|
||||
|
||||
// -- Caches --
|
||||
|
||||
// The number of temp buffers in our pool
|
||||
@ -221,7 +225,8 @@ public class Util {
|
||||
// to remove the buffer from the cache (as this method does
|
||||
// below) given that we won't put the new buffer in the cache.
|
||||
if (isBufferTooLarge(size)) {
|
||||
return ByteBuffer.allocateDirect(size);
|
||||
long addr = unsafe.allocateMemory(size);
|
||||
return NIO_ACCESS.newDirectByteBuffer(addr, size);
|
||||
}
|
||||
|
||||
BufferCache cache = bufferCache.get();
|
||||
@ -236,7 +241,8 @@ public class Util {
|
||||
buf = cache.removeFirst();
|
||||
free(buf);
|
||||
}
|
||||
return ByteBuffer.allocateDirect(size);
|
||||
long addr = unsafe.allocateMemory(size);
|
||||
return NIO_ACCESS.newDirectByteBuffer(addr, size);
|
||||
}
|
||||
}
|
||||
|
||||
@ -247,8 +253,8 @@ public class Util {
|
||||
public static ByteBuffer getTemporaryAlignedDirectBuffer(int size,
|
||||
int alignment) {
|
||||
if (isBufferTooLarge(size)) {
|
||||
return ByteBuffer.allocateDirect(size + alignment - 1)
|
||||
.alignedSlice(alignment);
|
||||
return getTemporaryDirectBuffer(size + alignment - 1)
|
||||
.alignedSlice(alignment);
|
||||
}
|
||||
|
||||
BufferCache cache = bufferCache.get();
|
||||
@ -263,8 +269,8 @@ public class Util {
|
||||
free(buf);
|
||||
}
|
||||
}
|
||||
return ByteBuffer.allocateDirect(size + alignment - 1)
|
||||
.alignedSlice(alignment);
|
||||
return getTemporaryDirectBuffer(size + alignment - 1)
|
||||
.alignedSlice(alignment);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -274,12 +280,23 @@ public class Util {
|
||||
offerFirstTemporaryDirectBuffer(buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the underling byte buffer if the given byte buffer is
|
||||
* an aligned slice.
|
||||
*/
|
||||
private static ByteBuffer unwrapIfAlignedSlice(ByteBuffer buf) {
|
||||
var parent = (ByteBuffer) ((DirectBuffer) buf).attachment();
|
||||
return (parent != null) ? parent : buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases a temporary buffer by returning to the cache or freeing it. If
|
||||
* returning to the cache then insert it at the start so that it is
|
||||
* likely to be returned by a subsequent call to getTemporaryDirectBuffer.
|
||||
*/
|
||||
static void offerFirstTemporaryDirectBuffer(ByteBuffer buf) {
|
||||
buf = unwrapIfAlignedSlice(buf);
|
||||
|
||||
// If the buffer is too large for the cache we don't have to
|
||||
// check the cache. We'll just free it.
|
||||
if (isBufferTooLarge(buf)) {
|
||||
@ -302,6 +319,8 @@ public class Util {
|
||||
* cache in same order that they were obtained.
|
||||
*/
|
||||
static void offerLastTemporaryDirectBuffer(ByteBuffer buf) {
|
||||
buf = unwrapIfAlignedSlice(buf);
|
||||
|
||||
// If the buffer is too large for the cache we don't have to
|
||||
// check the cache. We'll just free it.
|
||||
if (isBufferTooLarge(buf)) {
|
||||
@ -321,7 +340,7 @@ public class Util {
|
||||
* Frees the memory for the given direct buffer
|
||||
*/
|
||||
private static void free(ByteBuffer buf) {
|
||||
((DirectBuffer)buf).cleaner().clean();
|
||||
unsafe.freeMemory(((DirectBuffer)buf).address());
|
||||
}
|
||||
|
||||
|
||||
|
@ -69,6 +69,3 @@ java/util/Properties/StoreReproducibilityTest.java 0000000 generic-all
|
||||
java/util/Properties/StoreReproducibilityTest.java 0000000 generic-all
|
||||
javax/management/ImplementationVersion/ImplVersionTest.java 0000000 generic-all
|
||||
javax/management/remote/mandatory/version/ImplVersionTest.java 0000000 generic-all
|
||||
|
||||
# Direct buffer memory allocated before test launch
|
||||
java/nio/Buffer/LimitDirectMemory.java 8342849 generic-all
|
||||
|
Loading…
Reference in New Issue
Block a user