< prev index next >
src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java
Print this page
@@ -1,7 +1,7 @@
/*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
@@ -40,10 +40,11 @@
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.SelectableChannel;
import java.nio.channels.WritableByteChannel;
import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
import jdk.internal.misc.JavaIOFileDescriptorAccess;
import jdk.internal.misc.JavaNioAccess;
import jdk.internal.misc.SharedSecrets;
import jdk.internal.ref.Cleaner;
@@ -130,10 +131,22 @@
}
}
}
}
+ // Release and invalidate any orphaned locks still held
+ if (fileLockStates != null) {
+ for (FileLockState fls : fileLockStates) {
+ synchronized (fls) {
+ if (fls.isValid()) {
+ nd.release(fd, fls.position, fls.size);
+ fls.invalidate();
+ }
+ }
+ }
+ }
+
// signal any threads blocked on this channel
threads.signalAndWait();
if (parent != null) {
@@ -1018,10 +1031,13 @@
// indicates if the disableSystemWideOverlappingFileLockCheck property
// has been checked
private static volatile boolean propertyChecked;
+ // States of locks acquired on the channel
+ private volatile List<FileLockState> fileLockStates;
+
// The lock list in J2SE 1.4/5.0 was local to each FileChannel instance so
// the overlap check wasn't system wide when there were multiple channels to
// the same file. This property is used to get 1.4/5.0 behavior if desired.
private static boolean isSharedFileLockTable() {
if (!propertyChecked) {
@@ -1056,10 +1072,21 @@
}
}
return fileLockTable;
}
+ private List<FileLockState> fileLockStates() {
+ if (fileLockStates == null) {
+ synchronized (this) {
+ if (fileLockStates == null) {
+ fileLockStates = new CopyOnWriteArrayList<FileLockState>();
+ }
+ }
+ }
+ return fileLockStates;
+ }
+
public FileLock lock(long position, long size, boolean shared)
throws IOException
{
ensureOpen();
if (shared && !readable)
@@ -1067,10 +1094,12 @@
if (!shared && !writable)
throw new NonWritableChannelException();
FileLockImpl fli = new FileLockImpl(this, position, size, shared);
FileLockTable flt = fileLockTable();
flt.add(fli);
+ List<FileLockState> fls = fileLockStates();
+ fls.add(fli.getState());
boolean completed = false;
int ti = -1;
try {
begin();
ti = threads.add();
@@ -1084,17 +1113,21 @@
if (n == FileDispatcher.RET_EX_LOCK) {
assert shared;
FileLockImpl fli2 = new FileLockImpl(this, position, size,
false);
flt.replace(fli, fli2);
+ fls.remove(fli.getState());
fli = fli2;
+ fls.add(fli.getState());
}
completed = true;
}
} finally {
- if (!completed)
+ if (!completed) {
flt.remove(fli);
+ fls.remove(fli.getState());
+ }
threads.remove(ti);
try {
end(completed);
} catch (ClosedByInterruptException e) {
throw new FileLockInterruptionException();
@@ -1112,30 +1145,36 @@
if (!shared && !writable)
throw new NonWritableChannelException();
FileLockImpl fli = new FileLockImpl(this, position, size, shared);
FileLockTable flt = fileLockTable();
flt.add(fli);
+ List<FileLockState> fls = fileLockStates();
+ fls.add(fli.getState());
int result;
int ti = threads.add();
try {
try {
ensureOpen();
result = nd.lock(fd, false, position, size, shared);
} catch (IOException e) {
flt.remove(fli);
+ fls.remove(fli.getState());
throw e;
}
if (result == FileDispatcher.NO_LOCK) {
flt.remove(fli);
+ fls.remove(fli.getState());
return null;
}
if (result == FileDispatcher.RET_EX_LOCK) {
assert shared;
FileLockImpl fli2 = new FileLockImpl(this, position, size,
false);
flt.replace(fli, fli2);
+ fls.remove(fli.getState());
+ fls.add(fli2.getState());
return fli2;
}
return fli;
} finally {
threads.remove(ti);
< prev index next >