Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/java.base/share/classes/java/nio/Buffer.java
Original file line number Diff line number Diff line change
Expand Up @@ -847,6 +847,11 @@ public ByteBuffer newHeapByteBuffer(byte[] hb, int offset, int capacity, MemoryS
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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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}.
*/
Expand Down
33 changes: 26 additions & 7 deletions src/java.base/share/classes/sun/nio/ch/Util.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,15 @@
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
Expand Down Expand Up @@ -221,7 +225,8 @@ public static ByteBuffer getTemporaryDirectBuffer(int size) {
// 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();
Expand All @@ -236,7 +241,8 @@ public static ByteBuffer getTemporaryDirectBuffer(int size) {
buf = cache.removeFirst();
free(buf);
}
return ByteBuffer.allocateDirect(size);
long addr = unsafe.allocateMemory(size);
return NIO_ACCESS.newDirectByteBuffer(addr, size);
}
}

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

/**
Expand All @@ -274,12 +280,23 @@ public static void releaseTemporaryDirectBuffer(ByteBuffer buf) {
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)) {
Expand All @@ -302,6 +319,8 @@ static void offerFirstTemporaryDirectBuffer(ByteBuffer buf) {
* 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)) {
Expand All @@ -321,7 +340,7 @@ static void offerLastTemporaryDirectBuffer(ByteBuffer buf) {
* Frees the memory for the given direct buffer
*/
private static void free(ByteBuffer buf) {
((DirectBuffer)buf).cleaner().clean();
unsafe.freeMemory(((DirectBuffer)buf).address());
}


Expand Down
3 changes: 0 additions & 3 deletions test/jdk/ProblemList-Virtual.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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