mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 23:04:50 +02:00
8296024: Usage of DirectBuffer::address should be guarded
Reviewed-by: mcimadamore, alanb, psandoz, bpb
This commit is contained in:
parent
a9e6c62ba7
commit
84b927a05b
24 changed files with 635 additions and 430 deletions
|
@ -25,6 +25,8 @@
|
|||
|
||||
package com.sun.crypto.provider;
|
||||
|
||||
import jdk.internal.access.JavaNioAccess;
|
||||
import jdk.internal.access.SharedSecrets;
|
||||
import jdk.internal.misc.Unsafe;
|
||||
import sun.nio.ch.DirectBuffer;
|
||||
import sun.security.jca.JCAUtil;
|
||||
|
@ -92,6 +94,8 @@ abstract class GaloisCounterMode extends CipherSpi {
|
|||
|
||||
static final byte[] EMPTY_BUF = new byte[0];
|
||||
|
||||
private static final JavaNioAccess NIO_ACCESS = SharedSecrets.getJavaNioAccess();
|
||||
|
||||
private boolean initialized = false;
|
||||
|
||||
SymmetricCipher blockCipher;
|
||||
|
@ -909,6 +913,8 @@ abstract class GaloisCounterMode extends CipherSpi {
|
|||
*/
|
||||
ByteBuffer overlapDetection(ByteBuffer src, ByteBuffer dst) {
|
||||
if (src.isDirect() && dst.isDirect()) {
|
||||
// The use of DirectBuffer::address below need not be guarded as
|
||||
// no access is made to actual memory.
|
||||
DirectBuffer dsrc = (DirectBuffer) src;
|
||||
DirectBuffer ddst = (DirectBuffer) dst;
|
||||
|
||||
|
@ -946,7 +952,6 @@ abstract class GaloisCounterMode extends CipherSpi {
|
|||
((DirectBuffer) dst).address() - dstaddr + dst.position()) {
|
||||
return dst;
|
||||
}
|
||||
|
||||
} else if (!src.isDirect() && !dst.isDirect()) {
|
||||
// if src is read only, then we need a copy
|
||||
if (!src.isReadOnly()) {
|
||||
|
@ -1585,8 +1590,13 @@ abstract class GaloisCounterMode extends CipherSpi {
|
|||
int ofs = dst.arrayOffset() + dst.position();
|
||||
Arrays.fill(dst.array(), ofs , ofs + len, (byte)0);
|
||||
} else {
|
||||
Unsafe.getUnsafe().setMemory(((DirectBuffer)dst).address(),
|
||||
len + dst.position(), (byte)0);
|
||||
NIO_ACCESS.acquireSession(dst);
|
||||
try {
|
||||
Unsafe.getUnsafe().setMemory(((DirectBuffer)dst).address(),
|
||||
len + dst.position(), (byte) 0);
|
||||
} finally {
|
||||
NIO_ACCESS.releaseSession(dst);
|
||||
}
|
||||
}
|
||||
throw new AEADBadTagException("Tag mismatch");
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ import jdk.internal.vm.annotation.ForceInline;
|
|||
|
||||
import java.io.FileDescriptor;
|
||||
import java.lang.foreign.MemorySegment;
|
||||
import java.lang.ref.Reference;
|
||||
import java.util.Objects;
|
||||
import java.util.Spliterator;
|
||||
|
||||
|
@ -779,6 +780,7 @@ public abstract sealed class Buffer
|
|||
// setup access to this package in SharedSecrets
|
||||
SharedSecrets.setJavaNioAccess(
|
||||
new JavaNioAccess() {
|
||||
|
||||
@Override
|
||||
public BufferPool getDirectBufferPool() {
|
||||
return Bits.BUFFER_POOL;
|
||||
|
@ -824,16 +826,34 @@ public abstract sealed class Buffer
|
|||
}
|
||||
|
||||
@Override
|
||||
public Runnable acquireSession(Buffer buffer, boolean async) {
|
||||
var session = buffer.session();
|
||||
if (session == null) {
|
||||
return null;
|
||||
public void acquireSession(Buffer buffer) {
|
||||
var scope = buffer.session();
|
||||
if (scope != null) {
|
||||
scope.acquire0();
|
||||
}
|
||||
if (async && session.ownerThread() != null) {
|
||||
throw new IllegalStateException("Confined session not supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void releaseSession(Buffer buffer) {
|
||||
try {
|
||||
var scope = buffer.session();
|
||||
if (scope != null) {
|
||||
scope.release0();
|
||||
}
|
||||
} finally {
|
||||
Reference.reachabilityFence(buffer);
|
||||
}
|
||||
session.acquire0();
|
||||
return session::release0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isThreadConfined(Buffer buffer) {
|
||||
var scope = buffer.session();
|
||||
return scope != null && scope.ownerThread() != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSession(Buffer buffer) {
|
||||
return buffer.session() != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -25,11 +25,13 @@
|
|||
|
||||
package java.util.zip;
|
||||
|
||||
import java.lang.ref.Reference;
|
||||
import java.nio.ByteBuffer;
|
||||
import sun.nio.ch.DirectBuffer;
|
||||
|
||||
import jdk.internal.util.Preconditions;
|
||||
import jdk.internal.vm.annotation.IntrinsicCandidate;
|
||||
import sun.nio.ch.DirectBuffer;
|
||||
|
||||
import static java.util.zip.ZipUtils.NIO_ACCESS;
|
||||
|
||||
/**
|
||||
* A class that can be used to compute the Adler-32 checksum of a data
|
||||
|
@ -96,10 +98,11 @@ public class Adler32 implements Checksum {
|
|||
if (rem <= 0)
|
||||
return;
|
||||
if (buffer.isDirect()) {
|
||||
NIO_ACCESS.acquireSession(buffer);
|
||||
try {
|
||||
adler = updateByteBuffer(adler, ((DirectBuffer)buffer).address(), pos, rem);
|
||||
} finally {
|
||||
Reference.reachabilityFence(buffer);
|
||||
NIO_ACCESS.releaseSession(buffer);
|
||||
}
|
||||
} else if (buffer.hasArray()) {
|
||||
adler = updateBytes(adler, buffer.array(), pos + buffer.arrayOffset(), rem);
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
|
||||
package java.util.zip;
|
||||
|
||||
import java.lang.ref.Reference;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Objects;
|
||||
|
||||
|
@ -33,6 +32,8 @@ import sun.nio.ch.DirectBuffer;
|
|||
import jdk.internal.util.Preconditions;
|
||||
import jdk.internal.vm.annotation.IntrinsicCandidate;
|
||||
|
||||
import static java.util.zip.ZipUtils.NIO_ACCESS;
|
||||
|
||||
/**
|
||||
* A class that can be used to compute the CRC-32 of a data stream.
|
||||
*
|
||||
|
@ -96,10 +97,11 @@ public class CRC32 implements Checksum {
|
|||
if (rem <= 0)
|
||||
return;
|
||||
if (buffer.isDirect()) {
|
||||
NIO_ACCESS.acquireSession(buffer);
|
||||
try {
|
||||
crc = updateByteBuffer(crc, ((DirectBuffer)buffer).address(), pos, rem);
|
||||
} finally {
|
||||
Reference.reachabilityFence(buffer);
|
||||
NIO_ACCESS.releaseSession(buffer);
|
||||
}
|
||||
} else if (buffer.hasArray()) {
|
||||
crc = updateBytes(crc, buffer.array(), pos + buffer.arrayOffset(), rem);
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
*/
|
||||
package java.util.zip;
|
||||
|
||||
import java.lang.ref.Reference;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
|
@ -33,6 +32,8 @@ import jdk.internal.util.Preconditions;
|
|||
import jdk.internal.vm.annotation.IntrinsicCandidate;
|
||||
import sun.nio.ch.DirectBuffer;
|
||||
|
||||
import static java.util.zip.ZipUtils.NIO_ACCESS;
|
||||
|
||||
/**
|
||||
* A class that can be used to compute the CRC-32C of a data stream.
|
||||
*
|
||||
|
@ -171,11 +172,12 @@ public final class CRC32C implements Checksum {
|
|||
}
|
||||
|
||||
if (buffer.isDirect()) {
|
||||
NIO_ACCESS.acquireSession(buffer);
|
||||
try {
|
||||
crc = updateDirectByteBuffer(crc, ((DirectBuffer) buffer).address(),
|
||||
crc = updateDirectByteBuffer(crc, ((DirectBuffer)buffer).address(),
|
||||
pos, limit);
|
||||
} finally {
|
||||
Reference.reachabilityFence(buffer);
|
||||
NIO_ACCESS.releaseSession(buffer);
|
||||
}
|
||||
} else if (buffer.hasArray()) {
|
||||
crc = updateBytes(crc, buffer.array(), pos + buffer.arrayOffset(),
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
package java.util.zip;
|
||||
|
||||
import java.lang.ref.Cleaner.Cleanable;
|
||||
import java.lang.ref.Reference;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ReadOnlyBufferException;
|
||||
import java.util.Objects;
|
||||
|
@ -35,6 +34,8 @@ import jdk.internal.ref.CleanerFactory;
|
|||
import jdk.internal.util.Preconditions;
|
||||
import sun.nio.ch.DirectBuffer;
|
||||
|
||||
import static java.util.zip.ZipUtils.NIO_ACCESS;
|
||||
|
||||
/**
|
||||
* This class provides support for general purpose compression using the
|
||||
* popular ZLIB compression library. The ZLIB compression library was
|
||||
|
@ -337,11 +338,12 @@ public class Deflater {
|
|||
int remaining = Math.max(dictionary.limit() - position, 0);
|
||||
ensureOpen();
|
||||
if (dictionary.isDirect()) {
|
||||
long address = ((DirectBuffer) dictionary).address();
|
||||
NIO_ACCESS.acquireSession(dictionary);
|
||||
try {
|
||||
long address = ((DirectBuffer) dictionary).address();
|
||||
setDictionaryBuffer(zsRef.address(), address + position, remaining);
|
||||
} finally {
|
||||
Reference.reachabilityFence(dictionary);
|
||||
NIO_ACCESS.releaseSession(dictionary);
|
||||
}
|
||||
} else {
|
||||
byte[] array = ZipUtils.getBufferArray(dictionary);
|
||||
|
@ -587,6 +589,7 @@ public class Deflater {
|
|||
inputPos = input.position();
|
||||
int inputRem = Math.max(input.limit() - inputPos, 0);
|
||||
if (input.isDirect()) {
|
||||
NIO_ACCESS.acquireSession(input);
|
||||
try {
|
||||
long inputAddress = ((DirectBuffer) input).address();
|
||||
result = deflateBufferBytes(zsRef.address(),
|
||||
|
@ -594,7 +597,7 @@ public class Deflater {
|
|||
output, off, len,
|
||||
flush, params);
|
||||
} finally {
|
||||
Reference.reachabilityFence(input);
|
||||
NIO_ACCESS.releaseSession(input);
|
||||
}
|
||||
} else {
|
||||
byte[] inputArray = ZipUtils.getBufferArray(input);
|
||||
|
@ -709,14 +712,15 @@ public class Deflater {
|
|||
if (input == null) {
|
||||
inputPos = this.inputPos;
|
||||
if (output.isDirect()) {
|
||||
long outputAddress = ((DirectBuffer) output).address();
|
||||
NIO_ACCESS.acquireSession(output);
|
||||
try {
|
||||
long outputAddress = ((DirectBuffer) output).address();
|
||||
result = deflateBytesBuffer(zsRef.address(),
|
||||
inputArray, inputPos, inputLim - inputPos,
|
||||
outputAddress + outputPos, outputRem,
|
||||
flush, params);
|
||||
} finally {
|
||||
Reference.reachabilityFence(output);
|
||||
NIO_ACCESS.releaseSession(output);
|
||||
}
|
||||
} else {
|
||||
byte[] outputArray = ZipUtils.getBufferArray(output);
|
||||
|
@ -730,17 +734,19 @@ public class Deflater {
|
|||
inputPos = input.position();
|
||||
int inputRem = Math.max(input.limit() - inputPos, 0);
|
||||
if (input.isDirect()) {
|
||||
long inputAddress = ((DirectBuffer) input).address();
|
||||
NIO_ACCESS.acquireSession(input);
|
||||
try {
|
||||
long inputAddress = ((DirectBuffer) input).address();
|
||||
if (output.isDirect()) {
|
||||
long outputAddress = outputPos + ((DirectBuffer) output).address();
|
||||
NIO_ACCESS.acquireSession(output);
|
||||
try {
|
||||
long outputAddress = outputPos + ((DirectBuffer) output).address();
|
||||
result = deflateBufferBuffer(zsRef.address(),
|
||||
inputAddress + inputPos, inputRem,
|
||||
outputAddress, outputRem,
|
||||
flush, params);
|
||||
} finally {
|
||||
Reference.reachabilityFence(output);
|
||||
NIO_ACCESS.releaseSession(output);
|
||||
}
|
||||
} else {
|
||||
byte[] outputArray = ZipUtils.getBufferArray(output);
|
||||
|
@ -751,20 +757,21 @@ public class Deflater {
|
|||
flush, params);
|
||||
}
|
||||
} finally {
|
||||
Reference.reachabilityFence(input);
|
||||
NIO_ACCESS.releaseSession(input);
|
||||
}
|
||||
} else {
|
||||
byte[] inputArray = ZipUtils.getBufferArray(input);
|
||||
int inputOffset = ZipUtils.getBufferOffset(input);
|
||||
if (output.isDirect()) {
|
||||
long outputAddress = ((DirectBuffer) output).address();
|
||||
NIO_ACCESS.acquireSession(output);
|
||||
try {
|
||||
long outputAddress = ((DirectBuffer) output).address();
|
||||
result = deflateBytesBuffer(zsRef.address(),
|
||||
inputArray, inputOffset + inputPos, inputRem,
|
||||
outputAddress + outputPos, outputRem,
|
||||
flush, params);
|
||||
} finally {
|
||||
Reference.reachabilityFence(output);
|
||||
NIO_ACCESS.releaseSession(output);
|
||||
}
|
||||
} else {
|
||||
byte[] outputArray = ZipUtils.getBufferArray(output);
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
package java.util.zip;
|
||||
|
||||
import java.lang.ref.Cleaner.Cleanable;
|
||||
import java.lang.ref.Reference;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ReadOnlyBufferException;
|
||||
import java.util.Objects;
|
||||
|
@ -35,6 +34,8 @@ import jdk.internal.ref.CleanerFactory;
|
|||
import jdk.internal.util.Preconditions;
|
||||
import sun.nio.ch.DirectBuffer;
|
||||
|
||||
import static java.util.zip.ZipUtils.NIO_ACCESS;
|
||||
|
||||
/**
|
||||
* This class provides support for general purpose decompression using the
|
||||
* popular ZLIB compression library. The ZLIB compression library was
|
||||
|
@ -259,11 +260,12 @@ public class Inflater {
|
|||
int remaining = Math.max(dictionary.limit() - position, 0);
|
||||
ensureOpen();
|
||||
if (dictionary.isDirect()) {
|
||||
long address = ((DirectBuffer) dictionary).address();
|
||||
NIO_ACCESS.acquireSession(dictionary);
|
||||
try {
|
||||
long address = ((DirectBuffer) dictionary).address();
|
||||
setDictionaryBuffer(zsRef.address(), address + position, remaining);
|
||||
} finally {
|
||||
Reference.reachabilityFence(dictionary);
|
||||
NIO_ACCESS.releaseSession(dictionary);
|
||||
}
|
||||
} else {
|
||||
byte[] array = ZipUtils.getBufferArray(dictionary);
|
||||
|
@ -383,13 +385,14 @@ public class Inflater {
|
|||
try {
|
||||
int inputRem = Math.max(input.limit() - inputPos, 0);
|
||||
if (input.isDirect()) {
|
||||
NIO_ACCESS.acquireSession(input);
|
||||
try {
|
||||
long inputAddress = ((DirectBuffer) input).address();
|
||||
result = inflateBufferBytes(zsRef.address(),
|
||||
inputAddress + inputPos, inputRem,
|
||||
output, off, len);
|
||||
} finally {
|
||||
Reference.reachabilityFence(input);
|
||||
NIO_ACCESS.releaseSession(input);
|
||||
}
|
||||
} else {
|
||||
byte[] inputArray = ZipUtils.getBufferArray(input);
|
||||
|
@ -517,13 +520,14 @@ public class Inflater {
|
|||
inputPos = this.inputPos;
|
||||
try {
|
||||
if (output.isDirect()) {
|
||||
long outputAddress = ((DirectBuffer) output).address();
|
||||
NIO_ACCESS.acquireSession(output);
|
||||
try {
|
||||
long outputAddress = ((DirectBuffer) output).address();
|
||||
result = inflateBytesBuffer(zsRef.address(),
|
||||
inputArray, inputPos, inputLim - inputPos,
|
||||
outputAddress + outputPos, outputRem);
|
||||
} finally {
|
||||
Reference.reachabilityFence(output);
|
||||
NIO_ACCESS.releaseSession(output);
|
||||
}
|
||||
} else {
|
||||
byte[] outputArray = ZipUtils.getBufferArray(output);
|
||||
|
@ -541,16 +545,18 @@ public class Inflater {
|
|||
int inputRem = Math.max(input.limit() - inputPos, 0);
|
||||
try {
|
||||
if (input.isDirect()) {
|
||||
long inputAddress = ((DirectBuffer) input).address();
|
||||
NIO_ACCESS.acquireSession(input);
|
||||
try {
|
||||
long inputAddress = ((DirectBuffer) input).address();
|
||||
if (output.isDirect()) {
|
||||
long outputAddress = ((DirectBuffer) output).address();
|
||||
NIO_ACCESS.acquireSession(output);
|
||||
try {
|
||||
long outputAddress = ((DirectBuffer) output).address();
|
||||
result = inflateBufferBuffer(zsRef.address(),
|
||||
inputAddress + inputPos, inputRem,
|
||||
outputAddress + outputPos, outputRem);
|
||||
} finally {
|
||||
Reference.reachabilityFence(output);
|
||||
NIO_ACCESS.releaseSession(output);
|
||||
}
|
||||
} else {
|
||||
byte[] outputArray = ZipUtils.getBufferArray(output);
|
||||
|
@ -560,19 +566,20 @@ public class Inflater {
|
|||
outputArray, outputOffset + outputPos, outputRem);
|
||||
}
|
||||
} finally {
|
||||
Reference.reachabilityFence(input);
|
||||
NIO_ACCESS.releaseSession(input);
|
||||
}
|
||||
} else {
|
||||
byte[] inputArray = ZipUtils.getBufferArray(input);
|
||||
int inputOffset = ZipUtils.getBufferOffset(input);
|
||||
if (output.isDirect()) {
|
||||
long outputAddress = ((DirectBuffer) output).address();
|
||||
NIO_ACCESS.acquireSession(output);
|
||||
try {
|
||||
long outputAddress = ((DirectBuffer) output).address();
|
||||
result = inflateBytesBuffer(zsRef.address(),
|
||||
inputArray, inputOffset + inputPos, inputRem,
|
||||
outputAddress + outputPos, outputRem);
|
||||
} finally {
|
||||
Reference.reachabilityFence(output);
|
||||
NIO_ACCESS.releaseSession(output);
|
||||
}
|
||||
} else {
|
||||
byte[] outputArray = ZipUtils.getBufferArray(output);
|
||||
|
|
|
@ -36,10 +36,14 @@ import java.util.concurrent.TimeUnit;
|
|||
|
||||
import static java.util.zip.ZipConstants.ENDHDR;
|
||||
|
||||
import jdk.internal.access.JavaNioAccess;
|
||||
import jdk.internal.access.SharedSecrets;
|
||||
import jdk.internal.misc.Unsafe;
|
||||
|
||||
class ZipUtils {
|
||||
|
||||
static final JavaNioAccess NIO_ACCESS = SharedSecrets.getJavaNioAccess();
|
||||
|
||||
// used to adjust values between Windows and java epoch
|
||||
private static final long WINDOWS_EPOCH_IN_MICROSECONDS = -11644473600000000L;
|
||||
|
||||
|
|
|
@ -86,12 +86,26 @@ public interface JavaNioAccess {
|
|||
MemorySegment bufferSegment(Buffer buffer);
|
||||
|
||||
/**
|
||||
* Used by I/O operations to make a buffer's session non-closeable
|
||||
* (for the duration of the I/O operation) by acquiring the session.
|
||||
* Null is returned if the buffer has no scope, or acquiring is not
|
||||
* required to guarantee safety.
|
||||
* Used by operations to make a buffer's session non-closeable
|
||||
* (for the duration of the operation) by acquiring the session.
|
||||
* {@snippet lang = java:
|
||||
* acquireSession(buffer);
|
||||
* try {
|
||||
* performOperation(buffer);
|
||||
* } finally {
|
||||
* releaseSession(buffer);
|
||||
* }
|
||||
*}
|
||||
*
|
||||
* @see #releaseSession(Buffer)
|
||||
*/
|
||||
Runnable acquireSession(Buffer buffer, boolean async);
|
||||
void acquireSession(Buffer buffer);
|
||||
|
||||
void releaseSession(Buffer buffer);
|
||||
|
||||
boolean isThreadConfined(Buffer buffer);
|
||||
|
||||
boolean hasSession(Buffer buffer);
|
||||
|
||||
/**
|
||||
* Used by {@code jdk.internal.foreign.MappedMemorySegmentImpl} and byte buffer var handle views.
|
||||
|
|
|
@ -166,7 +166,9 @@ module java.base {
|
|||
jdk.jartool,
|
||||
jdk.jlink,
|
||||
jdk.jfr,
|
||||
jdk.net;
|
||||
jdk.net,
|
||||
jdk.sctp,
|
||||
jdk.crypto.cryptoki;
|
||||
exports jdk.internal.foreign to
|
||||
jdk.incubator.vector;
|
||||
exports jdk.internal.event to
|
||||
|
|
|
@ -71,6 +71,8 @@ import java.util.concurrent.TimeUnit;
|
|||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import jdk.internal.access.JavaNioAccess;
|
||||
import jdk.internal.access.SharedSecrets;
|
||||
import jdk.internal.ref.CleanerFactory;
|
||||
import sun.net.ResourceManager;
|
||||
import sun.net.ext.ExtendedSocketOptions;
|
||||
|
@ -87,6 +89,8 @@ class DatagramChannelImpl
|
|||
// Used to make native read and write calls
|
||||
private static final NativeDispatcher nd = new DatagramDispatcher();
|
||||
|
||||
private static final JavaNioAccess NIO_ACCESS = SharedSecrets.getJavaNioAccess();
|
||||
|
||||
// true if interruptible (can be false to emulate legacy DatagramSocket)
|
||||
private final boolean interruptible;
|
||||
|
||||
|
@ -780,13 +784,18 @@ class DatagramChannelImpl
|
|||
boolean connected)
|
||||
throws IOException
|
||||
{
|
||||
int n = receive0(fd,
|
||||
((DirectBuffer)bb).address() + pos, rem,
|
||||
sourceSockAddr.address(),
|
||||
connected);
|
||||
if (n > 0)
|
||||
bb.position(pos + n);
|
||||
return n;
|
||||
NIO_ACCESS.acquireSession(bb);
|
||||
try {
|
||||
int n = receive0(fd,
|
||||
((DirectBuffer)bb).address() + pos, rem,
|
||||
sourceSockAddr.address(),
|
||||
connected);
|
||||
if (n > 0)
|
||||
bb.position(pos + n);
|
||||
return n;
|
||||
} finally {
|
||||
NIO_ACCESS.releaseSession(bb);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -930,6 +939,7 @@ class DatagramChannelImpl
|
|||
int rem = (pos <= lim ? lim - pos : 0);
|
||||
|
||||
int written;
|
||||
NIO_ACCESS.acquireSession(bb);
|
||||
try {
|
||||
int addressLen = targetSocketAddress(target);
|
||||
written = send0(fd, ((DirectBuffer)bb).address() + pos, rem,
|
||||
|
@ -938,6 +948,8 @@ class DatagramChannelImpl
|
|||
if (isConnected())
|
||||
throw pue;
|
||||
written = rem;
|
||||
} finally {
|
||||
NIO_ACCESS.releaseSession(bb);
|
||||
}
|
||||
if (written > 0)
|
||||
bb.position(pos + written);
|
||||
|
|
|
@ -30,6 +30,13 @@ import jdk.internal.ref.Cleaner;
|
|||
|
||||
public interface DirectBuffer {
|
||||
|
||||
// Use of the returned address must be guarded if this DirectBuffer
|
||||
// is backed by a memory session that is explicitly closeable.
|
||||
//
|
||||
// Failure to do this means the outcome is undefined including
|
||||
// silent unrelated memory mutation and JVM crashes.
|
||||
//
|
||||
// See JavaNioAccess for methods to safely acquire/release resources.
|
||||
public long address();
|
||||
|
||||
public Object attachment();
|
||||
|
|
|
@ -31,12 +31,13 @@ import java.nio.ByteBuffer;
|
|||
import java.util.Objects;
|
||||
import jdk.internal.access.JavaNioAccess;
|
||||
import jdk.internal.access.SharedSecrets;
|
||||
import jdk.internal.foreign.MemorySessionImpl;
|
||||
|
||||
/**
|
||||
* File-descriptor based I/O utilities that are shared by NIO classes.
|
||||
*/
|
||||
|
||||
public class IOUtil {
|
||||
public final class IOUtil {
|
||||
|
||||
/**
|
||||
* Max number of iovec structures that readv/writev supports
|
||||
|
@ -128,7 +129,7 @@ public class IOUtil {
|
|||
int written = 0;
|
||||
if (rem == 0)
|
||||
return 0;
|
||||
var handle = acquireScope(bb, async);
|
||||
acquireScope(bb, async);
|
||||
try {
|
||||
if (position != -1) {
|
||||
written = nd.pwrite(fd, bufferAddress(bb) + pos, rem, position);
|
||||
|
@ -136,7 +137,7 @@ public class IOUtil {
|
|||
written = nd.write(fd, bufferAddress(bb) + pos, rem);
|
||||
}
|
||||
} finally {
|
||||
releaseScope(handle);
|
||||
releaseScope(bb);
|
||||
}
|
||||
if (written > 0)
|
||||
bb.position(pos + written);
|
||||
|
@ -181,9 +182,9 @@ public class IOUtil {
|
|||
int i = offset;
|
||||
while (i < count && iov_len < IOV_MAX && writevLen < WRITEV_MAX) {
|
||||
ByteBuffer buf = bufs[i];
|
||||
var h = acquireScope(buf, async);
|
||||
if (h != null) {
|
||||
handleReleasers = LinkedRunnable.of(Releaser.of(h), handleReleasers);
|
||||
acquireScope(buf, async);
|
||||
if (NIO_ACCESS.hasSession(buf)) {
|
||||
handleReleasers = LinkedRunnable.of(Releaser.of(buf), handleReleasers);
|
||||
}
|
||||
int pos = buf.position();
|
||||
int lim = buf.limit();
|
||||
|
@ -331,7 +332,7 @@ public class IOUtil {
|
|||
if (rem == 0)
|
||||
return 0;
|
||||
int n = 0;
|
||||
var handle = acquireScope(bb, async);
|
||||
acquireScope(bb, async);
|
||||
try {
|
||||
if (position != -1) {
|
||||
n = nd.pread(fd, bufferAddress(bb) + pos, rem, position);
|
||||
|
@ -339,7 +340,7 @@ public class IOUtil {
|
|||
n = nd.read(fd, bufferAddress(bb) + pos, rem);
|
||||
}
|
||||
} finally {
|
||||
releaseScope(handle);
|
||||
releaseScope(bb);
|
||||
}
|
||||
if (n > 0)
|
||||
bb.position(pos + n);
|
||||
|
@ -393,9 +394,9 @@ public class IOUtil {
|
|||
ByteBuffer buf = bufs[i];
|
||||
if (buf.isReadOnly())
|
||||
throw new IllegalArgumentException("Read-only buffer");
|
||||
var h = acquireScope(buf, async);
|
||||
if (h != null) {
|
||||
handleReleasers = LinkedRunnable.of(Releaser.of(h), handleReleasers);
|
||||
acquireScope(buf, async);
|
||||
if (NIO_ACCESS.hasSession(buf)) {
|
||||
handleReleasers = LinkedRunnable.of(Releaser.of(buf), handleReleasers);
|
||||
}
|
||||
int pos = buf.position();
|
||||
int lim = buf.limit();
|
||||
|
@ -474,15 +475,16 @@ public class IOUtil {
|
|||
|
||||
private static final JavaNioAccess NIO_ACCESS = SharedSecrets.getJavaNioAccess();
|
||||
|
||||
static Runnable acquireScope(ByteBuffer bb, boolean async) {
|
||||
return NIO_ACCESS.acquireSession(bb, async);
|
||||
static void acquireScope(ByteBuffer bb, boolean async) {
|
||||
if (async && NIO_ACCESS.isThreadConfined(bb)) {
|
||||
throw new IllegalStateException("Confined session not supported");
|
||||
}
|
||||
NIO_ACCESS.acquireSession(bb);
|
||||
}
|
||||
|
||||
private static void releaseScope(Runnable handle) {
|
||||
if (handle == null)
|
||||
return;
|
||||
private static void releaseScope(ByteBuffer bb) {
|
||||
try {
|
||||
handle.run();
|
||||
NIO_ACCESS.releaseSession(bb);
|
||||
} catch (Exception e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
|
@ -495,15 +497,14 @@ public class IOUtil {
|
|||
static Runnable acquireScopes(ByteBuffer buf, ByteBuffer[] buffers) {
|
||||
if (buffers == null) {
|
||||
assert buf != null;
|
||||
return IOUtil.Releaser.ofNullable(IOUtil.acquireScope(buf, true));
|
||||
IOUtil.acquireScope(buf, true);
|
||||
return IOUtil.Releaser.of(buf);
|
||||
} else {
|
||||
assert buf == null;
|
||||
Runnable handleReleasers = null;
|
||||
for (var b : buffers) {
|
||||
var h = IOUtil.acquireScope(b, true);
|
||||
if (h != null) {
|
||||
handleReleasers = IOUtil.LinkedRunnable.of(IOUtil.Releaser.of(h), handleReleasers);
|
||||
}
|
||||
IOUtil.acquireScope(b, true);
|
||||
handleReleasers = IOUtil.LinkedRunnable.of(IOUtil.Releaser.of(b), handleReleasers);
|
||||
}
|
||||
return handleReleasers;
|
||||
}
|
||||
|
@ -514,12 +515,11 @@ public class IOUtil {
|
|||
releasers.run();
|
||||
}
|
||||
|
||||
static record LinkedRunnable(Runnable node, Runnable next)
|
||||
implements Runnable
|
||||
{
|
||||
record LinkedRunnable(Runnable node, Runnable next) implements Runnable {
|
||||
LinkedRunnable {
|
||||
Objects.requireNonNull(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
|
@ -529,20 +529,28 @@ public class IOUtil {
|
|||
next.run();
|
||||
}
|
||||
}
|
||||
|
||||
static LinkedRunnable of(Runnable first, Runnable second) {
|
||||
return new LinkedRunnable(first, second);
|
||||
}
|
||||
}
|
||||
|
||||
static record Releaser(Runnable handle) implements Runnable {
|
||||
Releaser { Objects.requireNonNull(handle) ; }
|
||||
@Override public void run() { releaseScope(handle); }
|
||||
static Runnable of(Runnable handle) { return new Releaser(handle); }
|
||||
static Runnable ofNullable(Runnable handle) {
|
||||
if (handle == null)
|
||||
return () -> { };
|
||||
return new Releaser(handle);
|
||||
record Releaser(ByteBuffer bb) implements Runnable {
|
||||
Releaser {
|
||||
Objects.requireNonNull(bb);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
releaseScope(bb);
|
||||
}
|
||||
|
||||
static Runnable of(ByteBuffer bb) {
|
||||
return NIO_ACCESS.hasSession(bb)
|
||||
? new Releaser(bb)
|
||||
: () -> {};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static long bufferAddress(ByteBuffer buf) {
|
||||
|
|
|
@ -134,6 +134,7 @@ grant codeBase "jrt:/jdk.crypto.cryptoki" {
|
|||
permission java.lang.RuntimePermission
|
||||
"accessClassInPackage.com.sun.crypto.provider";
|
||||
permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.misc";
|
||||
permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.access";
|
||||
permission java.lang.RuntimePermission
|
||||
"accessClassInPackage.sun.security.*";
|
||||
permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue