Talk about BufferPoolMXBean of openjdk

  jdk

Order

This article mainly studies BufferPoolMXBean of openjdk.

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();
}

The PlatformManagedObject interface defines the getObjectName method for returning 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 interface inherits PlatformManagedObject, which defines getName, getCount, getTotalCapacity, getMemoryUsed methods

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();
            }
        };
    }

    //......
}
  • The getBufferPoolMXBeans method of ManagementFactoryHelper creates two BufferPoolMXBean through the createBufferPoolMXBean method and adds them to bufferPools
  • One is DirectBufferPool and the other is MappedBufferPool; . They were created using Shared Secrets. GetJavaNioAccess (). GetDirectBufferPool (), and Sun. Nio.ch. FileChannelImpl. GetMappedBufferPool (), respectively.
  • The createBufferPoolMXBean method uses anonymous classes to create the implementation of BufferPoolMXBean. CreateBufferPoolMXBean method receives Java NioAccess.BufferPool parameter, and getCount, getTotalCapacity, getMemoryUsed, etc. are related methods directly using 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();
}
  • BufferPool interface is defined in JavaNioAccess, which defines getName, getCount, getTotalCapacity, getMemoryUsed methods; In addition, JavaNioAccess also defines the getDirectBufferPool method to return 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 provides getter and setter for JavaNioAccess.

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;
                }
            });
    }

}
  • The abstract class Buffer has a static code block in which anonymous JavaNioAccess is created and then set to SharedSecrets. The getDirectBufferPool m ethod of anonymous JavaNioAccess returns 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 defines the getMappedBufferPool method, which returns anonymous JavaNioAccess.BufferPool, and its related return implements the corresponding method directly using Unmapper. Unmapper implemented Runnable interface

Summary

  • BufferPoolMXBean interface inherits PlatformManagedObject, which defines getName, getCount, getTotalCapacity, getMemoryUsed methods
  • The getBufferPoolMXBeans method of ManagementFactoryHelper creates two BufferPoolMXBean through the createBufferPoolMXBean method and then adds them to bufferPools; ; One is DirectBufferPool and the other is MappedBufferPool; . They were created using Shared Secrets. GetJavaNioAccess (). GetDirectBufferPool (), and Sun. Nio.ch. FileChannelImpl. GetMappedBufferPool (), respectively.
  • CreateBufferPoolMXBean method receives JavaNioAccess.BufferPool parameter; The abstract class Buffer has a static code block in which anonymous JavaNioAccess is created and then set to SharedSecrets. The getDirectBufferPool method of anonymous JavaNioAccess returns Bits.BUFFER_POOL; ; FileChannelImpl defines the getMappedBufferPool method, which returns anonymous JavaNioAccess.BufferPool, and its related return implements the corresponding method directly using Unmapper. Unmapper implemented Runnable interface

doc