Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/nio/ch/FileChannelImpl.java
38918 views
/*1* Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.nio.ch;2627import java.io.FileDescriptor;28import java.io.IOException;29import java.nio.ByteBuffer;30import java.nio.MappedByteBuffer;31import java.nio.channels.ClosedByInterruptException;32import java.nio.channels.ClosedChannelException;33import java.nio.channels.FileChannel;34import java.nio.channels.FileLock;35import java.nio.channels.FileLockInterruptionException;36import java.nio.channels.NonReadableChannelException;37import java.nio.channels.NonWritableChannelException;38import java.nio.channels.OverlappingFileLockException;39import java.nio.channels.ReadableByteChannel;40import java.nio.channels.SelectableChannel;41import java.nio.channels.WritableByteChannel;42import java.security.AccessController;43import java.util.ArrayList;44import java.util.List;4546import sun.misc.Cleaner;47import sun.security.action.GetPropertyAction;4849public class FileChannelImpl50extends FileChannel51{52// Memory allocation size for mapping buffers53private static final long allocationGranularity;5455// Used to make native read and write calls56private final FileDispatcher nd;5758// File descriptor59private final FileDescriptor fd;6061// File access mode (immutable)62private final boolean writable;63private final boolean readable;64private final boolean append;6566// Required to prevent finalization of creating stream (immutable)67private final Object parent;6869// The path of the referenced file70// (null if the parent stream is created with a file descriptor)71private final String path;7273// Thread-safe set of IDs of native threads, for signalling74private final NativeThreadSet threads = new NativeThreadSet(2);7576// Lock for operations involving position and size77private final Object positionLock = new Object();7879private FileChannelImpl(FileDescriptor fd, String path, boolean readable,80boolean writable, boolean append, Object parent)81{82this.fd = fd;83this.readable = readable;84this.writable = writable;85this.append = append;86this.parent = parent;87this.path = path;88this.nd = new FileDispatcherImpl(append);89}9091// Used by FileInputStream.getChannel() and RandomAccessFile.getChannel()92public static FileChannel open(FileDescriptor fd, String path,93boolean readable, boolean writable,94Object parent)95{96return new FileChannelImpl(fd, path, readable, writable, false, parent);97}9899// Used by FileOutputStream.getChannel100public static FileChannel open(FileDescriptor fd, String path,101boolean readable, boolean writable,102boolean append, Object parent)103{104return new FileChannelImpl(fd, path, readable, writable, append, parent);105}106107private void ensureOpen() throws IOException {108if (!isOpen())109throw new ClosedChannelException();110}111112113// -- Standard channel operations --114115protected void implCloseChannel() throws IOException {116// Release and invalidate any locks that we still hold117if (fileLockTable != null) {118for (FileLock fl: fileLockTable.removeAll()) {119synchronized (fl) {120if (fl.isValid()) {121nd.release(fd, fl.position(), fl.size());122((FileLockImpl)fl).invalidate();123}124}125}126}127128// signal any threads blocked on this channel129threads.signalAndWait();130131if (parent != null) {132133// Close the fd via the parent stream's close method. The parent134// will reinvoke our close method, which is defined in the135// superclass AbstractInterruptibleChannel, but the isOpen logic in136// that method will prevent this method from being reinvoked.137//138((java.io.Closeable)parent).close();139} else {140nd.close(fd);141}142143}144145public int read(ByteBuffer dst) throws IOException {146ensureOpen();147if (!readable)148throw new NonReadableChannelException();149synchronized (positionLock) {150int n = 0;151int ti = -1;152try {153begin();154ti = threads.add();155if (!isOpen())156return 0;157do {158n = IOUtil.read(fd, dst, -1, nd);159} while ((n == IOStatus.INTERRUPTED) && isOpen());160return IOStatus.normalize(n);161} finally {162threads.remove(ti);163end(n > 0);164assert IOStatus.check(n);165}166}167}168169public long read(ByteBuffer[] dsts, int offset, int length)170throws IOException171{172if ((offset < 0) || (length < 0) || (offset > dsts.length - length))173throw new IndexOutOfBoundsException();174ensureOpen();175if (!readable)176throw new NonReadableChannelException();177synchronized (positionLock) {178long n = 0;179int ti = -1;180try {181begin();182ti = threads.add();183if (!isOpen())184return 0;185do {186n = IOUtil.read(fd, dsts, offset, length, nd);187} while ((n == IOStatus.INTERRUPTED) && isOpen());188return IOStatus.normalize(n);189} finally {190threads.remove(ti);191end(n > 0);192assert IOStatus.check(n);193}194}195}196197public int write(ByteBuffer src) throws IOException {198ensureOpen();199if (!writable)200throw new NonWritableChannelException();201synchronized (positionLock) {202int n = 0;203int ti = -1;204try {205begin();206ti = threads.add();207if (!isOpen())208return 0;209do {210n = IOUtil.write(fd, src, -1, nd);211} while ((n == IOStatus.INTERRUPTED) && isOpen());212return IOStatus.normalize(n);213} finally {214threads.remove(ti);215end(n > 0);216assert IOStatus.check(n);217}218}219}220221public long write(ByteBuffer[] srcs, int offset, int length)222throws IOException223{224if ((offset < 0) || (length < 0) || (offset > srcs.length - length))225throw new IndexOutOfBoundsException();226ensureOpen();227if (!writable)228throw new NonWritableChannelException();229synchronized (positionLock) {230long n = 0;231int ti = -1;232try {233begin();234ti = threads.add();235if (!isOpen())236return 0;237do {238n = IOUtil.write(fd, srcs, offset, length, nd);239} while ((n == IOStatus.INTERRUPTED) && isOpen());240return IOStatus.normalize(n);241} finally {242threads.remove(ti);243end(n > 0);244assert IOStatus.check(n);245}246}247}248249// -- Other operations --250251public long position() throws IOException {252ensureOpen();253synchronized (positionLock) {254long p = -1;255int ti = -1;256try {257begin();258ti = threads.add();259if (!isOpen())260return 0;261do {262// in append-mode then position is advanced to end before writing263p = (append) ? nd.size(fd) : nd.seek(fd, -1);264} while ((p == IOStatus.INTERRUPTED) && isOpen());265return IOStatus.normalize(p);266} finally {267threads.remove(ti);268end(p > -1);269assert IOStatus.check(p);270}271}272}273274public FileChannel position(long newPosition) throws IOException {275ensureOpen();276if (newPosition < 0)277throw new IllegalArgumentException();278synchronized (positionLock) {279long p = -1;280int ti = -1;281try {282begin();283ti = threads.add();284if (!isOpen())285return null;286do {287p = nd.seek(fd, newPosition);288} while ((p == IOStatus.INTERRUPTED) && isOpen());289return this;290} finally {291threads.remove(ti);292end(p > -1);293assert IOStatus.check(p);294}295}296}297298public long size() throws IOException {299ensureOpen();300synchronized (positionLock) {301long s = -1;302int ti = -1;303try {304begin();305ti = threads.add();306if (!isOpen())307return -1;308do {309s = nd.size(fd);310} while ((s == IOStatus.INTERRUPTED) && isOpen());311return IOStatus.normalize(s);312} finally {313threads.remove(ti);314end(s > -1);315assert IOStatus.check(s);316}317}318}319320public FileChannel truncate(long newSize) throws IOException {321ensureOpen();322if (newSize < 0)323throw new IllegalArgumentException("Negative size");324if (!writable)325throw new NonWritableChannelException();326synchronized (positionLock) {327int rv = -1;328long p = -1;329int ti = -1;330long rp = -1;331try {332begin();333ti = threads.add();334if (!isOpen())335return null;336337// get current size338long size;339do {340size = nd.size(fd);341} while ((size == IOStatus.INTERRUPTED) && isOpen());342if (!isOpen())343return null;344345// get current position346do {347p = nd.seek(fd, -1);348} while ((p == IOStatus.INTERRUPTED) && isOpen());349if (!isOpen())350return null;351assert p >= 0;352353// truncate file if given size is less than the current size354if (newSize < size) {355do {356rv = nd.truncate(fd, newSize);357} while ((rv == IOStatus.INTERRUPTED) && isOpen());358if (!isOpen())359return null;360}361362// if position is beyond new size then adjust it363if (p > newSize)364p = newSize;365do {366rp = nd.seek(fd, p);367} while ((rp == IOStatus.INTERRUPTED) && isOpen());368return this;369} finally {370threads.remove(ti);371end(rv > -1);372assert IOStatus.check(rv);373}374}375}376377public void force(boolean metaData) throws IOException {378ensureOpen();379int rv = -1;380int ti = -1;381try {382begin();383ti = threads.add();384if (!isOpen())385return;386do {387rv = nd.force(fd, metaData);388} while ((rv == IOStatus.INTERRUPTED) && isOpen());389} finally {390threads.remove(ti);391end(rv > -1);392assert IOStatus.check(rv);393}394}395396// Assume at first that the underlying kernel supports sendfile();397// set this to false if we find out later that it doesn't398//399private static volatile boolean transferSupported = true;400401// Assume that the underlying kernel sendfile() will work if the target402// fd is a pipe; set this to false if we find out later that it doesn't403//404private static volatile boolean pipeSupported = true;405406// Assume that the underlying kernel sendfile() will work if the target407// fd is a file; set this to false if we find out later that it doesn't408//409private static volatile boolean fileSupported = true;410411private long transferToDirectlyInternal(long position, int icount,412WritableByteChannel target,413FileDescriptor targetFD)414throws IOException415{416assert !nd.transferToDirectlyNeedsPositionLock() ||417Thread.holdsLock(positionLock);418419long n = -1;420int ti = -1;421try {422begin();423ti = threads.add();424if (!isOpen())425return -1;426do {427n = transferTo0(fd, position, icount, targetFD);428} while ((n == IOStatus.INTERRUPTED) && isOpen());429if (n == IOStatus.UNSUPPORTED_CASE) {430if (target instanceof SinkChannelImpl)431pipeSupported = false;432if (target instanceof FileChannelImpl)433fileSupported = false;434return IOStatus.UNSUPPORTED_CASE;435}436if (n == IOStatus.UNSUPPORTED) {437// Don't bother trying again438transferSupported = false;439return IOStatus.UNSUPPORTED;440}441return IOStatus.normalize(n);442} finally {443threads.remove(ti);444end (n > -1);445}446}447448private long transferToDirectly(long position, int icount,449WritableByteChannel target)450throws IOException451{452if (!transferSupported)453return IOStatus.UNSUPPORTED;454455FileDescriptor targetFD = null;456if (target instanceof FileChannelImpl) {457if (!fileSupported)458return IOStatus.UNSUPPORTED_CASE;459targetFD = ((FileChannelImpl)target).fd;460} else if (target instanceof SelChImpl) {461// Direct transfer to pipe causes EINVAL on some configurations462if ((target instanceof SinkChannelImpl) && !pipeSupported)463return IOStatus.UNSUPPORTED_CASE;464465// Platform-specific restrictions. Now there is only one:466// Direct transfer to non-blocking channel could be forbidden467SelectableChannel sc = (SelectableChannel)target;468if (!nd.canTransferToDirectly(sc))469return IOStatus.UNSUPPORTED_CASE;470471targetFD = ((SelChImpl)target).getFD();472}473474if (targetFD == null)475return IOStatus.UNSUPPORTED;476int thisFDVal = IOUtil.fdVal(fd);477int targetFDVal = IOUtil.fdVal(targetFD);478if (thisFDVal == targetFDVal) // Not supported on some configurations479return IOStatus.UNSUPPORTED;480481if (nd.transferToDirectlyNeedsPositionLock()) {482synchronized (positionLock) {483long pos = position();484try {485return transferToDirectlyInternal(position, icount,486target, targetFD);487} finally {488position(pos);489}490}491} else {492return transferToDirectlyInternal(position, icount, target, targetFD);493}494}495496// Maximum size to map when using a mapped buffer497private static final long MAPPED_TRANSFER_SIZE = 8L*1024L*1024L;498499private long transferToTrustedChannel(long position, long count,500WritableByteChannel target)501throws IOException502{503boolean isSelChImpl = (target instanceof SelChImpl);504if (!((target instanceof FileChannelImpl) || isSelChImpl))505return IOStatus.UNSUPPORTED;506507// Trusted target: Use a mapped buffer508long remaining = count;509while (remaining > 0L) {510long size = Math.min(remaining, MAPPED_TRANSFER_SIZE);511try {512MappedByteBuffer dbb = map(MapMode.READ_ONLY, position, size);513try {514// ## Bug: Closing this channel will not terminate the write515int n = target.write(dbb);516assert n >= 0;517remaining -= n;518if (isSelChImpl) {519// one attempt to write to selectable channel520break;521}522assert n > 0;523position += n;524} finally {525unmap(dbb);526}527} catch (ClosedByInterruptException e) {528// target closed by interrupt as ClosedByInterruptException needs529// to be thrown after closing this channel.530assert !target.isOpen();531try {532close();533} catch (Throwable suppressed) {534e.addSuppressed(suppressed);535}536throw e;537} catch (IOException ioe) {538// Only throw exception if no bytes have been written539if (remaining == count)540throw ioe;541break;542}543}544return count - remaining;545}546547private long transferToArbitraryChannel(long position, int icount,548WritableByteChannel target)549throws IOException550{551// Untrusted target: Use a newly-erased buffer552int c = Math.min(icount, TRANSFER_SIZE);553ByteBuffer bb = ByteBuffer.allocate(c);554long tw = 0; // Total bytes written555long pos = position;556try {557while (tw < icount) {558bb.limit(Math.min((int)(icount - tw), TRANSFER_SIZE));559int nr = read(bb, pos);560if (nr <= 0)561break;562bb.flip();563// ## Bug: Will block writing target if this channel564// ## is asynchronously closed565int nw = target.write(bb);566tw += nw;567if (nw != nr)568break;569pos += nw;570bb.clear();571}572return tw;573} catch (IOException x) {574if (tw > 0)575return tw;576throw x;577}578}579580public long transferTo(long position, long count,581WritableByteChannel target)582throws IOException583{584ensureOpen();585if (!target.isOpen())586throw new ClosedChannelException();587if (!readable)588throw new NonReadableChannelException();589if (target instanceof FileChannelImpl &&590!((FileChannelImpl)target).writable)591throw new NonWritableChannelException();592if ((position < 0) || (count < 0))593throw new IllegalArgumentException();594long sz = size();595if (position > sz)596return 0;597int icount = (int)Math.min(count, Integer.MAX_VALUE);598if ((sz - position) < icount)599icount = (int)(sz - position);600601long n;602603// Attempt a direct transfer, if the kernel supports it604if ((n = transferToDirectly(position, icount, target)) >= 0)605return n;606607// Attempt a mapped transfer, but only to trusted channel types608if ((n = transferToTrustedChannel(position, icount, target)) >= 0)609return n;610611// Slow path for untrusted targets612return transferToArbitraryChannel(position, icount, target);613}614615private long transferFromFileChannel(FileChannelImpl src,616long position, long count)617throws IOException618{619if (!src.readable)620throw new NonReadableChannelException();621synchronized (src.positionLock) {622long pos = src.position();623long max = Math.min(count, src.size() - pos);624625long remaining = max;626long p = pos;627while (remaining > 0L) {628long size = Math.min(remaining, MAPPED_TRANSFER_SIZE);629// ## Bug: Closing this channel will not terminate the write630MappedByteBuffer bb = src.map(MapMode.READ_ONLY, p, size);631try {632long n = write(bb, position);633assert n > 0;634p += n;635position += n;636remaining -= n;637} catch (IOException ioe) {638// Only throw exception if no bytes have been written639if (remaining == max)640throw ioe;641break;642} finally {643unmap(bb);644}645}646long nwritten = max - remaining;647src.position(pos + nwritten);648return nwritten;649}650}651652private static final int TRANSFER_SIZE = 8192;653654private long transferFromArbitraryChannel(ReadableByteChannel src,655long position, long count)656throws IOException657{658// Untrusted target: Use a newly-erased buffer659int c = (int)Math.min(count, TRANSFER_SIZE);660ByteBuffer bb = ByteBuffer.allocate(c);661long tw = 0; // Total bytes written662long pos = position;663try {664while (tw < count) {665bb.limit((int)Math.min((count - tw), (long)TRANSFER_SIZE));666// ## Bug: Will block reading src if this channel667// ## is asynchronously closed668int nr = src.read(bb);669if (nr <= 0)670break;671bb.flip();672int nw = write(bb, pos);673tw += nw;674if (nw != nr)675break;676pos += nw;677bb.clear();678}679return tw;680} catch (IOException x) {681if (tw > 0)682return tw;683throw x;684}685}686687public long transferFrom(ReadableByteChannel src,688long position, long count)689throws IOException690{691ensureOpen();692if (!src.isOpen())693throw new ClosedChannelException();694if (!writable)695throw new NonWritableChannelException();696if ((position < 0) || (count < 0))697throw new IllegalArgumentException();698if (position > size())699return 0;700if (src instanceof FileChannelImpl)701return transferFromFileChannel((FileChannelImpl)src,702position, count);703704return transferFromArbitraryChannel(src, position, count);705}706707public int read(ByteBuffer dst, long position) throws IOException {708if (dst == null)709throw new NullPointerException();710if (position < 0)711throw new IllegalArgumentException("Negative position");712if (!readable)713throw new NonReadableChannelException();714ensureOpen();715if (nd.needsPositionLock()) {716synchronized (positionLock) {717return readInternal(dst, position);718}719} else {720return readInternal(dst, position);721}722}723724private int readInternal(ByteBuffer dst, long position) throws IOException {725assert !nd.needsPositionLock() || Thread.holdsLock(positionLock);726int n = 0;727int ti = -1;728try {729begin();730ti = threads.add();731if (!isOpen())732return -1;733do {734n = IOUtil.read(fd, dst, position, nd);735} while ((n == IOStatus.INTERRUPTED) && isOpen());736return IOStatus.normalize(n);737} finally {738threads.remove(ti);739end(n > 0);740assert IOStatus.check(n);741}742}743744public int write(ByteBuffer src, long position) throws IOException {745if (src == null)746throw new NullPointerException();747if (position < 0)748throw new IllegalArgumentException("Negative position");749if (!writable)750throw new NonWritableChannelException();751ensureOpen();752if (nd.needsPositionLock()) {753synchronized (positionLock) {754return writeInternal(src, position);755}756} else {757return writeInternal(src, position);758}759}760761private int writeInternal(ByteBuffer src, long position) throws IOException {762assert !nd.needsPositionLock() || Thread.holdsLock(positionLock);763int n = 0;764int ti = -1;765try {766begin();767ti = threads.add();768if (!isOpen())769return -1;770do {771n = IOUtil.write(fd, src, position, nd);772} while ((n == IOStatus.INTERRUPTED) && isOpen());773return IOStatus.normalize(n);774} finally {775threads.remove(ti);776end(n > 0);777assert IOStatus.check(n);778}779}780781782// -- Memory-mapped buffers --783784private static class Unmapper785implements Runnable786{787// may be required to close file788private static final NativeDispatcher nd = new FileDispatcherImpl();789790// keep track of mapped buffer usage791static volatile int count;792static volatile long totalSize;793static volatile long totalCapacity;794795private volatile long address;796private final long size;797private final int cap;798private final FileDescriptor fd;799800private Unmapper(long address, long size, int cap,801FileDescriptor fd)802{803assert (address != 0);804this.address = address;805this.size = size;806this.cap = cap;807this.fd = fd;808809synchronized (Unmapper.class) {810count++;811totalSize += size;812totalCapacity += cap;813}814}815816public void run() {817if (address == 0)818return;819unmap0(address, size);820address = 0;821822// if this mapping has a valid file descriptor then we close it823if (fd.valid()) {824try {825nd.close(fd);826} catch (IOException ignore) {827// nothing we can do828}829}830831synchronized (Unmapper.class) {832count--;833totalSize -= size;834totalCapacity -= cap;835}836}837}838839private static void unmap(MappedByteBuffer bb) {840Cleaner cl = ((DirectBuffer)bb).cleaner();841if (cl != null)842cl.clean();843}844845private static final int MAP_RO = 0;846private static final int MAP_RW = 1;847private static final int MAP_PV = 2;848849public MappedByteBuffer map(MapMode mode, long position, long size)850throws IOException851{852ensureOpen();853if (mode == null)854throw new NullPointerException("Mode is null");855if (position < 0L)856throw new IllegalArgumentException("Negative position");857if (size < 0L)858throw new IllegalArgumentException("Negative size");859if (position + size < 0)860throw new IllegalArgumentException("Position + size overflow");861if (size > Integer.MAX_VALUE)862throw new IllegalArgumentException("Size exceeds Integer.MAX_VALUE");863864int imode = -1;865if (mode == MapMode.READ_ONLY)866imode = MAP_RO;867else if (mode == MapMode.READ_WRITE)868imode = MAP_RW;869else if (mode == MapMode.PRIVATE)870imode = MAP_PV;871assert (imode >= 0);872if ((mode != MapMode.READ_ONLY) && !writable)873throw new NonWritableChannelException();874if (!readable)875throw new NonReadableChannelException();876877long addr = -1;878int ti = -1;879try {880begin();881ti = threads.add();882if (!isOpen())883return null;884885long mapSize;886int pagePosition;887synchronized (positionLock) {888long filesize;889do {890filesize = nd.size(fd);891} while ((filesize == IOStatus.INTERRUPTED) && isOpen());892if (!isOpen())893return null;894895if (filesize < position + size) { // Extend file size896if (!writable) {897throw new IOException("Channel not open for writing " +898"- cannot extend file to required size");899}900int rv;901do {902rv = nd.truncate(fd, position + size);903} while ((rv == IOStatus.INTERRUPTED) && isOpen());904if (!isOpen())905return null;906}907908if (size == 0) {909addr = 0;910// a valid file descriptor is not required911FileDescriptor dummy = new FileDescriptor();912if ((!writable) || (imode == MAP_RO))913return Util.newMappedByteBufferR(0, 0, dummy, null);914else915return Util.newMappedByteBuffer(0, 0, dummy, null);916}917918pagePosition = (int)(position % allocationGranularity);919long mapPosition = position - pagePosition;920mapSize = size + pagePosition;921try {922// If map0 did not throw an exception, the address is valid923addr = map0(imode, mapPosition, mapSize);924} catch (OutOfMemoryError x) {925// An OutOfMemoryError may indicate that we've exhausted926// memory so force gc and re-attempt map927System.gc();928try {929Thread.sleep(100);930} catch (InterruptedException y) {931Thread.currentThread().interrupt();932}933try {934addr = map0(imode, mapPosition, mapSize);935} catch (OutOfMemoryError y) {936// After a second OOME, fail937throw new IOException("Map failed", y);938}939}940} // synchronized941942// On Windows, and potentially other platforms, we need an open943// file descriptor for some mapping operations.944FileDescriptor mfd;945try {946mfd = nd.duplicateForMapping(fd);947} catch (IOException ioe) {948unmap0(addr, mapSize);949throw ioe;950}951952assert (IOStatus.checkAll(addr));953assert (addr % allocationGranularity == 0);954int isize = (int)size;955Unmapper um = new Unmapper(addr, mapSize, isize, mfd);956if ((!writable) || (imode == MAP_RO)) {957return Util.newMappedByteBufferR(isize,958addr + pagePosition,959mfd,960um);961} else {962return Util.newMappedByteBuffer(isize,963addr + pagePosition,964mfd,965um);966}967} finally {968threads.remove(ti);969end(IOStatus.checkAll(addr));970}971}972973/**974* Invoked by sun.management.ManagementFactoryHelper to create the management975* interface for mapped buffers.976*/977public static sun.misc.JavaNioAccess.BufferPool getMappedBufferPool() {978return new sun.misc.JavaNioAccess.BufferPool() {979@Override980public String getName() {981return "mapped";982}983@Override984public long getCount() {985return Unmapper.count;986}987@Override988public long getTotalCapacity() {989return Unmapper.totalCapacity;990}991@Override992public long getMemoryUsed() {993return Unmapper.totalSize;994}995};996}997998// -- Locks --999100010011002// keeps track of locks on this file1003private volatile FileLockTable fileLockTable;10041005// indicates if file locks are maintained system-wide (as per spec)1006private static boolean isSharedFileLockTable;10071008// indicates if the disableSystemWideOverlappingFileLockCheck property1009// has been checked1010private static volatile boolean propertyChecked;10111012// The lock list in J2SE 1.4/5.0 was local to each FileChannel instance so1013// the overlap check wasn't system wide when there were multiple channels to1014// the same file. This property is used to get 1.4/5.0 behavior if desired.1015private static boolean isSharedFileLockTable() {1016if (!propertyChecked) {1017synchronized (FileChannelImpl.class) {1018if (!propertyChecked) {1019String value = AccessController.doPrivileged(1020new GetPropertyAction(1021"sun.nio.ch.disableSystemWideOverlappingFileLockCheck"));1022isSharedFileLockTable = ((value == null) || value.equals("false"));1023propertyChecked = true;1024}1025}1026}1027return isSharedFileLockTable;1028}10291030private FileLockTable fileLockTable() throws IOException {1031if (fileLockTable == null) {1032synchronized (this) {1033if (fileLockTable == null) {1034if (isSharedFileLockTable()) {1035int ti = threads.add();1036try {1037ensureOpen();1038fileLockTable = FileLockTable.newSharedFileLockTable(this, fd);1039} finally {1040threads.remove(ti);1041}1042} else {1043fileLockTable = new SimpleFileLockTable();1044}1045}1046}1047}1048return fileLockTable;1049}10501051public FileLock lock(long position, long size, boolean shared)1052throws IOException1053{1054ensureOpen();1055if (shared && !readable)1056throw new NonReadableChannelException();1057if (!shared && !writable)1058throw new NonWritableChannelException();1059FileLockImpl fli = new FileLockImpl(this, position, size, shared);1060FileLockTable flt = fileLockTable();1061flt.add(fli);1062boolean completed = false;1063int ti = -1;1064try {1065begin();1066ti = threads.add();1067if (!isOpen())1068return null;1069int n;1070do {1071n = nd.lock(fd, true, position, size, shared);1072} while ((n == FileDispatcher.INTERRUPTED) && isOpen());1073if (isOpen()) {1074if (n == FileDispatcher.RET_EX_LOCK) {1075assert shared;1076FileLockImpl fli2 = new FileLockImpl(this, position, size,1077false);1078flt.replace(fli, fli2);1079fli = fli2;1080}1081completed = true;1082}1083} finally {1084if (!completed)1085flt.remove(fli);1086threads.remove(ti);1087try {1088end(completed);1089} catch (ClosedByInterruptException e) {1090throw new FileLockInterruptionException();1091}1092}1093return fli;1094}10951096public FileLock tryLock(long position, long size, boolean shared)1097throws IOException1098{1099ensureOpen();1100if (shared && !readable)1101throw new NonReadableChannelException();1102if (!shared && !writable)1103throw new NonWritableChannelException();1104FileLockImpl fli = new FileLockImpl(this, position, size, shared);1105FileLockTable flt = fileLockTable();1106flt.add(fli);1107int result;11081109int ti = threads.add();1110try {1111try {1112ensureOpen();1113result = nd.lock(fd, false, position, size, shared);1114} catch (IOException e) {1115flt.remove(fli);1116throw e;1117}1118if (result == FileDispatcher.NO_LOCK) {1119flt.remove(fli);1120return null;1121}1122if (result == FileDispatcher.RET_EX_LOCK) {1123assert shared;1124FileLockImpl fli2 = new FileLockImpl(this, position, size,1125false);1126flt.replace(fli, fli2);1127return fli2;1128}1129return fli;1130} finally {1131threads.remove(ti);1132}1133}11341135void release(FileLockImpl fli) throws IOException {1136int ti = threads.add();1137try {1138ensureOpen();1139nd.release(fd, fli.position(), fli.size());1140} finally {1141threads.remove(ti);1142}1143assert fileLockTable != null;1144fileLockTable.remove(fli);1145}11461147// -- File lock support --11481149/**1150* A simple file lock table that maintains a list of FileLocks obtained by a1151* FileChannel. Use to get 1.4/5.0 behaviour.1152*/1153private static class SimpleFileLockTable extends FileLockTable {1154// synchronize on list for access1155private final List<FileLock> lockList = new ArrayList<FileLock>(2);11561157public SimpleFileLockTable() {1158}11591160private void checkList(long position, long size)1161throws OverlappingFileLockException1162{1163assert Thread.holdsLock(lockList);1164for (FileLock fl: lockList) {1165if (fl.overlaps(position, size)) {1166throw new OverlappingFileLockException();1167}1168}1169}11701171public void add(FileLock fl) throws OverlappingFileLockException {1172synchronized (lockList) {1173checkList(fl.position(), fl.size());1174lockList.add(fl);1175}1176}11771178public void remove(FileLock fl) {1179synchronized (lockList) {1180lockList.remove(fl);1181}1182}11831184public List<FileLock> removeAll() {1185synchronized(lockList) {1186List<FileLock> result = new ArrayList<FileLock>(lockList);1187lockList.clear();1188return result;1189}1190}11911192public void replace(FileLock fl1, FileLock fl2) {1193synchronized (lockList) {1194lockList.remove(fl1);1195lockList.add(fl2);1196}1197}1198}11991200// -- Native methods --12011202// Creates a new mapping1203private native long map0(int prot, long position, long length)1204throws IOException;12051206// Removes an existing mapping1207private static native int unmap0(long address, long length);12081209// Transfers from src to dst, or returns -2 if kernel can't do that1210private native long transferTo0(FileDescriptor src, long position,1211long count, FileDescriptor dst);12121213// Caches fieldIDs1214private static native long initIDs();12151216static {1217IOUtil.load();1218allocationGranularity = initIDs();1219}12201221}122212231224