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 |