mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-21 19:44:41 +02:00
6682020: (bf) Support monitoring of direct and mapped buffer usage
Reviewed-by: mchung, iris
This commit is contained in:
parent
827a25e39d
commit
d41b0a77b2
10 changed files with 409 additions and 15 deletions
|
@ -449,6 +449,7 @@ JAVA_JAVA_java = \
|
||||||
sun/misc/JavaLangAccess.java \
|
sun/misc/JavaLangAccess.java \
|
||||||
sun/misc/JavaIOAccess.java \
|
sun/misc/JavaIOAccess.java \
|
||||||
sun/misc/JavaIODeleteOnExitAccess.java \
|
sun/misc/JavaIODeleteOnExitAccess.java \
|
||||||
sun/misc/JavaIOFileDescriptorAccess.java
|
sun/misc/JavaIOFileDescriptorAccess.java \
|
||||||
|
sun/misc/JavaNioAccess.java
|
||||||
|
|
||||||
FILES_java = $(JAVA_JAVA_java)
|
FILES_java = $(JAVA_JAVA_java)
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
FILES_src = \
|
FILES_src = \
|
||||||
java/nio/Bits.java \
|
java/nio/Bits.java \
|
||||||
java/nio/Buffer.java \
|
java/nio/Buffer.java \
|
||||||
|
java/nio/BufferPoolMXBean.java \
|
||||||
java/nio/ByteOrder.java \
|
java/nio/ByteOrder.java \
|
||||||
java/nio/MappedByteBuffer.java \
|
java/nio/MappedByteBuffer.java \
|
||||||
java/nio/StringCharBuffer.java \
|
java/nio/StringCharBuffer.java \
|
||||||
|
|
|
@ -32,6 +32,7 @@ import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.logging.LoggingMXBean;
|
import java.util.logging.LoggingMXBean;
|
||||||
import java.util.logging.LogManager;
|
import java.util.logging.LogManager;
|
||||||
|
import java.nio.BufferPoolMXBean;
|
||||||
import javax.management.MBeanServerConnection;
|
import javax.management.MBeanServerConnection;
|
||||||
import javax.management.MalformedObjectNameException;
|
import javax.management.MalformedObjectNameException;
|
||||||
import javax.management.ObjectName;
|
import javax.management.ObjectName;
|
||||||
|
@ -188,6 +189,23 @@ enum PlatformComponent {
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Buffer pools.
|
||||||
|
*/
|
||||||
|
BUFFER_POOL(
|
||||||
|
"java.nio.BufferPoolMXBean",
|
||||||
|
"java.nio", "BufferPool", keyProperties("name"),
|
||||||
|
new MXBeanFetcher<BufferPoolMXBean>() {
|
||||||
|
public List<BufferPoolMXBean> getMXBeans() {
|
||||||
|
List<BufferPoolMXBean> pools = new ArrayList<BufferPoolMXBean>(2);
|
||||||
|
pools.add( sun.misc.SharedSecrets.getJavaNioAccess().getDirectBufferPoolMXBean() );
|
||||||
|
pools.add( sun.nio.ch.FileChannelImpl.getMappedBufferPoolMXBean() );
|
||||||
|
return pools;
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
|
||||||
|
|
||||||
// Sun Platform Extension
|
// Sun Platform Extension
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -29,6 +29,8 @@ import java.security.AccessController;
|
||||||
import java.security.PrivilegedAction;
|
import java.security.PrivilegedAction;
|
||||||
import sun.misc.Unsafe;
|
import sun.misc.Unsafe;
|
||||||
import sun.misc.VM;
|
import sun.misc.VM;
|
||||||
|
import javax.management.ObjectName;
|
||||||
|
import javax.management.MalformedObjectNameException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Access to bits, native and otherwise.
|
* Access to bits, native and otherwise.
|
||||||
|
@ -625,13 +627,15 @@ class Bits { // package-private
|
||||||
// direct buffer memory. This value may be changed during VM
|
// direct buffer memory. This value may be changed during VM
|
||||||
// initialization if it is launched with "-XX:MaxDirectMemorySize=<size>".
|
// initialization if it is launched with "-XX:MaxDirectMemorySize=<size>".
|
||||||
private static volatile long maxMemory = VM.maxDirectMemory();
|
private static volatile long maxMemory = VM.maxDirectMemory();
|
||||||
private static volatile long reservedMemory = 0;
|
private static volatile long reservedMemory;
|
||||||
|
private static volatile long usedMemory;
|
||||||
|
private static volatile long count;
|
||||||
private static boolean memoryLimitSet = false;
|
private static boolean memoryLimitSet = false;
|
||||||
|
|
||||||
// These methods should be called whenever direct memory is allocated or
|
// These methods should be called whenever direct memory is allocated or
|
||||||
// freed. They allow the user to control the amount of direct memory
|
// freed. They allow the user to control the amount of direct memory
|
||||||
// which a process may access. All sizes are specified in bytes.
|
// which a process may access. All sizes are specified in bytes.
|
||||||
static void reserveMemory(long size) {
|
static void reserveMemory(long size, int cap) {
|
||||||
|
|
||||||
synchronized (Bits.class) {
|
synchronized (Bits.class) {
|
||||||
if (!memoryLimitSet && VM.isBooted()) {
|
if (!memoryLimitSet && VM.isBooted()) {
|
||||||
|
@ -640,6 +644,8 @@ class Bits { // package-private
|
||||||
}
|
}
|
||||||
if (size <= maxMemory - reservedMemory) {
|
if (size <= maxMemory - reservedMemory) {
|
||||||
reservedMemory += size;
|
reservedMemory += size;
|
||||||
|
usedMemory += cap;
|
||||||
|
count++;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -655,17 +661,71 @@ class Bits { // package-private
|
||||||
if (reservedMemory + size > maxMemory)
|
if (reservedMemory + size > maxMemory)
|
||||||
throw new OutOfMemoryError("Direct buffer memory");
|
throw new OutOfMemoryError("Direct buffer memory");
|
||||||
reservedMemory += size;
|
reservedMemory += size;
|
||||||
|
usedMemory += cap;
|
||||||
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static synchronized void unreserveMemory(long size) {
|
static synchronized void unreserveMemory(long size, int cap) {
|
||||||
if (reservedMemory > 0) {
|
if (reservedMemory > 0) {
|
||||||
reservedMemory -= size;
|
reservedMemory -= size;
|
||||||
|
usedMemory -= cap;
|
||||||
|
count--;
|
||||||
assert (reservedMemory > -1);
|
assert (reservedMemory > -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -- Management interface for monitoring of direct buffer usage --
|
||||||
|
|
||||||
|
static {
|
||||||
|
// setup access to this package in SharedSecrets
|
||||||
|
sun.misc.SharedSecrets.setJavaNioAccess(
|
||||||
|
new sun.misc.JavaNioAccess() {
|
||||||
|
@Override
|
||||||
|
public BufferPoolMXBean getDirectBufferPoolMXBean() {
|
||||||
|
return LazyInitialization.directBufferPoolMXBean;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lazy initialization of management interface
|
||||||
|
private static class LazyInitialization {
|
||||||
|
static final BufferPoolMXBean directBufferPoolMXBean = directBufferPoolMXBean();
|
||||||
|
|
||||||
|
private static BufferPoolMXBean directBufferPoolMXBean() {
|
||||||
|
final String pool = "direct";
|
||||||
|
final ObjectName obj;
|
||||||
|
try {
|
||||||
|
obj = new ObjectName("java.nio:type=BufferPool,name=" + pool);
|
||||||
|
} catch (MalformedObjectNameException x) {
|
||||||
|
throw new AssertionError(x);
|
||||||
|
}
|
||||||
|
return new BufferPoolMXBean() {
|
||||||
|
@Override
|
||||||
|
public ObjectName getObjectName() {
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return pool;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public long getCount() {
|
||||||
|
return Bits.count;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public long getTotalCapacity() {
|
||||||
|
return Bits.usedMemory;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public long getMemoryUsed() {
|
||||||
|
return Bits.reservedMemory;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// -- Bulk get/put acceleration --
|
// -- Bulk get/put acceleration --
|
||||||
|
|
||||||
|
|
94
jdk/src/share/classes/java/nio/BufferPoolMXBean.java
Normal file
94
jdk/src/share/classes/java/nio/BufferPoolMXBean.java
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2007-2008 Sun Microsystems, Inc. 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. Sun designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Sun in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||||
|
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||||
|
* have any questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package java.nio;
|
||||||
|
|
||||||
|
import java.lang.management.PlatformManagedObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The management interface for a buffer pool.
|
||||||
|
*
|
||||||
|
* <p> A class implementing this interface is an <a href=
|
||||||
|
* "java.lang.management.ManagementFactory.html#MXBean">MXBean</a>. A Java
|
||||||
|
* virtual machine has one or more implementations of this interface. The {@link
|
||||||
|
* java.lang.management.ManagementFactory#getPlatformMXBeans getPlatformMXBeans}
|
||||||
|
* method can be used to obtain the list of {@code BufferPoolMXBean} objects
|
||||||
|
* representing the management interfaces for pools of buffers as follows:
|
||||||
|
* <pre>
|
||||||
|
* List<BufferPoolMXBean> pools = ManagementFactory.getPlatformMXBeans(BufferPoolMXBean.class);
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* <p> The management interfaces are also registered with the platform {@link
|
||||||
|
* javax.management.MBeanServer MBeanServer}. The {@link
|
||||||
|
* javax.management.ObjectName ObjectName} that uniquely identifies the
|
||||||
|
* management interface within the {@code MBeanServer} takes the form:
|
||||||
|
* <blockquote>
|
||||||
|
* <tt>java.nio:type=BufferPool</tt><tt>,name=</tt><i>pool name</i>
|
||||||
|
* </blockquote>
|
||||||
|
* where <em>pool name</em> is the {@link #getName name} of the buffer pool.
|
||||||
|
*
|
||||||
|
* @since 1.7
|
||||||
|
*/
|
||||||
|
|
||||||
|
public interface BufferPoolMXBean extends PlatformManagedObject {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the name representing this buffer pool.
|
||||||
|
*
|
||||||
|
* @return The name of this buffer pool.
|
||||||
|
*/
|
||||||
|
String getName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an estimate of the number of buffers in the pool.
|
||||||
|
*
|
||||||
|
* @return An estimate of the number of buffers in this pool
|
||||||
|
*/
|
||||||
|
long getCount();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an estimate of the total capacity of the buffers in this pool.
|
||||||
|
* A buffer's capacity is the number of elements it contains and the value
|
||||||
|
* returned by this method is an estimate of the total capacity of buffers
|
||||||
|
* in the pool in bytes.
|
||||||
|
*
|
||||||
|
* @return An estimate of the total capacity of the buffers in this pool
|
||||||
|
* in bytes
|
||||||
|
*/
|
||||||
|
long getTotalCapacity();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an estimate of the memory that the Java virtual machine is using
|
||||||
|
* for this buffer pool. The value returned by this method may differ
|
||||||
|
* from the estimate of the total {@link #getTotalCapacity capacity} of
|
||||||
|
* the buffers in this pool. This difference is explained by alignment,
|
||||||
|
* memory allocator, and other implementation specific reasons.
|
||||||
|
*
|
||||||
|
* @return An estimate of the memory that the Java virtual machine is using
|
||||||
|
* for this buffer pool in bytes, or {@code -1L} if an estimate of
|
||||||
|
* the memory usage is not available
|
||||||
|
*/
|
||||||
|
long getMemoryUsed();
|
||||||
|
}
|
|
@ -71,11 +71,13 @@ class Direct$Type$Buffer$RW$$BO$
|
||||||
private static Unsafe unsafe = Unsafe.getUnsafe();
|
private static Unsafe unsafe = Unsafe.getUnsafe();
|
||||||
|
|
||||||
private long address;
|
private long address;
|
||||||
|
private long size;
|
||||||
private int capacity;
|
private int capacity;
|
||||||
|
|
||||||
private Deallocator(long address, int capacity) {
|
private Deallocator(long address, long size, int capacity) {
|
||||||
assert (address != 0);
|
assert (address != 0);
|
||||||
this.address = address;
|
this.address = address;
|
||||||
|
this.size = size;
|
||||||
this.capacity = capacity;
|
this.capacity = capacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,7 +88,7 @@ class Direct$Type$Buffer$RW$$BO$
|
||||||
}
|
}
|
||||||
unsafe.freeMemory(address);
|
unsafe.freeMemory(address);
|
||||||
address = 0;
|
address = 0;
|
||||||
Bits.unreserveMemory(capacity);
|
Bits.unreserveMemory(size, capacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -110,23 +112,25 @@ class Direct$Type$Buffer$RW$$BO$
|
||||||
Direct$Type$Buffer$RW$(int cap) { // package-private
|
Direct$Type$Buffer$RW$(int cap) { // package-private
|
||||||
#if[rw]
|
#if[rw]
|
||||||
super(-1, 0, cap, cap, false);
|
super(-1, 0, cap, cap, false);
|
||||||
Bits.reserveMemory(cap);
|
|
||||||
int ps = Bits.pageSize();
|
int ps = Bits.pageSize();
|
||||||
|
int size = cap + ps;
|
||||||
|
Bits.reserveMemory(size, cap);
|
||||||
|
|
||||||
long base = 0;
|
long base = 0;
|
||||||
try {
|
try {
|
||||||
base = unsafe.allocateMemory(cap + ps);
|
base = unsafe.allocateMemory(size);
|
||||||
} catch (OutOfMemoryError x) {
|
} catch (OutOfMemoryError x) {
|
||||||
Bits.unreserveMemory(cap);
|
Bits.unreserveMemory(size, cap);
|
||||||
throw x;
|
throw x;
|
||||||
}
|
}
|
||||||
unsafe.setMemory(base, cap + ps, (byte) 0);
|
unsafe.setMemory(base, size, (byte) 0);
|
||||||
if (base % ps != 0) {
|
if (base % ps != 0) {
|
||||||
// Round up to page boundary
|
// Round up to page boundary
|
||||||
address = base + ps - (base & (ps - 1));
|
address = base + ps - (base & (ps - 1));
|
||||||
} else {
|
} else {
|
||||||
address = base;
|
address = base;
|
||||||
}
|
}
|
||||||
cleaner = Cleaner.create(this, new Deallocator(base, cap));
|
cleaner = Cleaner.create(this, new Deallocator(base, size, cap));
|
||||||
#else[rw]
|
#else[rw]
|
||||||
super(cap);
|
super(cap);
|
||||||
#end[rw]
|
#end[rw]
|
||||||
|
|
32
jdk/src/share/classes/sun/misc/JavaNioAccess.java
Normal file
32
jdk/src/share/classes/sun/misc/JavaNioAccess.java
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2007-2008 Sun Microsystems, Inc. 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. Sun designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Sun in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||||
|
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||||
|
* have any questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package sun.misc;
|
||||||
|
|
||||||
|
import java.nio.BufferPoolMXBean;
|
||||||
|
|
||||||
|
public interface JavaNioAccess {
|
||||||
|
BufferPoolMXBean getDirectBufferPoolMXBean();
|
||||||
|
}
|
|
@ -46,6 +46,7 @@ public class SharedSecrets {
|
||||||
private static JavaIOAccess javaIOAccess;
|
private static JavaIOAccess javaIOAccess;
|
||||||
private static JavaIODeleteOnExitAccess javaIODeleteOnExitAccess;
|
private static JavaIODeleteOnExitAccess javaIODeleteOnExitAccess;
|
||||||
private static JavaNetAccess javaNetAccess;
|
private static JavaNetAccess javaNetAccess;
|
||||||
|
private static JavaNioAccess javaNioAccess;
|
||||||
private static JavaIOFileDescriptorAccess javaIOFileDescriptorAccess;
|
private static JavaIOFileDescriptorAccess javaIOFileDescriptorAccess;
|
||||||
|
|
||||||
public static JavaUtilJarAccess javaUtilJarAccess() {
|
public static JavaUtilJarAccess javaUtilJarAccess() {
|
||||||
|
@ -77,6 +78,20 @@ public class SharedSecrets {
|
||||||
return javaNetAccess;
|
return javaNetAccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void setJavaNioAccess(JavaNioAccess jna) {
|
||||||
|
javaNioAccess = jna;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static JavaNioAccess getJavaNioAccess() {
|
||||||
|
if (javaNioAccess == null) {
|
||||||
|
// Ensure java.nio.ByteOrder is initialized; we know that
|
||||||
|
// this class initializes java.nio.Bits that provides the
|
||||||
|
// shared secret.
|
||||||
|
unsafe.ensureClassInitialized(java.nio.ByteOrder.class);
|
||||||
|
}
|
||||||
|
return javaNioAccess;
|
||||||
|
}
|
||||||
|
|
||||||
public static void setJavaIOAccess(JavaIOAccess jia) {
|
public static void setJavaIOAccess(JavaIOAccess jia) {
|
||||||
javaIOAccess = jia;
|
javaIOAccess = jia;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,7 @@ import java.io.RandomAccessFile;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.MappedByteBuffer;
|
import java.nio.MappedByteBuffer;
|
||||||
|
import java.nio.BufferPoolMXBean;
|
||||||
import java.nio.channels.*;
|
import java.nio.channels.*;
|
||||||
import java.nio.channels.spi.*;
|
import java.nio.channels.spi.*;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -43,10 +44,12 @@ import java.lang.ref.ReferenceQueue;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.security.AccessController;
|
import java.security.AccessController;
|
||||||
import java.security.PrivilegedAction;
|
import java.security.PrivilegedAction;
|
||||||
|
import javax.management.ObjectName;
|
||||||
|
import javax.management.MalformedObjectNameException;
|
||||||
|
|
||||||
import sun.misc.Cleaner;
|
import sun.misc.Cleaner;
|
||||||
import sun.security.action.GetPropertyAction;
|
import sun.security.action.GetPropertyAction;
|
||||||
|
|
||||||
|
|
||||||
public class FileChannelImpl
|
public class FileChannelImpl
|
||||||
extends FileChannel
|
extends FileChannel
|
||||||
{
|
{
|
||||||
|
@ -681,14 +684,26 @@ public class FileChannelImpl
|
||||||
private static class Unmapper
|
private static class Unmapper
|
||||||
implements Runnable
|
implements Runnable
|
||||||
{
|
{
|
||||||
|
// keep track of mapped buffer usage
|
||||||
|
static volatile int count;
|
||||||
|
static volatile long totalSize;
|
||||||
|
static volatile long totalCapacity;
|
||||||
|
|
||||||
private long address;
|
private long address;
|
||||||
private long size;
|
private long size;
|
||||||
|
private int cap;
|
||||||
|
|
||||||
private Unmapper(long address, long size) {
|
private Unmapper(long address, long size, int cap) {
|
||||||
assert (address != 0);
|
assert (address != 0);
|
||||||
this.address = address;
|
this.address = address;
|
||||||
this.size = size;
|
this.size = size;
|
||||||
|
this.cap = cap;
|
||||||
|
|
||||||
|
synchronized (Unmapper.class) {
|
||||||
|
count++;
|
||||||
|
totalSize += size;
|
||||||
|
totalCapacity += cap;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void run() {
|
public void run() {
|
||||||
|
@ -696,8 +711,13 @@ public class FileChannelImpl
|
||||||
return;
|
return;
|
||||||
unmap0(address, size);
|
unmap0(address, size);
|
||||||
address = 0;
|
address = 0;
|
||||||
}
|
|
||||||
|
|
||||||
|
synchronized (Unmapper.class) {
|
||||||
|
count--;
|
||||||
|
totalSize -= size;
|
||||||
|
totalCapacity -= cap;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void unmap(MappedByteBuffer bb) {
|
private static void unmap(MappedByteBuffer bb) {
|
||||||
|
@ -786,7 +806,7 @@ public class FileChannelImpl
|
||||||
assert (IOStatus.checkAll(addr));
|
assert (IOStatus.checkAll(addr));
|
||||||
assert (addr % allocationGranularity == 0);
|
assert (addr % allocationGranularity == 0);
|
||||||
int isize = (int)size;
|
int isize = (int)size;
|
||||||
Unmapper um = new Unmapper(addr, size + pagePosition);
|
Unmapper um = new Unmapper(addr, size + pagePosition, isize);
|
||||||
if ((!writable) || (imode == MAP_RO))
|
if ((!writable) || (imode == MAP_RO))
|
||||||
return Util.newMappedByteBufferR(isize, addr + pagePosition, um);
|
return Util.newMappedByteBufferR(isize, addr + pagePosition, um);
|
||||||
else
|
else
|
||||||
|
@ -797,6 +817,49 @@ public class FileChannelImpl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the management interface for mapped buffers
|
||||||
|
*/
|
||||||
|
public static BufferPoolMXBean getMappedBufferPoolMXBean() {
|
||||||
|
return LazyInitialization.mappedBufferPoolMXBean;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lazy initialization of management interface
|
||||||
|
private static class LazyInitialization {
|
||||||
|
static final BufferPoolMXBean mappedBufferPoolMXBean = mappedBufferPoolMXBean();
|
||||||
|
|
||||||
|
private static BufferPoolMXBean mappedBufferPoolMXBean() {
|
||||||
|
final String pool = "mapped";
|
||||||
|
final ObjectName obj;
|
||||||
|
try {
|
||||||
|
obj = new ObjectName("java.nio:type=BufferPool,name=" + pool);
|
||||||
|
} catch (MalformedObjectNameException x) {
|
||||||
|
throw new AssertionError(x);
|
||||||
|
}
|
||||||
|
return new BufferPoolMXBean() {
|
||||||
|
@Override
|
||||||
|
public ObjectName getObjectName() {
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return pool;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public long getCount() {
|
||||||
|
return Unmapper.count;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public long getTotalCapacity() {
|
||||||
|
return Unmapper.totalCapacity;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public long getMemoryUsed() {
|
||||||
|
return Unmapper.totalSize;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// -- Locks --
|
// -- Locks --
|
||||||
|
|
||||||
|
|
106
jdk/test/java/nio/BufferPoolMXBean/Basic.java
Normal file
106
jdk/test/java/nio/BufferPoolMXBean/Basic.java
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2007-2008 Sun Microsystems, Inc. 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.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||||
|
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||||
|
* have any questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* @test
|
||||||
|
* @bug 6606598
|
||||||
|
* @summary Unit test for java.nio.BufferPoolMXBean
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.MappedByteBuffer;
|
||||||
|
import java.nio.BufferPoolMXBean;
|
||||||
|
import java.nio.channels.FileChannel;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.RandomAccessFile;
|
||||||
|
import java.lang.management.ManagementFactory;
|
||||||
|
import javax.management.MBeanServer;
|
||||||
|
import javax.management.ObjectName;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class Basic {
|
||||||
|
|
||||||
|
// static fields to ensure buffers aren't GC'ed
|
||||||
|
static List<ByteBuffer> buffers;
|
||||||
|
static MappedByteBuffer mbb;
|
||||||
|
|
||||||
|
// check counters
|
||||||
|
static void check(List<BufferPoolMXBean> pools,
|
||||||
|
int minBufferCount,
|
||||||
|
long minTotalCapacity)
|
||||||
|
{
|
||||||
|
int bufferCount = 0;
|
||||||
|
long totalCap = 0;
|
||||||
|
long totalMem = 0;
|
||||||
|
for (BufferPoolMXBean pool: pools) {
|
||||||
|
bufferCount += pool.getCount();
|
||||||
|
totalCap += pool.getTotalCapacity();
|
||||||
|
totalMem += pool.getMemoryUsed();
|
||||||
|
}
|
||||||
|
if (bufferCount < minBufferCount)
|
||||||
|
throw new RuntimeException("Count less than expected");
|
||||||
|
if (totalMem < minTotalCapacity)
|
||||||
|
throw new RuntimeException("Memory usage less than expected");
|
||||||
|
if (totalCap < minTotalCapacity)
|
||||||
|
throw new RuntimeException("Total capacity less than expected");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
Random rand = new Random();
|
||||||
|
|
||||||
|
// allocate a few direct buffers
|
||||||
|
int bufferCount = 5 + rand.nextInt(20);
|
||||||
|
buffers = new ArrayList<ByteBuffer>(bufferCount);
|
||||||
|
long totalCapacity = 0L;
|
||||||
|
for (int i=0; i<bufferCount; i++) {
|
||||||
|
int cap = 1024 + rand.nextInt(4096);
|
||||||
|
buffers.add( ByteBuffer.allocateDirect(cap) );
|
||||||
|
totalCapacity += cap;
|
||||||
|
}
|
||||||
|
|
||||||
|
// map a file
|
||||||
|
File f = File.createTempFile("blah", null);
|
||||||
|
f.deleteOnExit();
|
||||||
|
RandomAccessFile raf = new RandomAccessFile(f, "rw");
|
||||||
|
FileChannel fc = raf.getChannel();
|
||||||
|
mbb = fc.map(FileChannel.MapMode.READ_WRITE, 10, 100);
|
||||||
|
bufferCount++;
|
||||||
|
totalCapacity += mbb.capacity();
|
||||||
|
|
||||||
|
// direct
|
||||||
|
List<BufferPoolMXBean> pools =
|
||||||
|
ManagementFactory.getPlatformMXBeans(BufferPoolMXBean.class);
|
||||||
|
check(pools, bufferCount, totalCapacity);
|
||||||
|
|
||||||
|
// using MBeanServer
|
||||||
|
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
|
||||||
|
Set<ObjectName> mbeans = server.queryNames(
|
||||||
|
new ObjectName("java.nio:type=BufferPool,*"), null);
|
||||||
|
pools = new ArrayList<BufferPoolMXBean>();
|
||||||
|
for (ObjectName name: mbeans) {
|
||||||
|
BufferPoolMXBean pool = ManagementFactory
|
||||||
|
.newPlatformMXBeanProxy(server, name.toString(), BufferPoolMXBean.class);
|
||||||
|
pools.add(pool);
|
||||||
|
}
|
||||||
|
check(pools, bufferCount, totalCapacity);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue