--- a/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java Tue Aug 20 10:46:23 2019 +0200
+++ b/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java Tue Aug 20 10:11:53 2019 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2019, 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
@@ -46,6 +46,8 @@
import jdk.internal.access.JavaIOFileDescriptorAccess;
import jdk.internal.access.JavaNioAccess;
import jdk.internal.access.SharedSecrets;
+import jdk.internal.misc.ExtendedMapMode;
+import jdk.internal.misc.Unsafe;
import jdk.internal.ref.Cleaner;
import jdk.internal.ref.CleanerFactory;
@@ -860,20 +862,15 @@
// -- Memory-mapped buffers --
- private static class Unmapper
+ private static abstract class Unmapper
implements Runnable
{
// may be required to close file
private static final NativeDispatcher nd = new FileDispatcherImpl();
- // keep track of mapped buffer usage
- static volatile int count;
- static volatile long totalSize;
- static volatile long totalCapacity;
-
private volatile long address;
- private final long size;
- private final int cap;
+ protected final long size;
+ protected final int cap;
private final FileDescriptor fd;
private Unmapper(long address, long size, int cap,
@@ -884,12 +881,6 @@
this.size = size;
this.cap = cap;
this.fd = fd;
-
- synchronized (Unmapper.class) {
- count++;
- totalSize += size;
- totalCapacity += cap;
- }
}
public void run() {
@@ -907,7 +898,63 @@
}
}
- synchronized (Unmapper.class) {
+ decrementStats();
+ }
+ protected abstract void incrementStats();
+ protected abstract void decrementStats();
+ }
+
+ private static class DefaultUnmapper extends Unmapper {
+
+ // keep track of non-sync mapped buffer usage
+ static volatile int count;
+ static volatile long totalSize;
+ static volatile long totalCapacity;
+
+ public DefaultUnmapper(long address, long size, int cap,
+ FileDescriptor fd) {
+ super(address, size, cap, fd);
+ incrementStats();
+ }
+
+ protected void incrementStats() {
+ synchronized (DefaultUnmapper.class) {
+ count++;
+ totalSize += size;
+ totalCapacity += cap;
+ }
+ }
+ protected void decrementStats() {
+ synchronized (DefaultUnmapper.class) {
+ count--;
+ totalSize -= size;
+ totalCapacity -= cap;
+ }
+ }
+ }
+
+ private static class SyncUnmapper extends Unmapper {
+
+ // keep track of mapped buffer usage
+ static volatile int count;
+ static volatile long totalSize;
+ static volatile long totalCapacity;
+
+ public SyncUnmapper(long address, long size, int cap,
+ FileDescriptor fd) {
+ super(address, size, cap, fd);
+ incrementStats();
+ }
+
+ protected void incrementStats() {
+ synchronized (SyncUnmapper.class) {
+ count++;
+ totalSize += size;
+ totalCapacity += cap;
+ }
+ }
+ protected void decrementStats() {
+ synchronized (SyncUnmapper.class) {
count--;
totalSize -= size;
totalCapacity -= cap;
@@ -941,18 +988,30 @@
throw new IllegalArgumentException("Size exceeds Integer.MAX_VALUE");
int imode;
+ boolean isSync = false;
if (mode == MapMode.READ_ONLY)
imode = MAP_RO;
else if (mode == MapMode.READ_WRITE)
imode = MAP_RW;
else if (mode == MapMode.PRIVATE)
imode = MAP_PV;
- else
+ else if (mode == ExtendedMapMode.READ_ONLY_SYNC) {
+ imode = MAP_RO;
+ isSync = true;
+ } else if (mode == ExtendedMapMode.READ_WRITE_SYNC) {
+ imode = MAP_RW;
+ isSync = true;
+ } else {
throw new UnsupportedOperationException();
- if ((mode != MapMode.READ_ONLY) && !writable)
+ }
+ if ((mode != MapMode.READ_ONLY) && mode != ExtendedMapMode.READ_ONLY_SYNC && !writable)
throw new NonWritableChannelException();
if (!readable)
throw new NonReadableChannelException();
+ // reject SYNC request if writeback is not enabled for this platform
+ if (isSync && !Unsafe.isWritebackEnabled()) {
+ throw new UnsupportedOperationException();
+ }
long addr = -1;
int ti = -1;
@@ -990,9 +1049,9 @@
// a valid file descriptor is not required
FileDescriptor dummy = new FileDescriptor();
if ((!writable) || (imode == MAP_RO))
- return Util.newMappedByteBufferR(0, 0, dummy, null);
+ return Util.newMappedByteBufferR(0, 0, dummy, null, isSync);
else
- return Util.newMappedByteBuffer(0, 0, dummy, null);
+ return Util.newMappedByteBuffer(0, 0, dummy, null, isSync);
}
pagePosition = (int)(position % allocationGranularity);
@@ -1000,7 +1059,7 @@
mapSize = size + pagePosition;
try {
// If map0 did not throw an exception, the address is valid
- addr = map0(imode, mapPosition, mapSize);
+ addr = map0(imode, mapPosition, mapSize, isSync);
} catch (OutOfMemoryError x) {
// An OutOfMemoryError may indicate that we've exhausted
// memory so force gc and re-attempt map
@@ -1011,7 +1070,7 @@
Thread.currentThread().interrupt();
}
try {
- addr = map0(imode, mapPosition, mapSize);
+ addr = map0(imode, mapPosition, mapSize, isSync);
} catch (OutOfMemoryError y) {
// After a second OOME, fail
throw new IOException("Map failed", y);
@@ -1032,17 +1091,21 @@
assert (IOStatus.checkAll(addr));
assert (addr % allocationGranularity == 0);
int isize = (int)size;
- Unmapper um = new Unmapper(addr, mapSize, isize, mfd);
+ Unmapper um = (isSync
+ ? new SyncUnmapper(addr, mapSize, isize, mfd)
+ : new DefaultUnmapper(addr, mapSize, isize, mfd));
if ((!writable) || (imode == MAP_RO)) {
return Util.newMappedByteBufferR(isize,
addr + pagePosition,
mfd,
- um);
+ um,
+ isSync);
} else {
return Util.newMappedByteBuffer(isize,
addr + pagePosition,
mfd,
- um);
+ um,
+ isSync);
}
} finally {
threads.remove(ti);
@@ -1062,15 +1125,40 @@
}
@Override
public long getCount() {
- return Unmapper.count;
+ return DefaultUnmapper.count;
}
@Override
public long getTotalCapacity() {
- return Unmapper.totalCapacity;
+ return DefaultUnmapper.totalCapacity;
}
@Override
public long getMemoryUsed() {
- return Unmapper.totalSize;
+ return DefaultUnmapper.totalSize;
+ }
+ };
+ }
+
+ /**
+ * Invoked by sun.management.ManagementFactoryHelper to create the management
+ * interface for sync mapped buffers.
+ */
+ public static JavaNioAccess.BufferPool getSyncMappedBufferPool() {
+ return new JavaNioAccess.BufferPool() {
+ @Override
+ public String getName() {
+ return "mapped - 'non-volatile memory'";
+ }
+ @Override
+ public long getCount() {
+ return SyncUnmapper.count;
+ }
+ @Override
+ public long getTotalCapacity() {
+ return SyncUnmapper.totalCapacity;
+ }
+ @Override
+ public long getMemoryUsed() {
+ return SyncUnmapper.totalSize;
}
};
}
@@ -1196,7 +1284,7 @@
// -- Native methods --
// Creates a new mapping
- private native long map0(int prot, long position, long length)
+ private native long map0(int prot, long position, long length, boolean isSync)
throws IOException;
// Removes an existing mapping