< prev index next >

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

Print this page




  25 
  26 package sun.nio.ch;
  27 
  28 import java.io.FileDescriptor;
  29 import java.io.IOException;
  30 import java.io.UncheckedIOException;
  31 import java.lang.ref.Cleaner.Cleanable;
  32 import java.nio.ByteBuffer;
  33 import java.nio.MappedByteBuffer;
  34 import java.nio.channels.AsynchronousCloseException;
  35 import java.nio.channels.ClosedByInterruptException;
  36 import java.nio.channels.ClosedChannelException;
  37 import java.nio.channels.FileChannel;
  38 import java.nio.channels.FileLock;
  39 import java.nio.channels.FileLockInterruptionException;
  40 import java.nio.channels.NonReadableChannelException;
  41 import java.nio.channels.NonWritableChannelException;
  42 import java.nio.channels.ReadableByteChannel;
  43 import java.nio.channels.SelectableChannel;
  44 import java.nio.channels.WritableByteChannel;

  45 
  46 import jdk.internal.access.JavaIOFileDescriptorAccess;
  47 import jdk.internal.access.JavaNioAccess;
  48 import jdk.internal.access.SharedSecrets;
  49 import jdk.internal.misc.ExtendedMapMode;
  50 import jdk.internal.misc.Unsafe;
  51 import jdk.internal.ref.Cleaner;
  52 import jdk.internal.ref.CleanerFactory;
  53 


  54 public class FileChannelImpl
  55     extends FileChannel
  56 {
  57     // Memory allocation size for mapping buffers
  58     private static final long allocationGranularity;
  59 
  60     // Access to FileDescriptor internals
  61     private static final JavaIOFileDescriptorAccess fdAccess =
  62         SharedSecrets.getJavaIOFileDescriptorAccess();
  63 
  64     // Used to make native read and write calls
  65     private final FileDispatcher nd;
  66 
  67     // File descriptor
  68     private final FileDescriptor fd;
  69 
  70     // File access mode (immutable)
  71     private final boolean writable;
  72     private final boolean readable;
  73 


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

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






 884         }
 885 

 886         public void run() {




 887             if (address == 0)
 888                 return;
 889             unmap0(address, size);
 890             address = 0;
 891 
 892             // if this mapping has a valid file descriptor then we close it
 893             if (fd.valid()) {
 894                 try {
 895                     nd.close(fd);
 896                 } catch (IOException ignore) {
 897                     // nothing we can do
 898                 }
 899             }
 900 
 901             decrementStats();
 902         }
 903         protected abstract void incrementStats();
 904         protected abstract void decrementStats();
 905     }
 906 
 907     private static class DefaultUnmapper extends Unmapper {
 908 
 909         // keep track of non-sync mapped buffer usage
 910         static volatile int count;
 911         static volatile long totalSize;
 912         static volatile long totalCapacity;
 913 
 914         public DefaultUnmapper(long address, long size, int cap,
 915                                      FileDescriptor fd) {
 916             super(address, size, cap, fd);
 917             incrementStats();
 918         }
 919 
 920         protected void incrementStats() {
 921             synchronized (DefaultUnmapper.class) {
 922                 count++;
 923                 totalSize += size;
 924                 totalCapacity += cap;
 925             }
 926         }
 927         protected void decrementStats() {
 928             synchronized (DefaultUnmapper.class) {
 929                 count--;
 930                 totalSize -= size;
 931                 totalCapacity -= cap;
 932             }
 933         }
 934     }
 935 
 936     private static class SyncUnmapper extends Unmapper {
 937 
 938         // keep track of mapped buffer usage
 939         static volatile int count;
 940         static volatile long totalSize;
 941         static volatile long totalCapacity;
 942 
 943         public SyncUnmapper(long address, long size, int cap,
 944                                   FileDescriptor fd) {
 945             super(address, size, cap, fd);
 946             incrementStats();
 947         }
 948 
 949         protected void incrementStats() {
 950             synchronized (SyncUnmapper.class) {
 951                 count++;
 952                 totalSize += size;
 953                 totalCapacity += cap;
 954             }
 955         }
 956         protected void decrementStats() {
 957             synchronized (SyncUnmapper.class) {
 958                 count--;
 959                 totalSize -= size;
 960                 totalCapacity -= cap;
 961             }
 962         }
 963     }
 964 
 965     private static void unmap(MappedByteBuffer bb) {
 966         Cleaner cl = ((DirectBuffer)bb).cleaner();
 967         if (cl != null)
 968             cl.clean();
 969     }
 970 

 971     private static final int MAP_RO = 0;
 972     private static final int MAP_RW = 1;
 973     private static final int MAP_PV = 2;
 974 
 975     public MappedByteBuffer map(MapMode mode, long position, long size)
































 976         throws IOException
 977     {
 978         ensureOpen();
 979         if (mode == null)
 980             throw new NullPointerException("Mode is null");
 981         if (position < 0L)
 982             throw new IllegalArgumentException("Negative position");
 983         if (size < 0L)
 984             throw new IllegalArgumentException("Negative size");
 985         if (position + size < 0)
 986             throw new IllegalArgumentException("Position + size overflow");
 987         if (size > Integer.MAX_VALUE)
 988             throw new IllegalArgumentException("Size exceeds Integer.MAX_VALUE");
 989 
 990         int imode;
 991         boolean isSync = false;
 992         if (mode == MapMode.READ_ONLY)
 993             imode = MAP_RO;
 994         else if (mode == MapMode.READ_WRITE)
 995             imode = MAP_RW;
 996         else if (mode == MapMode.PRIVATE)
 997             imode = MAP_PV;
 998         else if (mode == ExtendedMapMode.READ_ONLY_SYNC) {
 999             imode = MAP_RO;
1000             isSync = true;
1001         } else if (mode == ExtendedMapMode.READ_WRITE_SYNC) {
1002             imode = MAP_RW;
1003             isSync = true;
1004         } else {
1005             throw new UnsupportedOperationException();
1006         }
1007         if ((mode != MapMode.READ_ONLY) && mode != ExtendedMapMode.READ_ONLY_SYNC && !writable)
1008             throw new NonWritableChannelException();
1009         if (!readable)
1010             throw new NonReadableChannelException();
1011         // reject SYNC request if writeback is not enabled for this platform
1012         if (isSync && !Unsafe.isWritebackEnabled()) {
1013             throw new UnsupportedOperationException();
1014         }
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);
1030                 } while ((filesize == IOStatus.INTERRUPTED) && isOpen());
1031                 if (!isOpen())
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, isSync);
1053                     else
1054                         return Util.newMappedByteBuffer(0, 0, dummy, null, isSync);
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, isSync);
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, isSync);
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 = (isSync
1095                            ? new SyncUnmapper(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                                                  isSync);
1103             } else {
1104                 return Util.newMappedByteBuffer(isize,
1105                                                 addr + pagePosition,
1106                                                 mfd,
1107                                                 um,
1108                                                 isSync);
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;




  25 
  26 package sun.nio.ch;
  27 
  28 import java.io.FileDescriptor;
  29 import java.io.IOException;
  30 import java.io.UncheckedIOException;
  31 import java.lang.ref.Cleaner.Cleanable;
  32 import java.nio.ByteBuffer;
  33 import java.nio.MappedByteBuffer;
  34 import java.nio.channels.AsynchronousCloseException;
  35 import java.nio.channels.ClosedByInterruptException;
  36 import java.nio.channels.ClosedChannelException;
  37 import java.nio.channels.FileChannel;
  38 import java.nio.channels.FileLock;
  39 import java.nio.channels.FileLockInterruptionException;
  40 import java.nio.channels.NonReadableChannelException;
  41 import java.nio.channels.NonWritableChannelException;
  42 import java.nio.channels.ReadableByteChannel;
  43 import java.nio.channels.SelectableChannel;
  44 import java.nio.channels.WritableByteChannel;
  45 import java.util.Objects;
  46 
  47 import jdk.internal.access.JavaIOFileDescriptorAccess;
  48 import jdk.internal.access.JavaNioAccess;
  49 import jdk.internal.access.SharedSecrets;
  50 import jdk.internal.misc.ExtendedMapMode;
  51 import jdk.internal.misc.Unsafe;
  52 import jdk.internal.ref.Cleaner;
  53 import jdk.internal.ref.CleanerFactory;
  54 
  55 import jdk.internal.access.foreign.UnmapperProxy;
  56 
  57 public class FileChannelImpl
  58     extends FileChannel
  59 {
  60     // Memory allocation size for mapping buffers
  61     private static final long allocationGranularity;
  62 
  63     // Access to FileDescriptor internals
  64     private static final JavaIOFileDescriptorAccess fdAccess =
  65         SharedSecrets.getJavaIOFileDescriptorAccess();
  66 
  67     // Used to make native read and write calls
  68     private final FileDispatcher nd;
  69 
  70     // File descriptor
  71     private final FileDescriptor fd;
  72 
  73     // File access mode (immutable)
  74     private final boolean writable;
  75     private final boolean readable;
  76 


 849         try {
 850             beginBlocking();
 851             ti = threads.add();
 852             if (!isOpen())
 853                 return -1;
 854             do {
 855                 n = IOUtil.write(fd, src, position, direct, alignment, nd);
 856             } while ((n == IOStatus.INTERRUPTED) && isOpen());
 857             return IOStatus.normalize(n);
 858         } finally {
 859             threads.remove(ti);
 860             endBlocking(n > 0);
 861             assert IOStatus.check(n);
 862         }
 863     }
 864 
 865 
 866     // -- Memory-mapped buffers --
 867 
 868     private static abstract class Unmapper
 869         implements Runnable, UnmapperProxy
 870     {
 871         // may be required to close file
 872         private static final NativeDispatcher nd = new FileDispatcherImpl();
 873 
 874         private volatile long address;
 875         protected final long size;
 876         protected final long cap;
 877         private final FileDescriptor fd;
 878         private final int pagePosition;
 879 
 880         private Unmapper(long address, long size, long cap,
 881                          FileDescriptor fd, int pagePosition)
 882         {
 883             assert (address != 0);
 884             this.address = address;
 885             this.size = size;
 886             this.cap = cap;
 887             this.fd = fd;
 888             this.pagePosition = pagePosition;
 889         }
 890 
 891         @Override
 892         public long address() {
 893             return address;
 894         }
 895 
 896         @Override
 897         public void run() {
 898             unmap();
 899         }
 900 
 901         public void unmap() {
 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             decrementStats();
 917         }
 918         protected abstract void incrementStats();
 919         protected abstract void decrementStats();
 920     }
 921 
 922     private static class DefaultUnmapper extends Unmapper {
 923 
 924         // keep track of non-sync mapped buffer usage
 925         static volatile int count;
 926         static volatile long totalSize;
 927         static volatile long totalCapacity;
 928 
 929         public DefaultUnmapper(long address, long size, long cap,
 930                                FileDescriptor fd, int pagePosition) {
 931             super(address, size, cap, fd, pagePosition);
 932             incrementStats();
 933         }
 934 
 935         protected void incrementStats() {
 936             synchronized (DefaultUnmapper.class) {
 937                 count++;
 938                 totalSize += size;
 939                 totalCapacity += cap;
 940             }
 941         }
 942         protected void decrementStats() {
 943             synchronized (DefaultUnmapper.class) {
 944                 count--;
 945                 totalSize -= size;
 946                 totalCapacity -= cap;
 947             }
 948         }
 949     }
 950 
 951     private static class SyncUnmapper extends Unmapper {
 952 
 953         // keep track of mapped buffer usage
 954         static volatile int count;
 955         static volatile long totalSize;
 956         static volatile long totalCapacity;
 957 
 958         public SyncUnmapper(long address, long size, long cap,
 959                             FileDescriptor fd, int pagePosition) {
 960             super(address, size, cap, fd, pagePosition);
 961             incrementStats();
 962         }
 963 
 964         protected void incrementStats() {
 965             synchronized (SyncUnmapper.class) {
 966                 count++;
 967                 totalSize += size;
 968                 totalCapacity += cap;
 969             }
 970         }
 971         protected void decrementStats() {
 972             synchronized (SyncUnmapper.class) {
 973                 count--;
 974                 totalSize -= size;
 975                 totalCapacity -= cap;
 976             }
 977         }
 978     }
 979 
 980     private static void unmap(MappedByteBuffer bb) {
 981         Cleaner cl = ((DirectBuffer)bb).cleaner();
 982         if (cl != null)
 983             cl.clean();
 984     }
 985 
 986     private static final int MAP_INVALID = -1;
 987     private static final int MAP_RO = 0;
 988     private static final int MAP_RW = 1;
 989     private static final int MAP_PV = 2;
 990 
 991     public MappedByteBuffer map(MapMode mode, long position, long size) throws IOException {
 992         if (size > Integer.MAX_VALUE)
 993             throw new IllegalArgumentException("Size exceeds Integer.MAX_VALUE");
 994         boolean isSync = isSync(Objects.requireNonNull(mode, "Mode is null"));
 995         int prot = toProt(mode);
 996         Unmapper unmapper = mapInternal(mode, position, size, prot, isSync);
 997         if (unmapper == null) {
 998             // a valid file descriptor is not required
 999             FileDescriptor dummy = new FileDescriptor();
1000             if ((!writable) || (prot == MAP_RO))
1001                 return Util.newMappedByteBufferR(0, 0, dummy, null, isSync);
1002             else
1003                 return Util.newMappedByteBuffer(0, 0, dummy, null, isSync);
1004         } else if ((!writable) || (prot == MAP_RO)) {
1005             return Util.newMappedByteBufferR((int)unmapper.cap,
1006                     unmapper.address + unmapper.pagePosition,
1007                     unmapper.fd,
1008                     unmapper, isSync);
1009         } else {
1010             return Util.newMappedByteBuffer((int)unmapper.cap,
1011                     unmapper.address + unmapper.pagePosition,
1012                     unmapper.fd,
1013                     unmapper, isSync);
1014         }
1015     }
1016 
1017     public Unmapper mapInternal(MapMode mode, long position, long size) throws IOException {
1018         boolean isSync = isSync(Objects.requireNonNull(mode, "Mode is null"));
1019         int prot = toProt(mode);
1020         return mapInternal(mode, position, size, prot, isSync);
1021     }
1022 
1023     private Unmapper mapInternal(MapMode mode, long position, long size, int prot, boolean isSync)
1024         throws IOException
1025     {
1026         ensureOpen();
1027         if (mode == null)
1028             throw new NullPointerException("Mode is null");
1029         if (position < 0L)
1030             throw new IllegalArgumentException("Negative position");
1031         if (size < 0L)
1032             throw new IllegalArgumentException("Negative size");
1033         if (position + size < 0)
1034             throw new IllegalArgumentException("Position + size overflow");




























1035 
1036         checkMode(mode, prot, isSync);
1037         long addr = -1;
1038         int ti = -1;
1039         try {
1040             beginBlocking();
1041             ti = threads.add();
1042             if (!isOpen())
1043                 return null;
1044 
1045             long mapSize;
1046             int pagePosition;
1047             synchronized (positionLock) {
1048                 long filesize;
1049                 do {
1050                     filesize = nd.size(fd);
1051                 } while ((filesize == IOStatus.INTERRUPTED) && isOpen());
1052                 if (!isOpen())
1053                     return null;
1054 
1055                 if (filesize < position + size) { // Extend file size
1056                     if (!writable) {
1057                         throw new IOException("Channel not open for writing " +
1058                             "- cannot extend file to required size");
1059                     }
1060                     int rv;
1061                     do {
1062                         rv = nd.truncate(fd, position + size);
1063                     } while ((rv == IOStatus.INTERRUPTED) && isOpen());
1064                     if (!isOpen())
1065                         return null;
1066                 }
1067 
1068                 if (size == 0) {
1069                     return null;






1070                 }
1071 
1072                 pagePosition = (int)(position % allocationGranularity);
1073                 long mapPosition = position - pagePosition;
1074                 mapSize = size + pagePosition;
1075                 try {
1076                     // If map0 did not throw an exception, the address is valid
1077                     addr = map0(prot, mapPosition, mapSize, isSync);
1078                 } catch (OutOfMemoryError x) {
1079                     // An OutOfMemoryError may indicate that we've exhausted
1080                     // memory so force gc and re-attempt map
1081                     System.gc();
1082                     try {
1083                         Thread.sleep(100);
1084                     } catch (InterruptedException y) {
1085                         Thread.currentThread().interrupt();
1086                     }
1087                     try {
1088                         addr = map0(prot, mapPosition, mapSize, isSync);
1089                     } catch (OutOfMemoryError y) {
1090                         // After a second OOME, fail
1091                         throw new IOException("Map failed", y);
1092                     }
1093                 }
1094             } // synchronized
1095 
1096             // On Windows, and potentially other platforms, we need an open
1097             // file descriptor for some mapping operations.
1098             FileDescriptor mfd;
1099             try {
1100                 mfd = nd.duplicateForMapping(fd);
1101             } catch (IOException ioe) {
1102                 unmap0(addr, mapSize);
1103                 throw ioe;
1104             }
1105 
1106             assert (IOStatus.checkAll(addr));
1107             assert (addr % allocationGranularity == 0);

1108             Unmapper um = (isSync
1109                            ? new SyncUnmapper(addr, mapSize, size, mfd, pagePosition)
1110                            : new DefaultUnmapper(addr, mapSize, size, mfd, pagePosition));
1111             return um;












1112         } finally {
1113             threads.remove(ti);
1114             endBlocking(IOStatus.checkAll(addr));
1115         }
1116     }
1117 
1118     private boolean isSync(MapMode mode) {
1119         return mode == ExtendedMapMode.READ_ONLY_SYNC ||
1120                 mode == ExtendedMapMode.READ_WRITE_SYNC;
1121     }
1122 
1123     private int toProt(MapMode mode) {
1124         int prot;
1125         if (mode == MapMode.READ_ONLY) {
1126             prot = MAP_RO;
1127         } else if (mode == MapMode.READ_WRITE) {
1128             prot = MAP_RW;
1129         } else if (mode == MapMode.PRIVATE) {
1130             prot = MAP_PV;
1131         } else if (mode == ExtendedMapMode.READ_ONLY_SYNC) {
1132             prot = MAP_RO;
1133         } else if (mode == ExtendedMapMode.READ_WRITE_SYNC) {
1134             prot = MAP_RW;
1135         } else {
1136             prot = MAP_INVALID;
1137         }
1138         return prot;
1139     }
1140 
1141     private void checkMode(MapMode mode, int prot, boolean isSync) {
1142         if (prot == MAP_INVALID) {
1143             throw new UnsupportedOperationException();
1144         }
1145         if ((mode != MapMode.READ_ONLY) && mode != ExtendedMapMode.READ_ONLY_SYNC && !writable)
1146             throw new NonWritableChannelException();
1147         if (!readable)
1148             throw new NonReadableChannelException();
1149         // reject SYNC request if writeback is not enabled for this platform
1150         if (isSync && !Unsafe.isWritebackEnabled()) {
1151             throw new UnsupportedOperationException();
1152         }
1153     }
1154 
1155     /**
1156      * Invoked by sun.management.ManagementFactoryHelper to create the management
1157      * interface for mapped buffers.
1158      */
1159     public static JavaNioAccess.BufferPool getMappedBufferPool() {
1160         return new JavaNioAccess.BufferPool() {
1161             @Override
1162             public String getName() {
1163                 return "mapped";
1164             }
1165             @Override
1166             public long getCount() {
1167                 return DefaultUnmapper.count;
1168             }
1169             @Override
1170             public long getTotalCapacity() {
1171                 return DefaultUnmapper.totalCapacity;


< prev index next >