JVM Part 5 (direct memory)

Direct Memory:
Direct memory does not belong to the memory structure in the JVM. Direct memory is not managed by the JVM. Direct memory is system memory.
Direct memory

  1. Common in NIO operations, it is used for data buffer
  2. Allocation recovery cost is high, but read-write performance is high
  3. Not managed by JVM memory reclamation

During NIO operation, direct memory can be used as data buffer to improve reading and writing efficiency.
The following figure shows the use of heap memory for data buffers:

Because Java cannot directly operate on the system memory, the data line is first read from the disk file to the system memory, and then from the system memory to the Java heap memory, which is inefficient.

The following figure shows the case where direct memory is used as data buffer:

A piece of direct memory is opened up in the system as a data buffer. First, the file is read into the direct memory from the disk. java can operate the direct memory, so there is no need to read the data into the heap memory, and the efficiency is greatly improved.

Direct memory is not managed by the JVM and is managed directly by the operating system.
In Java code, the Unsafe class is used to allocate and release direct memory.

 public native void freeMemory(long var1);
 public native long allocateMemory(long var1);

Can be used in java
public abstract class ByteBuffer this class indirectly allocates and releases direct memory
Allocate direct memory through the allocateDirect method under ByteBuffer
The following is the source code

public static ByteBuffer allocateDirect(int capacity) {
	return new DirectByteBuffer(capacity);
}
DirectByteBuffer(int cap) {                   // package-private
    super(-1, 0, cap, cap);
    boolean pa = VM.isDirectMemoryPageAligned();
    int ps = Bits.pageSize();
    long size = Math.max(1L, (long)cap + (pa ? ps : 0));
    Bits.reserveMemory(size, cap);
    
    long base = 0;
    try {
         base = unsafe.allocateMemory(size)			//Complete direct memory allocation
    } catch (OutOfMemoryError x) {
        Bits.unreserveMemory(size, cap);
        throw x;
    }
    unsafe.setMemory(base, size, (byte) 0);
    if (pa && (base % ps != 0)) {
        // Round up to page boundary
        address = base + ps - (base & (ps - 1));
    } else {
        address = base;
    }
    cleaner = Cleaner.create(this, new Deallocator(base, size, cap));
    att = null;
}
private static class Deallocator
        implements Runnable
{
    private static Unsafe unsafe = Unsafe.getUnsafe();
    private long address;
    private long size;
    private int capacity;

    private Deallocator(long address, long size, int capacity) {
        assert (address != 0);
        this.address = address;
        this.size = size;
        this.capacity = capacity;
    }
    public void run() {
        if (address == 0) {
            // Paranoia
            return;
        }
        unsafe.freeMemory(address);    // Finally, the freeMemory method is executed to release the direct memory
        address = 0;
        Bits.unreserveMemory(size, capacity);
    }
}

You can see that the above code completes the allocation and release of direct memory. When direct memory is not referenced in Java, it is automatically released.
This can be achieved by displaying the GC

public static void main(String[] args) throws IOException {
    ByteBuffer byteBuffer = ByteBuffer.allocateDirect(_1Gb);
    System.out.println("Allocation complete...");
    System.in.read();
    System.out.println("Start release...");
    byteBuffer = null;
    System.gc(); // Explicit garbage collection, Full GC
    System.in.read();
}

Direct memory is allocated through ByteBuffer class, and then direct memory is not referenced. It shows that gc method is called for garbage collection and ByteBuffer memory is recycled, thus triggering the run method in Deallocator class to recycle direct memory.

System.gc(); // Explicit garbage collection, Full GC
The garbage collection displayed is Full GC, which affects the performance more. So it can also directly call the freeMemory method in the program to release the direct memory.

Tags: Java jvm

Posted on Wed, 10 Nov 2021 10:34:10 -0500 by DrTrans