java nio pool_聊聊openjdk的BufferPoolMXBean

本文主要研究一下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 bufferPools = null;

public static synchronized List 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接口

doc

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值