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