8344882: (bf) Temporary direct buffers should not count against the upper limit on direct buffer memory

Reviewed-by: alanb
This commit is contained in:
Brian Burkhalter 2024-11-27 16:14:03 +00:00
parent 75f3ec77e4
commit 0312694c46
5 changed files with 38 additions and 11 deletions

View File

@ -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) {

View File

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

View File

@ -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}.
*/

View File

@ -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,7 +253,7 @@ public class Util {
public static ByteBuffer getTemporaryAlignedDirectBuffer(int size,
int alignment) {
if (isBufferTooLarge(size)) {
return ByteBuffer.allocateDirect(size + alignment - 1)
return getTemporaryDirectBuffer(size + alignment - 1)
.alignedSlice(alignment);
}
@ -263,7 +269,7 @@ public class Util {
free(buf);
}
}
return ByteBuffer.allocateDirect(size + alignment - 1)
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());
}

View File

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