930 private static final int MAP_RO = 0;
931 private static final int MAP_RW = 1;
932 private static final int MAP_PV = 2;
933
934 public MappedByteBuffer map(MapMode mode, long position, long size)
935 throws IOException
936 {
937 ensureOpen();
938 if (mode == null)
939 throw new NullPointerException("Mode is null");
940 if (position < 0L)
941 throw new IllegalArgumentException("Negative position");
942 if (size < 0L)
943 throw new IllegalArgumentException("Negative size");
944 if (position + size < 0)
945 throw new IllegalArgumentException("Position + size overflow");
946 if (size > Integer.MAX_VALUE)
947 throw new IllegalArgumentException("Size exceeds Integer.MAX_VALUE");
948
949 int imode = -1;
950 if (mode == MapMode.READ_ONLY)
951 imode = MAP_RO;
952 else if (mode == MapMode.READ_WRITE)
953 imode = MAP_RW;
954 else if (mode == MapMode.PRIVATE)
955 imode = MAP_PV;
956 assert (imode >= 0);
957 if ((mode != MapMode.READ_ONLY) && !writable)
958 throw new NonWritableChannelException();
959 if (!readable)
960 throw new NonReadableChannelException();
961
962 long addr = -1;
963 int ti = -1;
964 try {
965 beginBlocking();
966 ti = threads.add();
967 if (!isOpen())
968 return null;
969
970 long mapSize;
971 int pagePosition;
972 synchronized (positionLock) {
973 long filesize;
974 do {
975 filesize = nd.size(fd);
978 return null;
979
980 if (filesize < position + size) { // Extend file size
981 if (!writable) {
982 throw new IOException("Channel not open for writing " +
983 "- cannot extend file to required size");
984 }
985 int rv;
986 do {
987 rv = nd.truncate(fd, position + size);
988 } while ((rv == IOStatus.INTERRUPTED) && isOpen());
989 if (!isOpen())
990 return null;
991 }
992
993 if (size == 0) {
994 addr = 0;
995 // a valid file descriptor is not required
996 FileDescriptor dummy = new FileDescriptor();
997 if ((!writable) || (imode == MAP_RO))
998 return Util.newMappedByteBufferR(0, 0, dummy, null);
999 else
1000 return Util.newMappedByteBuffer(0, 0, dummy, null);
1001 }
1002
1003 pagePosition = (int)(position % allocationGranularity);
1004 long mapPosition = position - pagePosition;
1005 mapSize = size + pagePosition;
1006 try {
1007 // If map0 did not throw an exception, the address is valid
1008 addr = map0(imode, mapPosition, mapSize);
1009 } catch (OutOfMemoryError x) {
1010 // An OutOfMemoryError may indicate that we've exhausted
1011 // memory so force gc and re-attempt map
1012 System.gc();
1013 try {
1014 Thread.sleep(100);
1015 } catch (InterruptedException y) {
1016 Thread.currentThread().interrupt();
1017 }
1018 try {
1019 addr = map0(imode, mapPosition, mapSize);
1020 } catch (OutOfMemoryError y) {
1021 // After a second OOME, fail
1022 throw new IOException("Map failed", y);
1023 }
1024 }
1025 } // synchronized
1026
1027 // On Windows, and potentially other platforms, we need an open
1028 // file descriptor for some mapping operations.
1029 FileDescriptor mfd;
1030 try {
1031 mfd = nd.duplicateForMapping(fd);
1032 } catch (IOException ioe) {
1033 unmap0(addr, mapSize);
1034 throw ioe;
1035 }
1036
1037 assert (IOStatus.checkAll(addr));
1038 assert (addr % allocationGranularity == 0);
1039 int isize = (int)size;
1040 Unmapper um = new Unmapper(addr, mapSize, isize, mfd);
1041 if ((!writable) || (imode == MAP_RO)) {
1042 return Util.newMappedByteBufferR(isize,
1043 addr + pagePosition,
1044 mfd,
1045 um);
1046 } else {
1047 return Util.newMappedByteBuffer(isize,
1048 addr + pagePosition,
1049 mfd,
1050 um);
1051 }
1052 } finally {
1053 threads.remove(ti);
1054 endBlocking(IOStatus.checkAll(addr));
1055 }
1056 }
1057
1058 /**
1059 * Invoked by sun.management.ManagementFactoryHelper to create the management
1060 * interface for mapped buffers.
1061 */
1062 public static JavaNioAccess.BufferPool getMappedBufferPool() {
1063 return new JavaNioAccess.BufferPool() {
1064 @Override
1065 public String getName() {
1066 return "mapped";
1067 }
1068 @Override
1069 public long getCount() {
1070 return Unmapper.count;
1184 } finally {
1185 threads.remove(ti);
1186 }
1187 }
1188
1189 void release(FileLockImpl fli) throws IOException {
1190 int ti = threads.add();
1191 try {
1192 ensureOpen();
1193 nd.release(fd, fli.position(), fli.size());
1194 } finally {
1195 threads.remove(ti);
1196 }
1197 assert fileLockTable != null;
1198 fileLockTable.remove(fli);
1199 }
1200
1201 // -- Native methods --
1202
1203 // Creates a new mapping
1204 private native long map0(int prot, long position, long length)
1205 throws IOException;
1206
1207 // Removes an existing mapping
1208 private static native int unmap0(long address, long length);
1209
1210 // Transfers from src to dst, or returns -2 if kernel can't do that
1211 private native long transferTo0(FileDescriptor src, long position,
1212 long count, FileDescriptor dst);
1213
1214 // Caches fieldIDs
1215 private static native long initIDs();
1216
1217 static {
1218 IOUtil.load();
1219 allocationGranularity = initIDs();
1220 }
1221 }
|
930 private static final int MAP_RO = 0;
931 private static final int MAP_RW = 1;
932 private static final int MAP_PV = 2;
933
934 public MappedByteBuffer map(MapMode mode, long position, long size)
935 throws IOException
936 {
937 ensureOpen();
938 if (mode == null)
939 throw new NullPointerException("Mode is null");
940 if (position < 0L)
941 throw new IllegalArgumentException("Negative position");
942 if (size < 0L)
943 throw new IllegalArgumentException("Negative size");
944 if (position + size < 0)
945 throw new IllegalArgumentException("Position + size overflow");
946 if (size > Integer.MAX_VALUE)
947 throw new IllegalArgumentException("Size exceeds Integer.MAX_VALUE");
948
949 int imode = -1;
950 boolean isPersistent = false;
951 if (mode == MapMode.READ_ONLY)
952 imode = MAP_RO;
953 else if (mode == MapMode.READ_WRITE)
954 imode = MAP_RW;
955 else if (mode == MapMode.PRIVATE) {
956 imode = MAP_PV;
957 } else if (mode == MapMode.READ_ONLY_PERSISTENT) {
958 imode = MAP_RO;
959 isPersistent = true;
960 } else if (mode == MapMode.READ_WRITE_PERSISTENT) {
961 imode = MAP_RW;
962 isPersistent = true;
963 }
964
965 assert (imode >= 0);
966 if ((mode != MapMode.READ_ONLY) && !writable)
967 throw new NonWritableChannelException();
968 if (!readable)
969 throw new NonReadableChannelException();
970
971 long addr = -1;
972 int ti = -1;
973 try {
974 beginBlocking();
975 ti = threads.add();
976 if (!isOpen())
977 return null;
978
979 long mapSize;
980 int pagePosition;
981 synchronized (positionLock) {
982 long filesize;
983 do {
984 filesize = nd.size(fd);
987 return null;
988
989 if (filesize < position + size) { // Extend file size
990 if (!writable) {
991 throw new IOException("Channel not open for writing " +
992 "- cannot extend file to required size");
993 }
994 int rv;
995 do {
996 rv = nd.truncate(fd, position + size);
997 } while ((rv == IOStatus.INTERRUPTED) && isOpen());
998 if (!isOpen())
999 return null;
1000 }
1001
1002 if (size == 0) {
1003 addr = 0;
1004 // a valid file descriptor is not required
1005 FileDescriptor dummy = new FileDescriptor();
1006 if ((!writable) || (imode == MAP_RO))
1007 return Util.newMappedByteBufferR(0, 0, dummy, null, isPersistent);
1008 else
1009 return Util.newMappedByteBuffer(0, 0, dummy, null, isPersistent);
1010 }
1011
1012 pagePosition = (int)(position % allocationGranularity);
1013 long mapPosition = position - pagePosition;
1014 mapSize = size + pagePosition;
1015 try {
1016 // If map0 did not throw an exception, the address is valid
1017 addr = map0(imode, mapPosition, mapSize, isPersistent);
1018 } catch (OutOfMemoryError x) {
1019 // An OutOfMemoryError may indicate that we've exhausted
1020 // memory so force gc and re-attempt map
1021 System.gc();
1022 try {
1023 Thread.sleep(100);
1024 } catch (InterruptedException y) {
1025 Thread.currentThread().interrupt();
1026 }
1027 try {
1028 addr = map0(imode, mapPosition, mapSize, isPersistent);
1029 } catch (OutOfMemoryError y) {
1030 // After a second OOME, fail
1031 throw new IOException("Map failed", y);
1032 }
1033 }
1034 } // synchronized
1035
1036 // On Windows, and potentially other platforms, we need an open
1037 // file descriptor for some mapping operations.
1038 FileDescriptor mfd;
1039 try {
1040 mfd = nd.duplicateForMapping(fd);
1041 } catch (IOException ioe) {
1042 unmap0(addr, mapSize);
1043 throw ioe;
1044 }
1045
1046 assert (IOStatus.checkAll(addr));
1047 assert (addr % allocationGranularity == 0);
1048 int isize = (int)size;
1049 Unmapper um = new Unmapper(addr, mapSize, isize, mfd);
1050 if ((!writable) || (imode == MAP_RO)) {
1051 return Util.newMappedByteBufferR(isize,
1052 addr + pagePosition,
1053 mfd,
1054 um,
1055 isPersistent);
1056 } else {
1057 return Util.newMappedByteBuffer(isize,
1058 addr + pagePosition,
1059 mfd,
1060 um,
1061 isPersistent);
1062 }
1063 } finally {
1064 threads.remove(ti);
1065 endBlocking(IOStatus.checkAll(addr));
1066 }
1067 }
1068
1069 /**
1070 * Invoked by sun.management.ManagementFactoryHelper to create the management
1071 * interface for mapped buffers.
1072 */
1073 public static JavaNioAccess.BufferPool getMappedBufferPool() {
1074 return new JavaNioAccess.BufferPool() {
1075 @Override
1076 public String getName() {
1077 return "mapped";
1078 }
1079 @Override
1080 public long getCount() {
1081 return Unmapper.count;
1195 } finally {
1196 threads.remove(ti);
1197 }
1198 }
1199
1200 void release(FileLockImpl fli) throws IOException {
1201 int ti = threads.add();
1202 try {
1203 ensureOpen();
1204 nd.release(fd, fli.position(), fli.size());
1205 } finally {
1206 threads.remove(ti);
1207 }
1208 assert fileLockTable != null;
1209 fileLockTable.remove(fli);
1210 }
1211
1212 // -- Native methods --
1213
1214 // Creates a new mapping
1215 private native long map0(int prot, long position, long length, boolean isPersistent)
1216 throws IOException;
1217
1218 // Removes an existing mapping
1219 private static native int unmap0(long address, long length);
1220
1221 // Transfers from src to dst, or returns -2 if kernel can't do that
1222 private native long transferTo0(FileDescriptor src, long position,
1223 long count, FileDescriptor dst);
1224
1225 // Caches fieldIDs
1226 private static native long initIDs();
1227
1228 static {
1229 IOUtil.load();
1230 allocationGranularity = initIDs();
1231 }
1232 }
|