mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 23:04:50 +02:00
8224974: Implement JEP 352
Non-Volatile Mapped Byte Buffers Reviewed-by: alanb, kvn, bpb, gromero, darcy, shade, bulasevich, dchuyko
This commit is contained in:
parent
db359f11b5
commit
047b8bfeb7
53 changed files with 1400 additions and 69 deletions
|
@ -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 java.nio.channels.WritableByteChannel;
|
|||
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 @@ public class FileChannelImpl
|
|||
|
||||
// -- 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 @@ public class FileChannelImpl
|
|||
this.size = size;
|
||||
this.cap = cap;
|
||||
this.fd = fd;
|
||||
|
||||
synchronized (Unmapper.class) {
|
||||
count++;
|
||||
totalSize += size;
|
||||
totalCapacity += cap;
|
||||
}
|
||||
}
|
||||
|
||||
public void run() {
|
||||
|
@ -907,7 +898,63 @@ public class FileChannelImpl
|
|||
}
|
||||
}
|
||||
|
||||
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 @@ public class FileChannelImpl
|
|||
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 @@ public class FileChannelImpl
|
|||
// 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 @@ public class FileChannelImpl
|
|||
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 @@ public class FileChannelImpl
|
|||
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 @@ public class FileChannelImpl
|
|||
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 @@ public class FileChannelImpl
|
|||
}
|
||||
@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 @@ public class FileChannelImpl
|
|||
// -- 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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue