This is the 13th day of my participation in the Gwen Challenge in November. Check out the details: The last Gwen Challenge in 2021″

Out of memory

Although Direct Memory is not managed by the JVM, it can still run out of Memory.

The sample

    static int ONE_HUNDRED_GB = 1024 * 1024 * 1024;

    public static void main(String[] args){
        List<ByteBuffer> byteBufferList = new ArrayList<>();
        Integer num = 0;
        try{
            while (true) {// The size of the direct memory allocated each time
                ByteBuffer bBuf = ByteBuffer.allocateDirect(ONE_HUNDRED_GB);
                byteBufferList.add(bBuf);
                num++;
                // Let the thread sleep at a time because it is too fastThread.sleep(2000l); }}catch (Exception e){
            e.printStackTrace();
        } finally{ System.out.println(num); }}Copy the code

Run this code will be quoted above: Java lang. OutOfMemoryError: Direct buffer memory errors, tip directly out of memory.

This is a direct memory overflow after three runs

Native memory before run

Runtime native memory

conclusion

Although direct memory is not allocated and managed by our JVM, it can still run out of memory.

As can be seen from pre-run memory and runtime memory, direct memory does not take up all the memory of our computer system, and when it reaches a certain size, it throws out of memory information.

Release the principle

The allocation and deallocation of direct memory is primarily governed by an object called Unsafe. Allocation is made using the native method allocateMemory() provided in this object, and ultimately in Java programs by calling allocateMemory() in the Unsafe object for direct memory allocation. A reclaim free is a reclaim free of direct memory using a native method in this object that provides freeMemory().

Mainly embodied in the ByteBuffer. AllocateDirect source code, the first point into the source code.

Enter the new DirectByteBuffer(Capacity) method to view the source code.

Unsafe.allocatememory (size) allocates memory directly via unsafe.allocatememory (size). This method is native. The implementation of this method is implemented by other languages, but we know that direct memory is eventually allocated through this method.

This code does not directly see the Deallocator method. If we go to new Deallocator(Base, size, cap), we will find a run() method. The unsafe.freememory (address) method calls the direct memory free method;

How the run() method is executed, as shown in the previous diagram, is mainly through the Cleaner (virtual reference type), which is characterized by the cleaner.clean method being triggered when the object it is associated with is recycled by the JVM.

Here it is associated with a ByteBuffer object, which is a Java object that executes the Cleaner object’s clean method when it is garbage collected.

Look at the Clean method in the Cleaner object

Here the run() method is called for the direct memory deallocation.