< prev index next >

src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java

Print this page




 849         int ti = -1;
 850         try {
 851             beginBlocking();
 852             ti = threads.add();
 853             if (!isOpen())
 854                 return -1;
 855             do {
 856                 n = IOUtil.write(fd, src, position, direct, alignment, nd);
 857             } while ((n == IOStatus.INTERRUPTED) && isOpen());
 858             return IOStatus.normalize(n);
 859         } finally {
 860             threads.remove(ti);
 861             endBlocking(n > 0);
 862             assert IOStatus.check(n);
 863         }
 864     }
 865 
 866 
 867     // -- Memory-mapped buffers --
 868 
 869     private static class Unmapper
 870         implements Runnable
 871     {
 872         // may be required to close file
 873         private static final NativeDispatcher nd = new FileDispatcherImpl();
 874 
 875         // keep track of mapped buffer usage
 876         static volatile int count;
 877         static volatile long totalSize;
 878         static volatile long totalCapacity;
 879 
 880         private volatile long address;
 881         private final long size;
 882         private final int cap;
 883         private final FileDescriptor fd;
 884 
 885         private Unmapper(long address, long size, int cap,
 886                          FileDescriptor fd)
 887         {
 888             assert (address != 0);
 889             this.address = address;
 890             this.size = size;
 891             this.cap = cap;
 892             this.fd = fd;
 893 
 894             synchronized (Unmapper.class) {
 895                 count++;
 896                 totalSize += size;
 897                 totalCapacity += cap;
 898             }
 899         }
 900 
 901         public void run() {
 902             if (address == 0)
 903                 return;
 904             unmap0(address, size);
 905             address = 0;
 906 
 907             // if this mapping has a valid file descriptor then we close it
 908             if (fd.valid()) {
 909                 try {
 910                     nd.close(fd);
 911                 } catch (IOException ignore) {
 912                     // nothing we can do
 913                 }
 914             }
 915 
 916             synchronized (Unmapper.class) {
























































 917                 count--;
 918                 totalSize -= size;
 919                 totalCapacity -= cap;
 920             }
 921         }
 922     }
 923 
 924     private static void unmap(MappedByteBuffer bb) {
 925         Cleaner cl = ((DirectBuffer)bb).cleaner();
 926         if (cl != null)
 927             cl.clean();
 928     }
 929 
 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;

























1071             }
1072             @Override
1073             public long getTotalCapacity() {
1074                 return Unmapper.totalCapacity;
1075             }
1076             @Override
1077             public long getMemoryUsed() {
1078                 return Unmapper.totalSize;
1079             }
1080         };
1081     }
1082 
1083     // -- Locks --
1084 
1085     // keeps track of locks on this file
1086     private volatile FileLockTable fileLockTable;
1087 
1088     private FileLockTable fileLockTable() throws IOException {
1089         if (fileLockTable == null) {
1090             synchronized (this) {
1091                 if (fileLockTable == null) {
1092                     int ti = threads.add();
1093                     try {
1094                         ensureOpen();
1095                         fileLockTable = new FileLockTable(this, fd);
1096                     } finally {
1097                         threads.remove(ti);
1098                     }


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 }


 849         int ti = -1;
 850         try {
 851             beginBlocking();
 852             ti = threads.add();
 853             if (!isOpen())
 854                 return -1;
 855             do {
 856                 n = IOUtil.write(fd, src, position, direct, alignment, nd);
 857             } while ((n == IOStatus.INTERRUPTED) && isOpen());
 858             return IOStatus.normalize(n);
 859         } finally {
 860             threads.remove(ti);
 861             endBlocking(n > 0);
 862             assert IOStatus.check(n);
 863         }
 864     }
 865 
 866 
 867     // -- Memory-mapped buffers --
 868 
 869     private static abstract class Unmapper
 870         implements Runnable
 871     {
 872         // may be required to close file
 873         private static final NativeDispatcher nd = new FileDispatcherImpl();
 874 





 875         private volatile long address;
 876         protected final long size;
 877         protected final int cap;
 878         private final FileDescriptor fd;
 879 
 880         private Unmapper(long address, long size, int cap,
 881                          FileDescriptor fd)
 882         {
 883             assert (address != 0);
 884             this.address = address;
 885             this.size = size;
 886             this.cap = cap;
 887             this.fd = fd;






 888         }
 889 
 890         public void run() {
 891             if (address == 0)
 892                 return;
 893             unmap0(address, size);
 894             address = 0;
 895 
 896             // if this mapping has a valid file descriptor then we close it
 897             if (fd.valid()) {
 898                 try {
 899                     nd.close(fd);
 900                 } catch (IOException ignore) {
 901                     // nothing we can do
 902                 }
 903             }
 904 
 905             decrement_stats();
 906         }
 907         protected abstract void increment_stats();
 908         protected abstract void decrement_stats();
 909     }
 910 
 911     private static class DefaultUnmapper extends Unmapper {
 912 
 913         // keep track of non-persistent mapped buffer usage
 914         static volatile int count;
 915         static volatile long totalSize;
 916         static volatile long totalCapacity;
 917 
 918         public DefaultUnmapper(long address, long size, int cap,
 919                                      FileDescriptor fd) {
 920             super(address, size, cap, fd);
 921             increment_stats();
 922         }
 923         
 924         protected void increment_stats() {
 925             synchronized (DefaultUnmapper.class) {
 926                 count++;
 927                 totalSize += size;
 928                 totalCapacity += cap;
 929             }
 930         }
 931         protected void decrement_stats() {
 932             synchronized (DefaultUnmapper.class) {
 933                 count--;
 934                 totalSize -= size;
 935                 totalCapacity -= cap;
 936             }
 937         }
 938     }
 939     
 940     private static class PersistentUnmapper extends Unmapper {
 941 
 942         // keep track of mapped buffer usage
 943         static volatile int count;
 944         static volatile long totalSize;
 945         static volatile long totalCapacity;
 946 
 947         public PersistentUnmapper(long address, long size, int cap,
 948                                   FileDescriptor fd) {
 949             super(address, size, cap, fd);
 950             increment_stats();
 951         }
 952         
 953         protected void increment_stats() {
 954             synchronized (PersistentUnmapper.class) {
 955                 count++;
 956                 totalSize += size;
 957                 totalCapacity += cap;
 958             }
 959         }
 960         protected void decrement_stats() {
 961             synchronized (PersistentUnmapper.class) {
 962                 count--;
 963                 totalSize -= size;
 964                 totalCapacity -= cap;
 965             }
 966         }
 967     }
 968     
 969     private static void unmap(MappedByteBuffer bb) {
 970         Cleaner cl = ((DirectBuffer)bb).cleaner();
 971         if (cl != null)
 972             cl.clean();
 973     }
 974 
 975     private static final int MAP_RO = 0;
 976     private static final int MAP_RW = 1;
 977     private static final int MAP_PV = 2;
 978 
 979     public MappedByteBuffer map(MapMode mode, long position, long size)
 980         throws IOException
 981     {
 982         ensureOpen();
 983         if (mode == null)
 984             throw new NullPointerException("Mode is null");
 985         if (position < 0L)
 986             throw new IllegalArgumentException("Negative position");
 987         if (size < 0L)
 988             throw new IllegalArgumentException("Negative size");
 989         if (position + size < 0)
 990             throw new IllegalArgumentException("Position + size overflow");
 991         if (size > Integer.MAX_VALUE)
 992             throw new IllegalArgumentException("Size exceeds Integer.MAX_VALUE");
 993 
 994         int imode = -1;
 995         boolean isPersistent = false;
 996         if (mode == MapMode.READ_ONLY)
 997             imode = MAP_RO;
 998         else if (mode == MapMode.READ_WRITE)
 999             imode = MAP_RW;
1000         else if (mode == MapMode.PRIVATE) {
1001             imode = MAP_PV;
1002         } else if (mode == MapMode.READ_ONLY_PERSISTENT) {
1003             imode = MAP_RO;
1004             isPersistent = true;
1005         } else if (mode == MapMode.READ_WRITE_PERSISTENT) {
1006             imode = MAP_RW;
1007             isPersistent = true;
1008         }
1009 
1010         assert (imode >= 0);
1011         if ((mode != MapMode.READ_ONLY) && !writable)
1012             throw new NonWritableChannelException();
1013         if (!readable)
1014             throw new NonReadableChannelException();
1015 
1016         long addr = -1;
1017         int ti = -1;
1018         try {
1019             beginBlocking();
1020             ti = threads.add();
1021             if (!isOpen())
1022                 return null;
1023 
1024             long mapSize;
1025             int pagePosition;
1026             synchronized (positionLock) {
1027                 long filesize;
1028                 do {
1029                     filesize = nd.size(fd);


1032                     return null;
1033 
1034                 if (filesize < position + size) { // Extend file size
1035                     if (!writable) {
1036                         throw new IOException("Channel not open for writing " +
1037                             "- cannot extend file to required size");
1038                     }
1039                     int rv;
1040                     do {
1041                         rv = nd.truncate(fd, position + size);
1042                     } while ((rv == IOStatus.INTERRUPTED) && isOpen());
1043                     if (!isOpen())
1044                         return null;
1045                 }
1046 
1047                 if (size == 0) {
1048                     addr = 0;
1049                     // a valid file descriptor is not required
1050                     FileDescriptor dummy = new FileDescriptor();
1051                     if ((!writable) || (imode == MAP_RO))
1052                         return Util.newMappedByteBufferR(0, 0, dummy, null, isPersistent);
1053                     else
1054                         return Util.newMappedByteBuffer(0, 0, dummy, null, isPersistent);
1055                 }
1056 
1057                 pagePosition = (int)(position % allocationGranularity);
1058                 long mapPosition = position - pagePosition;
1059                 mapSize = size + pagePosition;
1060                 try {
1061                     // If map0 did not throw an exception, the address is valid
1062                     addr = map0(imode, mapPosition, mapSize, isPersistent);
1063                 } catch (OutOfMemoryError x) {
1064                     // An OutOfMemoryError may indicate that we've exhausted
1065                     // memory so force gc and re-attempt map
1066                     System.gc();
1067                     try {
1068                         Thread.sleep(100);
1069                     } catch (InterruptedException y) {
1070                         Thread.currentThread().interrupt();
1071                     }
1072                     try {
1073                         addr = map0(imode, mapPosition, mapSize, isPersistent);
1074                     } catch (OutOfMemoryError y) {
1075                         // After a second OOME, fail
1076                         throw new IOException("Map failed", y);
1077                     }
1078                 }
1079             } // synchronized
1080 
1081             // On Windows, and potentially other platforms, we need an open
1082             // file descriptor for some mapping operations.
1083             FileDescriptor mfd;
1084             try {
1085                 mfd = nd.duplicateForMapping(fd);
1086             } catch (IOException ioe) {
1087                 unmap0(addr, mapSize);
1088                 throw ioe;
1089             }
1090 
1091             assert (IOStatus.checkAll(addr));
1092             assert (addr % allocationGranularity == 0);
1093             int isize = (int)size;
1094             Unmapper um = (isPersistent
1095                            ? new PersistentUnmapper(addr, mapSize, isize, mfd)
1096                            : new DefaultUnmapper(addr, mapSize, isize, mfd));
1097             if ((!writable) || (imode == MAP_RO)) {
1098                 return Util.newMappedByteBufferR(isize,
1099                                                  addr + pagePosition,
1100                                                  mfd,
1101                                                  um,
1102                                                  isPersistent);
1103             } else {
1104                 return Util.newMappedByteBuffer(isize,
1105                                                 addr + pagePosition,
1106                                                 mfd,
1107                                                 um,
1108                                                 isPersistent);
1109             }
1110         } finally {
1111             threads.remove(ti);
1112             endBlocking(IOStatus.checkAll(addr));
1113         }
1114     }
1115 
1116     /**
1117      * Invoked by sun.management.ManagementFactoryHelper to create the management
1118      * interface for mapped buffers.
1119      */
1120     public static JavaNioAccess.BufferPool getMappedBufferPool() {
1121         return new JavaNioAccess.BufferPool() {
1122             @Override
1123             public String getName() {
1124                 return "mapped";
1125             }
1126             @Override
1127             public long getCount() {
1128                 return DefaultUnmapper.count;
1129             }
1130             @Override
1131             public long getTotalCapacity() {
1132                 return DefaultUnmapper.totalCapacity;
1133             }
1134             @Override
1135             public long getMemoryUsed() {
1136                 return DefaultUnmapper.totalSize;
1137             }
1138         };
1139     }
1140 
1141     /**
1142      * Invoked by sun.management.ManagementFactoryHelper to create the management
1143      * interface for persistent mapped buffers.
1144      */
1145     public static JavaNioAccess.BufferPool getPersistentMappedBufferPool() {
1146         return new JavaNioAccess.BufferPool() {
1147             @Override
1148             public String getName() {
1149                 return "mapped_persistent";
1150             }
1151             @Override
1152             public long getCount() {
1153                 return PersistentUnmapper.count;
1154             }
1155             @Override
1156             public long getTotalCapacity() {
1157                 return PersistentUnmapper.totalCapacity;
1158             }
1159             @Override
1160             public long getMemoryUsed() {
1161                 return PersistentUnmapper.totalSize;
1162             }
1163         };
1164     }
1165 
1166     // -- Locks --
1167 
1168     // keeps track of locks on this file
1169     private volatile FileLockTable fileLockTable;
1170 
1171     private FileLockTable fileLockTable() throws IOException {
1172         if (fileLockTable == null) {
1173             synchronized (this) {
1174                 if (fileLockTable == null) {
1175                     int ti = threads.add();
1176                     try {
1177                         ensureOpen();
1178                         fileLockTable = new FileLockTable(this, fd);
1179                     } finally {
1180                         threads.remove(ti);
1181                     }


1267         } finally {
1268             threads.remove(ti);
1269         }
1270     }
1271 
1272     void release(FileLockImpl fli) throws IOException {
1273         int ti = threads.add();
1274         try {
1275             ensureOpen();
1276             nd.release(fd, fli.position(), fli.size());
1277         } finally {
1278             threads.remove(ti);
1279         }
1280         assert fileLockTable != null;
1281         fileLockTable.remove(fli);
1282     }
1283 
1284     // -- Native methods --
1285 
1286     // Creates a new mapping
1287     private native long map0(int prot, long position, long length, boolean isPersistent)
1288         throws IOException;
1289 
1290     // Removes an existing mapping
1291     private static native int unmap0(long address, long length);
1292 
1293     // Transfers from src to dst, or returns -2 if kernel can't do that
1294     private native long transferTo0(FileDescriptor src, long position,
1295                                     long count, FileDescriptor dst);
1296 
1297     // Caches fieldIDs
1298     private static native long initIDs();
1299 
1300     static {
1301         IOUtil.load();
1302         allocationGranularity = initIDs();
1303     }
1304 }
< prev index next >