序
本文主要研究一下openjdk的BufferPoolMXBean
PlatformManagedObject
java.management/java/lang/management/PlatformManagedObject.java
public interface PlatformManagedObject {
/**
* Returns an {@link ObjectName ObjectName} instance representing
* the object name of this platform managed object.
*
* @return an {@link ObjectName ObjectName} instance representing
* the object name of this platform managed object.
*/
public ObjectName getObjectName();
}
PlatformManagedObject接口定义了getObjectName方法用于返回ObjectName
BufferPoolMXBean
java.management/java/lang/management/BufferPoolMXBean.java
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();
}
- BufferPoolMXBean接口继承了PlatformManagedObject,它定义了getName、getCount、getTotalCapacity、getMemoryUsed方法
ManagementFactoryHelper
java.management/sun/management/ManagementFactoryHelper.java
public class ManagementFactoryHelper {
static {
// make sure that the management lib is loaded within
// java.lang.management.ManagementFactory
jdk.internal.misc.Unsafe.getUnsafe().ensureClassInitialized(ManagementFactory.class);
}
private static final VMManagement jvm = new VMManagementImpl();
private ManagementFactoryHelper() {};
public static VMManagement getVMManagement() {
return jvm;
}
static final String LOGGING_MXBEAN_NAME = "java.util.logging:type=Logging";
private static ClassLoadingImpl classMBean = null;
private static MemoryImpl memoryMBean = null;
private static ThreadImpl threadMBean = null;
private static RuntimeImpl runtimeMBean = null;
private static CompilationImpl compileMBean = null;
private static BaseOperatingSystemImpl osMBean = null;
//......
private static List<BufferPoolMXBean> bufferPools = null;
public static synchronized List<BufferPoolMXBean> getBufferPoolMXBeans() {
if (bufferPools == null) {
bufferPools = new ArrayList<>(2);
bufferPools.add(createBufferPoolMXBean(SharedSecrets.getJavaNioAccess()
.getDirectBufferPool()));
bufferPools.add(createBufferPoolMXBean(sun.nio.ch.FileChannelImpl
.getMappedBufferPool()));
}
return bufferPools;
}
private static BufferPoolMXBean
createBufferPoolMXBean(final JavaNioAccess.BufferPool pool)
{
return new BufferPoolMXBean() {
private volatile ObjectName objname; // created lazily
@Override
public ObjectName getObjectName() {
ObjectName result = objname;
if (result == null) {
synchronized (this) {
result = objname;
if (result == null) {
result = Util.newObjectName(BUFFER_POOL_MXBEAN_NAME +
",name=" + pool.getName());
objname = result;
}
}
}
return result;
}
@Override
public String getName() {
return pool.getName();
}
@Override
public long getCount() {
return pool.getCount();
}
@Override
public long getTotalCapacity() {
return pool.getTotalCapacity();
}
@Override
public long getMemoryUsed() {
return pool.getMemoryUsed();
}
};
}
//......
}
- ManagementFactoryHelper的getBufferPoolMXBeans方法会通过createBufferPoolMXBean方法创建两个BufferPoolMXBean,然后添加到bufferPools
- 其中一个是DirectBufferPool,一个是MappedBufferPool;他们分别使用SharedSecrets.getJavaNioAccess().getDirectBufferPool()以及sun.nio.ch.FileChannelImpl.getMappedBufferPool()来创建
- createBufferPoolMXBean方法使用匿名类创建了BufferPoolMXBean的实现;createBufferPoolMXBean方法接收JavaNioAccess.BufferPool参数,其getCount、getTotalCapacity、getMemoryUsed等均是直接使用pool的相关方法
JavaNioAccess.BufferPool
java.base/jdk/internal/access/JavaNioAccess.java
public interface JavaNioAccess {
/**
* Provides access to information on buffer usage.
*/
interface BufferPool {
String getName();
long getCount();
long getTotalCapacity();
long getMemoryUsed();
}
BufferPool getDirectBufferPool();
}
- JavaNioAccess里头定义了BufferPool接口,它定义了getName、getCount、getTotalCapacity、getMemoryUsed方法;除此之外JavaNioAccess还定义了getDirectBufferPool方法用于返回BufferPool
SharedSecrets
java.base/jdk/internal/access/SharedSecrets.java
public class SharedSecrets {
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static JavaUtilJarAccess javaUtilJarAccess;
private static JavaLangAccess javaLangAccess;
private static JavaLangModuleAccess javaLangModuleAccess;
private static JavaLangInvokeAccess javaLangInvokeAccess;
private static JavaLangRefAccess javaLangRefAccess;
private static JavaIOAccess javaIOAccess;
private static JavaNetInetAddressAccess javaNetInetAddressAccess;
private static JavaNetHttpCookieAccess javaNetHttpCookieAccess;
private static JavaNetSocketAccess javaNetSocketAccess;
private static JavaNetUriAccess javaNetUriAccess;
private static JavaNetURLAccess javaNetURLAccess;
private static JavaNetURLClassLoaderAccess javaNetURLClassLoaderAccess;
private static JavaNioAccess javaNioAccess;
private static JavaIOFileDescriptorAccess javaIOFileDescriptorAccess;
private static JavaIOFilePermissionAccess javaIOFilePermissionAccess;
private static JavaSecurityAccess javaSecurityAccess;
private static JavaUtilZipFileAccess javaUtilZipFileAccess;
private static JavaUtilResourceBundleAccess javaUtilResourceBundleAccess;
private static JavaAWTAccess javaAWTAccess;
private static JavaAWTFontAccess javaAWTFontAccess;
private static JavaBeansAccess javaBeansAccess;
private static JavaObjectInputStreamAccess javaObjectInputStreamAccess;
private static JavaObjectInputFilterAccess javaObjectInputFilterAccess;
private static JavaIORandomAccessFileAccess javaIORandomAccessFileAccess;
private static JavaxCryptoSealedObjectAccess javaxCryptoSealedObjectAccess;
//......
public static void setJavaNioAccess(JavaNioAccess jna) {
javaNioAccess = jna;
}
public static JavaNioAccess getJavaNioAccess() {
if (javaNioAccess == null) {
// Ensure java.nio.Buffer is initialized, which provides the
// shared secret.
unsafe.ensureClassInitialized(java.nio.Buffer.class);
}
return javaNioAccess;
}
//......
}
- SharedSecrets提供了JavaNioAccess的getter及setter
Buffer
java.base/java/nio/Buffer.java
public abstract class Buffer {
// Cached unsafe-access object
static final Unsafe UNSAFE = Unsafe.getUnsafe();
/**
* The characteristics of Spliterators that traverse and split elements
* maintained in Buffers.
*/
static final int SPLITERATOR_CHARACTERISTICS =
Spliterator.SIZED | Spliterator.SUBSIZED | Spliterator.ORDERED;
// Invariants: mark <= position <= limit <= capacity
private int mark = -1;
private int position = 0;
private int limit;
private int capacity;
// Used by heap byte buffers or direct buffers with Unsafe access
// For heap byte buffers this field will be the address relative to the
// array base address and offset into that array. The address might
// not align on a word boundary for slices, nor align at a long word
// (8 byte) boundary for byte[] allocations on 32-bit systems.
// For direct buffers it is the start address of the memory region. The
// address might not align on a word boundary for slices, nor when created
// using JNI, see NewDirectByteBuffer(void*, long).
// Should ideally be declared final
// NOTE: hoisted here for speed in JNI GetDirectBufferAddress
long address;
//......
static {
// setup access to this package in SharedSecrets
SharedSecrets.setJavaNioAccess(
new JavaNioAccess() {
@Override
public JavaNioAccess.BufferPool getDirectBufferPool() {
return Bits.BUFFER_POOL;
}
});
}
}
- 抽象类Buffer有个static代码块,里头创建了匿名JavaNioAccess,然后设置到了SharedSecrets中;其中匿名JavaNioAccess的getDirectBufferPool方法返回的是Bits.BUFFER_POOL
FileChannelImpl
java.base/sun/nio/ch/FileChannelImpl.java
public class FileChannelImpl
extends FileChannel
{
// Memory allocation size for mapping buffers
private static final long allocationGranularity;
// Access to FileDescriptor internals
private static final JavaIOFileDescriptorAccess fdAccess =
SharedSecrets.getJavaIOFileDescriptorAccess();
// Used to make native read and write calls
private final FileDispatcher nd;
// File descriptor
private final FileDescriptor fd;
//......
// -- Memory-mapped buffers --
private static 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;
private final FileDescriptor fd;
private Unmapper(long address, long size, int cap,
FileDescriptor fd)
{
assert (address != 0);
this.address = address;
this.size = size;
this.cap = cap;
this.fd = fd;
synchronized (Unmapper.class) {
count++;
totalSize += size;
totalCapacity += cap;
}
}
public void run() {
if (address == 0)
return;
unmap0(address, size);
address = 0;
// if this mapping has a valid file descriptor then we close it
if (fd.valid()) {
try {
nd.close(fd);
} catch (IOException ignore) {
// nothing we can do
}
}
synchronized (Unmapper.class) {
count--;
totalSize -= size;
totalCapacity -= cap;
}
}
}
//......
/**
* Invoked by sun.management.ManagementFactoryHelper to create the management
* interface for mapped buffers.
*/
public static JavaNioAccess.BufferPool getMappedBufferPool() {
return new JavaNioAccess.BufferPool() {
@Override
public String getName() {
return "mapped";
}
@Override
public long getCount() {
return Unmapper.count;
}
@Override
public long getTotalCapacity() {
return Unmapper.totalCapacity;
}
@Override
public long getMemoryUsed() {
return Unmapper.totalSize;
}
};
}
//......
}
FileChannelImpl定义了getMappedBufferPool方法,返回的是匿名JavaNioAccess.BufferPool,其相关返回实现直接使用Unmapper的对应方法;Unmapper实现了Runnable接口
小结
- BufferPoolMXBean接口继承了PlatformManagedObject,它定义了getName、getCount、getTotalCapacity、getMemoryUsed方法
- ManagementFactoryHelper的getBufferPoolMXBeans方法会通过createBufferPoolMXBean方法创建两个BufferPoolMXBean,然后添加到bufferPools;其中一个是DirectBufferPool,一个是MappedBufferPool;他们分别使用SharedSecrets.getJavaNioAccess().getDirectBufferPool()以及sun.nio.ch.FileChannelImpl.getMappedBufferPool()来创建
- createBufferPoolMXBean方法接收JavaNioAccess.BufferPool参数;抽象类Buffer有个static代码块,里头创建了匿名JavaNioAccess,然后设置到了SharedSecrets中;其中匿名JavaNioAccess的getDirectBufferPool方法返回的是Bits.BUFFER_POOL;FileChannelImpl定义了getMappedBufferPool方法,返回的是匿名JavaNioAccess.BufferPool,其相关返回实现直接使用Unmapper的对应方法;Unmapper实现了Runnable接口
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。