src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java
changeset 57804 9b7b9f16dfd9
parent 54532 e9c62d960d64
equal deleted inserted replaced
57803:23e3ab980622 57804:9b7b9f16dfd9
     1 /*
     1 /*
     2  * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    44 import java.nio.channels.WritableByteChannel;
    44 import java.nio.channels.WritableByteChannel;
    45 
    45 
    46 import jdk.internal.access.JavaIOFileDescriptorAccess;
    46 import jdk.internal.access.JavaIOFileDescriptorAccess;
    47 import jdk.internal.access.JavaNioAccess;
    47 import jdk.internal.access.JavaNioAccess;
    48 import jdk.internal.access.SharedSecrets;
    48 import jdk.internal.access.SharedSecrets;
       
    49 import jdk.internal.misc.ExtendedMapMode;
       
    50 import jdk.internal.misc.Unsafe;
    49 import jdk.internal.ref.Cleaner;
    51 import jdk.internal.ref.Cleaner;
    50 import jdk.internal.ref.CleanerFactory;
    52 import jdk.internal.ref.CleanerFactory;
    51 
    53 
    52 public class FileChannelImpl
    54 public class FileChannelImpl
    53     extends FileChannel
    55     extends FileChannel
   858     }
   860     }
   859 
   861 
   860 
   862 
   861     // -- Memory-mapped buffers --
   863     // -- Memory-mapped buffers --
   862 
   864 
   863     private static class Unmapper
   865     private static abstract class Unmapper
   864         implements Runnable
   866         implements Runnable
   865     {
   867     {
   866         // may be required to close file
   868         // may be required to close file
   867         private static final NativeDispatcher nd = new FileDispatcherImpl();
   869         private static final NativeDispatcher nd = new FileDispatcherImpl();
   868 
   870 
   869         // keep track of mapped buffer usage
       
   870         static volatile int count;
       
   871         static volatile long totalSize;
       
   872         static volatile long totalCapacity;
       
   873 
       
   874         private volatile long address;
   871         private volatile long address;
   875         private final long size;
   872         protected final long size;
   876         private final int cap;
   873         protected final int cap;
   877         private final FileDescriptor fd;
   874         private final FileDescriptor fd;
   878 
   875 
   879         private Unmapper(long address, long size, int cap,
   876         private Unmapper(long address, long size, int cap,
   880                          FileDescriptor fd)
   877                          FileDescriptor fd)
   881         {
   878         {
   882             assert (address != 0);
   879             assert (address != 0);
   883             this.address = address;
   880             this.address = address;
   884             this.size = size;
   881             this.size = size;
   885             this.cap = cap;
   882             this.cap = cap;
   886             this.fd = fd;
   883             this.fd = fd;
   887 
       
   888             synchronized (Unmapper.class) {
       
   889                 count++;
       
   890                 totalSize += size;
       
   891                 totalCapacity += cap;
       
   892             }
       
   893         }
   884         }
   894 
   885 
   895         public void run() {
   886         public void run() {
   896             if (address == 0)
   887             if (address == 0)
   897                 return;
   888                 return;
   905                 } catch (IOException ignore) {
   896                 } catch (IOException ignore) {
   906                     // nothing we can do
   897                     // nothing we can do
   907                 }
   898                 }
   908             }
   899             }
   909 
   900 
   910             synchronized (Unmapper.class) {
   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) {
   911                 count--;
   958                 count--;
   912                 totalSize -= size;
   959                 totalSize -= size;
   913                 totalCapacity -= cap;
   960                 totalCapacity -= cap;
   914             }
   961             }
   915         }
   962         }
   939             throw new IllegalArgumentException("Position + size overflow");
   986             throw new IllegalArgumentException("Position + size overflow");
   940         if (size > Integer.MAX_VALUE)
   987         if (size > Integer.MAX_VALUE)
   941             throw new IllegalArgumentException("Size exceeds Integer.MAX_VALUE");
   988             throw new IllegalArgumentException("Size exceeds Integer.MAX_VALUE");
   942 
   989 
   943         int imode;
   990         int imode;
       
   991         boolean isSync = false;
   944         if (mode == MapMode.READ_ONLY)
   992         if (mode == MapMode.READ_ONLY)
   945             imode = MAP_RO;
   993             imode = MAP_RO;
   946         else if (mode == MapMode.READ_WRITE)
   994         else if (mode == MapMode.READ_WRITE)
   947             imode = MAP_RW;
   995             imode = MAP_RW;
   948         else if (mode == MapMode.PRIVATE)
   996         else if (mode == MapMode.PRIVATE)
   949             imode = MAP_PV;
   997             imode = MAP_PV;
   950         else
   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 {
   951             throw new UnsupportedOperationException();
  1005             throw new UnsupportedOperationException();
   952         if ((mode != MapMode.READ_ONLY) && !writable)
  1006         }
       
  1007         if ((mode != MapMode.READ_ONLY) && mode != ExtendedMapMode.READ_ONLY_SYNC && !writable)
   953             throw new NonWritableChannelException();
  1008             throw new NonWritableChannelException();
   954         if (!readable)
  1009         if (!readable)
   955             throw new NonReadableChannelException();
  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         }
   956 
  1015 
   957         long addr = -1;
  1016         long addr = -1;
   958         int ti = -1;
  1017         int ti = -1;
   959         try {
  1018         try {
   960             beginBlocking();
  1019             beginBlocking();
   988                 if (size == 0) {
  1047                 if (size == 0) {
   989                     addr = 0;
  1048                     addr = 0;
   990                     // a valid file descriptor is not required
  1049                     // a valid file descriptor is not required
   991                     FileDescriptor dummy = new FileDescriptor();
  1050                     FileDescriptor dummy = new FileDescriptor();
   992                     if ((!writable) || (imode == MAP_RO))
  1051                     if ((!writable) || (imode == MAP_RO))
   993                         return Util.newMappedByteBufferR(0, 0, dummy, null);
  1052                         return Util.newMappedByteBufferR(0, 0, dummy, null, isSync);
   994                     else
  1053                     else
   995                         return Util.newMappedByteBuffer(0, 0, dummy, null);
  1054                         return Util.newMappedByteBuffer(0, 0, dummy, null, isSync);
   996                 }
  1055                 }
   997 
  1056 
   998                 pagePosition = (int)(position % allocationGranularity);
  1057                 pagePosition = (int)(position % allocationGranularity);
   999                 long mapPosition = position - pagePosition;
  1058                 long mapPosition = position - pagePosition;
  1000                 mapSize = size + pagePosition;
  1059                 mapSize = size + pagePosition;
  1001                 try {
  1060                 try {
  1002                     // If map0 did not throw an exception, the address is valid
  1061                     // If map0 did not throw an exception, the address is valid
  1003                     addr = map0(imode, mapPosition, mapSize);
  1062                     addr = map0(imode, mapPosition, mapSize, isSync);
  1004                 } catch (OutOfMemoryError x) {
  1063                 } catch (OutOfMemoryError x) {
  1005                     // An OutOfMemoryError may indicate that we've exhausted
  1064                     // An OutOfMemoryError may indicate that we've exhausted
  1006                     // memory so force gc and re-attempt map
  1065                     // memory so force gc and re-attempt map
  1007                     System.gc();
  1066                     System.gc();
  1008                     try {
  1067                     try {
  1009                         Thread.sleep(100);
  1068                         Thread.sleep(100);
  1010                     } catch (InterruptedException y) {
  1069                     } catch (InterruptedException y) {
  1011                         Thread.currentThread().interrupt();
  1070                         Thread.currentThread().interrupt();
  1012                     }
  1071                     }
  1013                     try {
  1072                     try {
  1014                         addr = map0(imode, mapPosition, mapSize);
  1073                         addr = map0(imode, mapPosition, mapSize, isSync);
  1015                     } catch (OutOfMemoryError y) {
  1074                     } catch (OutOfMemoryError y) {
  1016                         // After a second OOME, fail
  1075                         // After a second OOME, fail
  1017                         throw new IOException("Map failed", y);
  1076                         throw new IOException("Map failed", y);
  1018                     }
  1077                     }
  1019                 }
  1078                 }
  1030             }
  1089             }
  1031 
  1090 
  1032             assert (IOStatus.checkAll(addr));
  1091             assert (IOStatus.checkAll(addr));
  1033             assert (addr % allocationGranularity == 0);
  1092             assert (addr % allocationGranularity == 0);
  1034             int isize = (int)size;
  1093             int isize = (int)size;
  1035             Unmapper um = new Unmapper(addr, mapSize, isize, mfd);
  1094             Unmapper um = (isSync
       
  1095                            ? new SyncUnmapper(addr, mapSize, isize, mfd)
       
  1096                            : new DefaultUnmapper(addr, mapSize, isize, mfd));
  1036             if ((!writable) || (imode == MAP_RO)) {
  1097             if ((!writable) || (imode == MAP_RO)) {
  1037                 return Util.newMappedByteBufferR(isize,
  1098                 return Util.newMappedByteBufferR(isize,
  1038                                                  addr + pagePosition,
  1099                                                  addr + pagePosition,
  1039                                                  mfd,
  1100                                                  mfd,
  1040                                                  um);
  1101                                                  um,
       
  1102                                                  isSync);
  1041             } else {
  1103             } else {
  1042                 return Util.newMappedByteBuffer(isize,
  1104                 return Util.newMappedByteBuffer(isize,
  1043                                                 addr + pagePosition,
  1105                                                 addr + pagePosition,
  1044                                                 mfd,
  1106                                                 mfd,
  1045                                                 um);
  1107                                                 um,
       
  1108                                                 isSync);
  1046             }
  1109             }
  1047         } finally {
  1110         } finally {
  1048             threads.remove(ti);
  1111             threads.remove(ti);
  1049             endBlocking(IOStatus.checkAll(addr));
  1112             endBlocking(IOStatus.checkAll(addr));
  1050         }
  1113         }
  1060             public String getName() {
  1123             public String getName() {
  1061                 return "mapped";
  1124                 return "mapped";
  1062             }
  1125             }
  1063             @Override
  1126             @Override
  1064             public long getCount() {
  1127             public long getCount() {
  1065                 return Unmapper.count;
  1128                 return DefaultUnmapper.count;
  1066             }
  1129             }
  1067             @Override
  1130             @Override
  1068             public long getTotalCapacity() {
  1131             public long getTotalCapacity() {
  1069                 return Unmapper.totalCapacity;
  1132                 return DefaultUnmapper.totalCapacity;
  1070             }
  1133             }
  1071             @Override
  1134             @Override
  1072             public long getMemoryUsed() {
  1135             public long getMemoryUsed() {
  1073                 return Unmapper.totalSize;
  1136                 return DefaultUnmapper.totalSize;
       
  1137             }
       
  1138         };
       
  1139     }
       
  1140 
       
  1141     /**
       
  1142      * Invoked by sun.management.ManagementFactoryHelper to create the management
       
  1143      * interface for sync mapped buffers.
       
  1144      */
       
  1145     public static JavaNioAccess.BufferPool getSyncMappedBufferPool() {
       
  1146         return new JavaNioAccess.BufferPool() {
       
  1147             @Override
       
  1148             public String getName() {
       
  1149                 return "mapped - 'non-volatile memory'";
       
  1150             }
       
  1151             @Override
       
  1152             public long getCount() {
       
  1153                 return SyncUnmapper.count;
       
  1154             }
       
  1155             @Override
       
  1156             public long getTotalCapacity() {
       
  1157                 return SyncUnmapper.totalCapacity;
       
  1158             }
       
  1159             @Override
       
  1160             public long getMemoryUsed() {
       
  1161                 return SyncUnmapper.totalSize;
  1074             }
  1162             }
  1075         };
  1163         };
  1076     }
  1164     }
  1077 
  1165 
  1078     // -- Locks --
  1166     // -- Locks --
  1194     }
  1282     }
  1195 
  1283 
  1196     // -- Native methods --
  1284     // -- Native methods --
  1197 
  1285 
  1198     // Creates a new mapping
  1286     // Creates a new mapping
  1199     private native long map0(int prot, long position, long length)
  1287     private native long map0(int prot, long position, long length, boolean isSync)
  1200         throws IOException;
  1288         throws IOException;
  1201 
  1289 
  1202     // Removes an existing mapping
  1290     // Removes an existing mapping
  1203     private static native int unmap0(long address, long length);
  1291     private static native int unmap0(long address, long length);
  1204 
  1292