< prev index next >
src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java
Print this page
*** 40,58 ****
--- 40,61 ----
import java.nio.channels.NonReadableChannelException;
import java.nio.channels.NonWritableChannelException;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.SelectableChannel;
import java.nio.channels.WritableByteChannel;
+ import java.util.Objects;
import jdk.internal.access.JavaIOFileDescriptorAccess;
import jdk.internal.access.JavaNioAccess;
import jdk.internal.access.SharedSecrets;
import jdk.internal.misc.ExtendedMapMode;
import jdk.internal.misc.Unsafe;
import jdk.internal.ref.Cleaner;
import jdk.internal.ref.CleanerFactory;
+ import jdk.internal.access.foreign.UnmapperProxy;
+
public class FileChannelImpl
extends FileChannel
{
// Memory allocation size for mapping buffers
private static final long allocationGranularity;
*** 861,891 ****
// -- Memory-mapped buffers --
private static abstract class Unmapper
! implements Runnable
{
// may be required to close file
private static final NativeDispatcher nd = new FileDispatcherImpl();
private volatile long address;
protected final long size;
! protected final int cap;
private final FileDescriptor fd;
! private Unmapper(long address, long size, int cap,
! FileDescriptor fd)
{
assert (address != 0);
this.address = address;
this.size = size;
this.cap = cap;
this.fd = fd;
}
public void run() {
if (address == 0)
return;
unmap0(address, size);
address = 0;
--- 864,906 ----
// -- Memory-mapped buffers --
private static abstract class Unmapper
! implements Runnable, UnmapperProxy
{
// may be required to close file
private static final NativeDispatcher nd = new FileDispatcherImpl();
private volatile long address;
protected final long size;
! protected final long cap;
private final FileDescriptor fd;
+ private final int pagePosition;
! private Unmapper(long address, long size, long cap,
! FileDescriptor fd, int pagePosition)
{
assert (address != 0);
this.address = address;
this.size = size;
this.cap = cap;
this.fd = fd;
+ this.pagePosition = pagePosition;
+ }
+
+ @Override
+ public long address() {
+ return address;
}
+ @Override
public void run() {
+ unmap();
+ }
+
+ public void unmap() {
if (address == 0)
return;
unmap0(address, size);
address = 0;
*** 909,921 ****
// keep track of non-sync mapped buffer usage
static volatile int count;
static volatile long totalSize;
static volatile long totalCapacity;
! public DefaultUnmapper(long address, long size, int cap,
! FileDescriptor fd) {
! super(address, size, cap, fd);
incrementStats();
}
protected void incrementStats() {
synchronized (DefaultUnmapper.class) {
--- 924,936 ----
// keep track of non-sync mapped buffer usage
static volatile int count;
static volatile long totalSize;
static volatile long totalCapacity;
! public DefaultUnmapper(long address, long size, long cap,
! FileDescriptor fd, int pagePosition) {
! super(address, size, cap, fd, pagePosition);
incrementStats();
}
protected void incrementStats() {
synchronized (DefaultUnmapper.class) {
*** 938,950 ****
// keep track of mapped buffer usage
static volatile int count;
static volatile long totalSize;
static volatile long totalCapacity;
! public SyncUnmapper(long address, long size, int cap,
! FileDescriptor fd) {
! super(address, size, cap, fd);
incrementStats();
}
protected void incrementStats() {
synchronized (SyncUnmapper.class) {
--- 953,965 ----
// keep track of mapped buffer usage
static volatile int count;
static volatile long totalSize;
static volatile long totalCapacity;
! public SyncUnmapper(long address, long size, long cap,
! FileDescriptor fd, int pagePosition) {
! super(address, size, cap, fd, pagePosition);
incrementStats();
}
protected void incrementStats() {
synchronized (SyncUnmapper.class) {
*** 966,980 ****
Cleaner cl = ((DirectBuffer)bb).cleaner();
if (cl != null)
cl.clean();
}
private static final int MAP_RO = 0;
private static final int MAP_RW = 1;
private static final int MAP_PV = 2;
! public MappedByteBuffer map(MapMode mode, long position, long size)
throws IOException
{
ensureOpen();
if (mode == null)
throw new NullPointerException("Mode is null");
--- 981,1028 ----
Cleaner cl = ((DirectBuffer)bb).cleaner();
if (cl != null)
cl.clean();
}
+ private static final int MAP_INVALID = -1;
private static final int MAP_RO = 0;
private static final int MAP_RW = 1;
private static final int MAP_PV = 2;
! public MappedByteBuffer map(MapMode mode, long position, long size) throws IOException {
! if (size > Integer.MAX_VALUE)
! throw new IllegalArgumentException("Size exceeds Integer.MAX_VALUE");
! boolean isSync = isSync(Objects.requireNonNull(mode, "Mode is null"));
! int prot = toProt(mode);
! Unmapper unmapper = mapInternal(mode, position, size, prot, isSync);
! if (unmapper == null) {
! // a valid file descriptor is not required
! FileDescriptor dummy = new FileDescriptor();
! if ((!writable) || (prot == MAP_RO))
! return Util.newMappedByteBufferR(0, 0, dummy, null, isSync);
! else
! return Util.newMappedByteBuffer(0, 0, dummy, null, isSync);
! } else if ((!writable) || (prot == MAP_RO)) {
! return Util.newMappedByteBufferR((int)unmapper.cap,
! unmapper.address + unmapper.pagePosition,
! unmapper.fd,
! unmapper, isSync);
! } else {
! return Util.newMappedByteBuffer((int)unmapper.cap,
! unmapper.address + unmapper.pagePosition,
! unmapper.fd,
! unmapper, isSync);
! }
! }
!
! public Unmapper mapInternal(MapMode mode, long position, long size) throws IOException {
! boolean isSync = isSync(Objects.requireNonNull(mode, "Mode is null"));
! int prot = toProt(mode);
! return mapInternal(mode, position, size, prot, isSync);
! }
!
! private Unmapper mapInternal(MapMode mode, long position, long size, int prot, boolean isSync)
throws IOException
{
ensureOpen();
if (mode == null)
throw new NullPointerException("Mode is null");
*** 982,1020 ****
throw new IllegalArgumentException("Negative position");
if (size < 0L)
throw new IllegalArgumentException("Negative size");
if (position + size < 0)
throw new IllegalArgumentException("Position + size overflow");
- if (size > Integer.MAX_VALUE)
- throw new IllegalArgumentException("Size exceeds Integer.MAX_VALUE");
-
- int imode;
- boolean isSync = false;
- if (mode == MapMode.READ_ONLY)
- imode = MAP_RO;
- else if (mode == MapMode.READ_WRITE)
- imode = MAP_RW;
- else if (mode == MapMode.PRIVATE)
- imode = MAP_PV;
- else if (mode == ExtendedMapMode.READ_ONLY_SYNC) {
- imode = MAP_RO;
- isSync = true;
- } else if (mode == ExtendedMapMode.READ_WRITE_SYNC) {
- imode = MAP_RW;
- isSync = true;
- } else {
- throw new UnsupportedOperationException();
- }
- if ((mode != MapMode.READ_ONLY) && mode != ExtendedMapMode.READ_ONLY_SYNC && !writable)
- throw new NonWritableChannelException();
- if (!readable)
- throw new NonReadableChannelException();
- // reject SYNC request if writeback is not enabled for this platform
- if (isSync && !Unsafe.isWritebackEnabled()) {
- throw new UnsupportedOperationException();
- }
long addr = -1;
int ti = -1;
try {
beginBlocking();
ti = threads.add();
--- 1030,1041 ----
throw new IllegalArgumentException("Negative position");
if (size < 0L)
throw new IllegalArgumentException("Negative size");
if (position + size < 0)
throw new IllegalArgumentException("Position + size overflow");
+ checkMode(mode, prot, isSync);
long addr = -1;
int ti = -1;
try {
beginBlocking();
ti = threads.add();
*** 1043,1078 ****
if (!isOpen())
return null;
}
if (size == 0) {
! addr = 0;
! // a valid file descriptor is not required
! FileDescriptor dummy = new FileDescriptor();
! if ((!writable) || (imode == MAP_RO))
! return Util.newMappedByteBufferR(0, 0, dummy, null, isSync);
! else
! return Util.newMappedByteBuffer(0, 0, dummy, null, isSync);
}
pagePosition = (int)(position % allocationGranularity);
long mapPosition = position - pagePosition;
mapSize = size + pagePosition;
try {
// If map0 did not throw an exception, the address is valid
! addr = map0(imode, mapPosition, mapSize, isSync);
} catch (OutOfMemoryError x) {
// An OutOfMemoryError may indicate that we've exhausted
// memory so force gc and re-attempt map
System.gc();
try {
Thread.sleep(100);
} catch (InterruptedException y) {
Thread.currentThread().interrupt();
}
try {
! addr = map0(imode, mapPosition, mapSize, isSync);
} catch (OutOfMemoryError y) {
// After a second OOME, fail
throw new IOException("Map failed", y);
}
}
--- 1064,1093 ----
if (!isOpen())
return null;
}
if (size == 0) {
! return null;
}
pagePosition = (int)(position % allocationGranularity);
long mapPosition = position - pagePosition;
mapSize = size + pagePosition;
try {
// If map0 did not throw an exception, the address is valid
! addr = map0(prot, mapPosition, mapSize, isSync);
} catch (OutOfMemoryError x) {
// An OutOfMemoryError may indicate that we've exhausted
// memory so force gc and re-attempt map
System.gc();
try {
Thread.sleep(100);
} catch (InterruptedException y) {
Thread.currentThread().interrupt();
}
try {
! addr = map0(prot, mapPosition, mapSize, isSync);
} catch (OutOfMemoryError y) {
// After a second OOME, fail
throw new IOException("Map failed", y);
}
}
*** 1088,1120 ****
throw ioe;
}
assert (IOStatus.checkAll(addr));
assert (addr % allocationGranularity == 0);
- int isize = (int)size;
Unmapper um = (isSync
! ? new SyncUnmapper(addr, mapSize, isize, mfd)
! : new DefaultUnmapper(addr, mapSize, isize, mfd));
! if ((!writable) || (imode == MAP_RO)) {
! return Util.newMappedByteBufferR(isize,
! addr + pagePosition,
! mfd,
! um,
! isSync);
! } else {
! return Util.newMappedByteBuffer(isize,
! addr + pagePosition,
! mfd,
! um,
! isSync);
! }
} finally {
threads.remove(ti);
endBlocking(IOStatus.checkAll(addr));
}
}
/**
* Invoked by sun.management.ManagementFactoryHelper to create the management
* interface for mapped buffers.
*/
public static JavaNioAccess.BufferPool getMappedBufferPool() {
--- 1103,1159 ----
throw ioe;
}
assert (IOStatus.checkAll(addr));
assert (addr % allocationGranularity == 0);
Unmapper um = (isSync
! ? new SyncUnmapper(addr, mapSize, size, mfd, pagePosition)
! : new DefaultUnmapper(addr, mapSize, size, mfd, pagePosition));
! return um;
} finally {
threads.remove(ti);
endBlocking(IOStatus.checkAll(addr));
}
}
+ private boolean isSync(MapMode mode) {
+ return mode == ExtendedMapMode.READ_ONLY_SYNC ||
+ mode == ExtendedMapMode.READ_WRITE_SYNC;
+ }
+
+ private int toProt(MapMode mode) {
+ int prot;
+ if (mode == MapMode.READ_ONLY) {
+ prot = MAP_RO;
+ } else if (mode == MapMode.READ_WRITE) {
+ prot = MAP_RW;
+ } else if (mode == MapMode.PRIVATE) {
+ prot = MAP_PV;
+ } else if (mode == ExtendedMapMode.READ_ONLY_SYNC) {
+ prot = MAP_RO;
+ } else if (mode == ExtendedMapMode.READ_WRITE_SYNC) {
+ prot = MAP_RW;
+ } else {
+ prot = MAP_INVALID;
+ }
+ return prot;
+ }
+
+ private void checkMode(MapMode mode, int prot, boolean isSync) {
+ if (prot == MAP_INVALID) {
+ throw new UnsupportedOperationException();
+ }
+ if ((mode != MapMode.READ_ONLY) && mode != ExtendedMapMode.READ_ONLY_SYNC && !writable)
+ throw new NonWritableChannelException();
+ if (!readable)
+ throw new NonReadableChannelException();
+ // reject SYNC request if writeback is not enabled for this platform
+ if (isSync && !Unsafe.isWritebackEnabled()) {
+ throw new UnsupportedOperationException();
+ }
+ }
+
/**
* Invoked by sun.management.ManagementFactoryHelper to create the management
* interface for mapped buffers.
*/
public static JavaNioAccess.BufferPool getMappedBufferPool() {
< prev index next >