24 */ 25 26 package sun.nio.ch; 27 28 import java.io.FileDescriptor; 29 import java.io.IOException; 30 import java.lang.ref.Cleaner.Cleanable; 31 import java.nio.ByteBuffer; 32 import java.nio.MappedByteBuffer; 33 import java.nio.channels.ClosedByInterruptException; 34 import java.nio.channels.ClosedChannelException; 35 import java.nio.channels.FileChannel; 36 import java.nio.channels.FileLock; 37 import java.nio.channels.FileLockInterruptionException; 38 import java.nio.channels.NonReadableChannelException; 39 import java.nio.channels.NonWritableChannelException; 40 import java.nio.channels.OverlappingFileLockException; 41 import java.nio.channels.ReadableByteChannel; 42 import java.nio.channels.SelectableChannel; 43 import java.nio.channels.WritableByteChannel; 44 import java.util.ArrayList; 45 import java.util.List; 46 47 import jdk.internal.misc.JavaIOFileDescriptorAccess; 48 import jdk.internal.misc.JavaNioAccess; 49 import jdk.internal.misc.SharedSecrets; 50 import jdk.internal.ref.Cleaner; 51 import jdk.internal.ref.CleanerFactory; 52 import sun.security.action.GetPropertyAction; 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 70 // File access mode (immutable) 71 private final boolean writable; 72 private final boolean readable; 73 74 // Required to prevent finalization of creating stream (immutable) 75 private final Object parent; 76 77 // The path of the referenced file 78 // (null if the parent stream is created with a file descriptor) 79 private final String path; 80 81 // Thread-safe set of IDs of native threads, for signalling 82 private final NativeThreadSet threads = new NativeThreadSet(2); 83 84 // Lock for operations involving position and size 85 private final Object positionLock = new Object(); 86 87 // Positional-read is not interruptible 88 private volatile boolean uninterruptible; 89 90 // Cleanable with an action which closes this channel's file descriptor 91 private final Cleanable closer; 92 93 private FileChannelImpl(FileDescriptor fd, String path, boolean readable, 94 boolean writable, Object parent) 95 { 96 this.fd = fd; 97 this.readable = readable; 98 this.writable = writable; 99 this.parent = parent; 100 this.path = path; 101 this.nd = new FileDispatcherImpl(); 102 // Register a cleaning action if and only if there is no parent 103 // as the parent will take care of closing the file descriptor. 104 this.closer= parent != null ? null : 105 CleanerFactory.cleaner().register(this, () -> fdAccess.close(fd)); 106 } 107 108 // Used by FileInputStream.getChannel(), FileOutputStream.getChannel 109 // and RandomAccessFile.getChannel() 110 public static FileChannel open(FileDescriptor fd, String path, 111 boolean readable, boolean writable, 112 Object parent) 113 { 114 return new FileChannelImpl(fd, path, readable, writable, parent); 115 } 116 117 private void ensureOpen() throws IOException { 118 if (!isOpen()) 119 throw new ClosedChannelException(); 120 } 121 122 public void setUninterruptible() { 123 uninterruptible = true; 124 } 125 126 // -- Standard channel operations -- 127 128 protected void implCloseChannel() throws IOException { 129 if (!fd.valid()) 130 return; // nothing to do 131 132 // Release and invalidate any locks that we still hold 133 if (fileLockTable != null) { 134 for (FileLock fl: fileLockTable.removeAll()) { 150 // will reinvoke our close method, which is defined in the 151 // superclass AbstractInterruptibleChannel, but the isOpen logic in 152 // that method will prevent this method from being reinvoked. 153 // 154 ((java.io.Closeable)parent).close(); 155 } else if (closer != null) { 156 // Perform the cleaning action so it is not redone when 157 // this channel becomes phantom reachable. 158 closer.clean(); 159 } else { 160 fdAccess.close(fd); 161 } 162 163 } 164 165 public int read(ByteBuffer dst) throws IOException { 166 ensureOpen(); 167 if (!readable) 168 throw new NonReadableChannelException(); 169 synchronized (positionLock) { 170 int n = 0; 171 int ti = -1; 172 try { 173 begin(); 174 ti = threads.add(); 175 if (!isOpen()) 176 return 0; 177 do { 178 n = IOUtil.read(fd, dst, -1, nd); 179 } while ((n == IOStatus.INTERRUPTED) && isOpen()); 180 return IOStatus.normalize(n); 181 } finally { 182 threads.remove(ti); 183 end(n > 0); 184 assert IOStatus.check(n); 185 } 186 } 187 } 188 189 public long read(ByteBuffer[] dsts, int offset, int length) 190 throws IOException 191 { 192 if ((offset < 0) || (length < 0) || (offset > dsts.length - length)) 193 throw new IndexOutOfBoundsException(); 194 ensureOpen(); 195 if (!readable) 196 throw new NonReadableChannelException(); 197 synchronized (positionLock) { 198 long n = 0; 199 int ti = -1; 200 try { 201 begin(); 202 ti = threads.add(); 203 if (!isOpen()) 204 return 0; 205 do { 206 n = IOUtil.read(fd, dsts, offset, length, nd); 207 } while ((n == IOStatus.INTERRUPTED) && isOpen()); 208 return IOStatus.normalize(n); 209 } finally { 210 threads.remove(ti); 211 end(n > 0); 212 assert IOStatus.check(n); 213 } 214 } 215 } 216 217 public int write(ByteBuffer src) throws IOException { 218 ensureOpen(); 219 if (!writable) 220 throw new NonWritableChannelException(); 221 synchronized (positionLock) { 222 int n = 0; 223 int ti = -1; 224 try { 225 begin(); 226 ti = threads.add(); 227 if (!isOpen()) 228 return 0; 229 do { 230 n = IOUtil.write(fd, src, -1, nd); 231 } while ((n == IOStatus.INTERRUPTED) && isOpen()); 232 return IOStatus.normalize(n); 233 } finally { 234 threads.remove(ti); 235 end(n > 0); 236 assert IOStatus.check(n); 237 } 238 } 239 } 240 241 public long write(ByteBuffer[] srcs, int offset, int length) 242 throws IOException 243 { 244 if ((offset < 0) || (length < 0) || (offset > srcs.length - length)) 245 throw new IndexOutOfBoundsException(); 246 ensureOpen(); 247 if (!writable) 248 throw new NonWritableChannelException(); 249 synchronized (positionLock) { 250 long n = 0; 251 int ti = -1; 252 try { 253 begin(); 254 ti = threads.add(); 255 if (!isOpen()) 256 return 0; 257 do { 258 n = IOUtil.write(fd, srcs, offset, length, nd); 259 } while ((n == IOStatus.INTERRUPTED) && isOpen()); 260 return IOStatus.normalize(n); 261 } finally { 262 threads.remove(ti); 263 end(n > 0); 264 assert IOStatus.check(n); 265 } 266 } 267 } 268 269 // -- Other operations -- 270 271 public long position() throws IOException { 272 ensureOpen(); 273 synchronized (positionLock) { 274 long p = -1; 275 int ti = -1; 276 try { 277 begin(); 278 ti = threads.add(); 721 if (!writable) 722 throw new NonWritableChannelException(); 723 if ((position < 0) || (count < 0)) 724 throw new IllegalArgumentException(); 725 if (position > size()) 726 return 0; 727 if (src instanceof FileChannelImpl) 728 return transferFromFileChannel((FileChannelImpl)src, 729 position, count); 730 731 return transferFromArbitraryChannel(src, position, count); 732 } 733 734 public int read(ByteBuffer dst, long position) throws IOException { 735 if (dst == null) 736 throw new NullPointerException(); 737 if (position < 0) 738 throw new IllegalArgumentException("Negative position"); 739 if (!readable) 740 throw new NonReadableChannelException(); 741 ensureOpen(); 742 if (nd.needsPositionLock()) { 743 synchronized (positionLock) { 744 return readInternal(dst, position); 745 } 746 } else { 747 return readInternal(dst, position); 748 } 749 } 750 751 private int readInternal(ByteBuffer dst, long position) throws IOException { 752 assert !nd.needsPositionLock() || Thread.holdsLock(positionLock); 753 int n = 0; 754 int ti = -1; 755 756 boolean interruptible = !uninterruptible; 757 try { 758 if (interruptible) begin(); 759 ti = threads.add(); 760 if (!isOpen()) 761 return -1; 762 do { 763 n = IOUtil.read(fd, dst, position, nd); 764 } while ((n == IOStatus.INTERRUPTED) && isOpen()); 765 return IOStatus.normalize(n); 766 } finally { 767 threads.remove(ti); 768 if (interruptible) end(n > 0); 769 assert IOStatus.check(n); 770 } 771 } 772 773 public int write(ByteBuffer src, long position) throws IOException { 774 if (src == null) 775 throw new NullPointerException(); 776 if (position < 0) 777 throw new IllegalArgumentException("Negative position"); 778 if (!writable) 779 throw new NonWritableChannelException(); 780 ensureOpen(); 781 if (nd.needsPositionLock()) { 782 synchronized (positionLock) { 783 return writeInternal(src, position); 784 } 785 } else { 786 return writeInternal(src, position); 787 } 788 } 789 790 private int writeInternal(ByteBuffer src, long position) throws IOException { 791 assert !nd.needsPositionLock() || Thread.holdsLock(positionLock); 792 int n = 0; 793 int ti = -1; 794 try { 795 begin(); 796 ti = threads.add(); 797 if (!isOpen()) 798 return -1; 799 do { 800 n = IOUtil.write(fd, src, position, nd); 801 } while ((n == IOStatus.INTERRUPTED) && isOpen()); 802 return IOStatus.normalize(n); 803 } finally { 804 threads.remove(ti); 805 end(n > 0); 806 assert IOStatus.check(n); 807 } 808 } 809 810 811 // -- Memory-mapped buffers -- 812 813 private static class Unmapper 814 implements Runnable 815 { 816 // may be required to close file 817 private static final NativeDispatcher nd = new FileDispatcherImpl(); 818 819 // keep track of mapped buffer usage 820 static volatile int count; | 24 */ 25 26 package sun.nio.ch; 27 28 import java.io.FileDescriptor; 29 import java.io.IOException; 30 import java.lang.ref.Cleaner.Cleanable; 31 import java.nio.ByteBuffer; 32 import java.nio.MappedByteBuffer; 33 import java.nio.channels.ClosedByInterruptException; 34 import java.nio.channels.ClosedChannelException; 35 import java.nio.channels.FileChannel; 36 import java.nio.channels.FileLock; 37 import java.nio.channels.FileLockInterruptionException; 38 import java.nio.channels.NonReadableChannelException; 39 import java.nio.channels.NonWritableChannelException; 40 import java.nio.channels.OverlappingFileLockException; 41 import java.nio.channels.ReadableByteChannel; 42 import java.nio.channels.SelectableChannel; 43 import java.nio.channels.WritableByteChannel; 44 import java.nio.file.Files; 45 import java.nio.file.FileStore; 46 import java.nio.file.FileSystemException; 47 import java.nio.file.Path; 48 import java.nio.file.Paths; 49 import java.util.ArrayList; 50 import java.util.List; 51 52 import jdk.internal.misc.JavaIOFileDescriptorAccess; 53 import jdk.internal.misc.JavaNioAccess; 54 import jdk.internal.misc.SharedSecrets; 55 import jdk.internal.ref.Cleaner; 56 import jdk.internal.ref.CleanerFactory; 57 import sun.security.action.GetPropertyAction; 58 59 public class FileChannelImpl 60 extends FileChannel 61 { 62 // Memory allocation size for mapping buffers 63 private static final long allocationGranularity; 64 65 // Access to FileDescriptor internals 66 private static final JavaIOFileDescriptorAccess fdAccess = 67 SharedSecrets.getJavaIOFileDescriptorAccess(); 68 75 // File access mode (immutable) 76 private final boolean writable; 77 private final boolean readable; 78 79 // Required to prevent finalization of creating stream (immutable) 80 private final Object parent; 81 82 // The path of the referenced file 83 // (null if the parent stream is created with a file descriptor) 84 private final String path; 85 86 // Thread-safe set of IDs of native threads, for signalling 87 private final NativeThreadSet threads = new NativeThreadSet(2); 88 89 // Lock for operations involving position and size 90 private final Object positionLock = new Object(); 91 92 // Positional-read is not interruptible 93 private volatile boolean uninterruptible; 94 95 // DirectIO flag 96 private final boolean direct; 97 98 // IO alignment value for DirectIO 99 private final int alignment; 100 101 // Cleanable with an action which closes this channel's file descriptor 102 private final Cleanable closer; 103 104 private FileChannelImpl(FileDescriptor fd, String path, boolean readable, 105 boolean writable, boolean direct, Object parent) 106 { 107 this.fd = fd; 108 this.readable = readable; 109 this.writable = writable; 110 this.parent = parent; 111 this.path = path; 112 this.direct = direct; 113 this.nd = new FileDispatcherImpl(); 114 if (direct) { 115 assert path != null; 116 this.alignment = nd.setDirectIO(fd, path); 117 } else { 118 this.alignment = -1; 119 } 120 121 // Register a cleaning action if and only if there is no parent 122 // as the parent will take care of closing the file descriptor. 123 this.closer= parent != null ? null : 124 CleanerFactory.cleaner().register(this, () -> fdAccess.close(fd)); 125 } 126 127 // Used by FileInputStream.getChannel(), FileOutputStream.getChannel 128 // and RandomAccessFile.getChannel() 129 public static FileChannel open(FileDescriptor fd, String path, 130 boolean readable, boolean writable, 131 Object parent) 132 { 133 return new FileChannelImpl(fd, path, readable, writable, false, parent); 134 } 135 136 public static FileChannel open(FileDescriptor fd, String path, 137 boolean readable, boolean writable, 138 boolean direct, Object parent) 139 { 140 return new FileChannelImpl(fd, path, readable, writable, direct, parent); 141 } 142 143 private void ensureOpen() throws IOException { 144 if (!isOpen()) 145 throw new ClosedChannelException(); 146 } 147 148 public void setUninterruptible() { 149 uninterruptible = true; 150 } 151 152 // -- Standard channel operations -- 153 154 protected void implCloseChannel() throws IOException { 155 if (!fd.valid()) 156 return; // nothing to do 157 158 // Release and invalidate any locks that we still hold 159 if (fileLockTable != null) { 160 for (FileLock fl: fileLockTable.removeAll()) { 176 // will reinvoke our close method, which is defined in the 177 // superclass AbstractInterruptibleChannel, but the isOpen logic in 178 // that method will prevent this method from being reinvoked. 179 // 180 ((java.io.Closeable)parent).close(); 181 } else if (closer != null) { 182 // Perform the cleaning action so it is not redone when 183 // this channel becomes phantom reachable. 184 closer.clean(); 185 } else { 186 fdAccess.close(fd); 187 } 188 189 } 190 191 public int read(ByteBuffer dst) throws IOException { 192 ensureOpen(); 193 if (!readable) 194 throw new NonReadableChannelException(); 195 synchronized (positionLock) { 196 if (direct) 197 Util.checkChannelPositionAligned(position(), alignment); 198 int n = 0; 199 int ti = -1; 200 try { 201 begin(); 202 ti = threads.add(); 203 if (!isOpen()) 204 return 0; 205 do { 206 n = IOUtil.read(fd, dst, -1, direct, alignment, nd); 207 } while ((n == IOStatus.INTERRUPTED) && isOpen()); 208 return IOStatus.normalize(n); 209 } finally { 210 threads.remove(ti); 211 end(n > 0); 212 assert IOStatus.check(n); 213 } 214 } 215 } 216 217 public long read(ByteBuffer[] dsts, int offset, int length) 218 throws IOException 219 { 220 if ((offset < 0) || (length < 0) || (offset > dsts.length - length)) 221 throw new IndexOutOfBoundsException(); 222 ensureOpen(); 223 if (!readable) 224 throw new NonReadableChannelException(); 225 synchronized (positionLock) { 226 if (direct) 227 Util.checkChannelPositionAligned(position(), alignment); 228 long n = 0; 229 int ti = -1; 230 try { 231 begin(); 232 ti = threads.add(); 233 if (!isOpen()) 234 return 0; 235 do { 236 n = IOUtil.read(fd, dsts, offset, length, 237 direct, alignment, nd); 238 } while ((n == IOStatus.INTERRUPTED) && isOpen()); 239 return IOStatus.normalize(n); 240 } finally { 241 threads.remove(ti); 242 end(n > 0); 243 assert IOStatus.check(n); 244 } 245 } 246 } 247 248 public int write(ByteBuffer src) throws IOException { 249 ensureOpen(); 250 if (!writable) 251 throw new NonWritableChannelException(); 252 synchronized (positionLock) { 253 if (direct) 254 Util.checkChannelPositionAligned(position(), alignment); 255 int n = 0; 256 int ti = -1; 257 try { 258 begin(); 259 ti = threads.add(); 260 if (!isOpen()) 261 return 0; 262 do { 263 n = IOUtil.write(fd, src, -1, direct, alignment, nd); 264 } while ((n == IOStatus.INTERRUPTED) && isOpen()); 265 return IOStatus.normalize(n); 266 } finally { 267 threads.remove(ti); 268 end(n > 0); 269 assert IOStatus.check(n); 270 } 271 } 272 } 273 274 public long write(ByteBuffer[] srcs, int offset, int length) 275 throws IOException 276 { 277 if ((offset < 0) || (length < 0) || (offset > srcs.length - length)) 278 throw new IndexOutOfBoundsException(); 279 ensureOpen(); 280 if (!writable) 281 throw new NonWritableChannelException(); 282 synchronized (positionLock) { 283 if (direct) 284 Util.checkChannelPositionAligned(position(), alignment); 285 long n = 0; 286 int ti = -1; 287 try { 288 begin(); 289 ti = threads.add(); 290 if (!isOpen()) 291 return 0; 292 do { 293 n = IOUtil.write(fd, srcs, offset, length, 294 direct, alignment, nd); 295 } while ((n == IOStatus.INTERRUPTED) && isOpen()); 296 return IOStatus.normalize(n); 297 } finally { 298 threads.remove(ti); 299 end(n > 0); 300 assert IOStatus.check(n); 301 } 302 } 303 } 304 305 // -- Other operations -- 306 307 public long position() throws IOException { 308 ensureOpen(); 309 synchronized (positionLock) { 310 long p = -1; 311 int ti = -1; 312 try { 313 begin(); 314 ti = threads.add(); 757 if (!writable) 758 throw new NonWritableChannelException(); 759 if ((position < 0) || (count < 0)) 760 throw new IllegalArgumentException(); 761 if (position > size()) 762 return 0; 763 if (src instanceof FileChannelImpl) 764 return transferFromFileChannel((FileChannelImpl)src, 765 position, count); 766 767 return transferFromArbitraryChannel(src, position, count); 768 } 769 770 public int read(ByteBuffer dst, long position) throws IOException { 771 if (dst == null) 772 throw new NullPointerException(); 773 if (position < 0) 774 throw new IllegalArgumentException("Negative position"); 775 if (!readable) 776 throw new NonReadableChannelException(); 777 if (direct) 778 Util.checkChannelPositionAligned(position, alignment); 779 ensureOpen(); 780 if (nd.needsPositionLock()) { 781 synchronized (positionLock) { 782 return readInternal(dst, position); 783 } 784 } else { 785 return readInternal(dst, position); 786 } 787 } 788 789 private int readInternal(ByteBuffer dst, long position) throws IOException { 790 assert !nd.needsPositionLock() || Thread.holdsLock(positionLock); 791 int n = 0; 792 int ti = -1; 793 794 boolean interruptible = !uninterruptible; 795 try { 796 if (interruptible) begin(); 797 ti = threads.add(); 798 if (!isOpen()) 799 return -1; 800 do { 801 n = IOUtil.read(fd, dst, position, direct, alignment, nd); 802 } while ((n == IOStatus.INTERRUPTED) && isOpen()); 803 return IOStatus.normalize(n); 804 } finally { 805 threads.remove(ti); 806 if (interruptible) end(n > 0); 807 assert IOStatus.check(n); 808 } 809 } 810 811 public int write(ByteBuffer src, long position) throws IOException { 812 if (src == null) 813 throw new NullPointerException(); 814 if (position < 0) 815 throw new IllegalArgumentException("Negative position"); 816 if (!writable) 817 throw new NonWritableChannelException(); 818 if (direct) 819 Util.checkChannelPositionAligned(position, alignment); 820 ensureOpen(); 821 if (nd.needsPositionLock()) { 822 synchronized (positionLock) { 823 return writeInternal(src, position); 824 } 825 } else { 826 return writeInternal(src, position); 827 } 828 } 829 830 private int writeInternal(ByteBuffer src, long position) throws IOException { 831 assert !nd.needsPositionLock() || Thread.holdsLock(positionLock); 832 int n = 0; 833 int ti = -1; 834 try { 835 begin(); 836 ti = threads.add(); 837 if (!isOpen()) 838 return -1; 839 do { 840 n = IOUtil.write(fd, src, position, direct, alignment, nd); 841 } while ((n == IOStatus.INTERRUPTED) && isOpen()); 842 return IOStatus.normalize(n); 843 } finally { 844 threads.remove(ti); 845 end(n > 0); 846 assert IOStatus.check(n); 847 } 848 } 849 850 851 // -- Memory-mapped buffers -- 852 853 private static class Unmapper 854 implements Runnable 855 { 856 // may be required to close file 857 private static final NativeDispatcher nd = new FileDispatcherImpl(); 858 859 // keep track of mapped buffer usage 860 static volatile int count; |