Java内存操作知识汇总

堆缓冲和直接缓冲区、

堆内存可以使用工具VisualVM Launcher查看。

其他内存监控工具

直接缓冲区DIrect Buffers 又称堆外内存,本机内存,默认64M,可通过参数-XX:MaxDirectMemorySize指定。

public static void test() {
        ByteBuffer buf=ByteBuffer.allocateDirect(2048);
        System.out.println(buf.position());
        System.out.println(buf.limit());
        System.out.println(buf.capacity());
        System.out.println(buf.isDirect());
    }
/×
0
2048
2048
true

×/
ByteBuffer分配直接内存

 运行jar包时,添加-XX:+PrintGCDetails可打印GC信息。其他参数信息

堆外内存的释放

系统释放

Direct ByteBuffer 对象本身放在堆中,占用很小内存,关联对外内存。堆外内存使用过多,可能导致OutOfMemory错误。

 Direct ByteBuffer要full gc才能回收,所以如果堆内存用得少,堆外内存用得多,这样不触发full gc会导致堆外内存out of memory。

 ByteBuffer被GC,关联的对外内存也会被释放。当新生代满了,就会发生young gc;如果此时对象还没失效,就不会被回收;撑过几次young gc后,对象被迁移到老生代;当老生代也满了,就会发生full gc。

主动释放

使用sun.misc.Cleaner中的clean方法,参考文章

import java.nio.ByteBuffer;
import sun.nio.ch.DirectBuffer;
 
public class DirectByteBufferCleaner {
 
        public static void clean(final ByteBuffer byteBuffer) {
              if (byteBuffer.isDirect()) {
                 ((DirectBuffer)byteBuffer).cleaner().clean();
              }
        }
}

public static void sleep(long i) {
    try {
          Thread.sleep(i);
     }catch(Exception e) {
          /*skip*/
     }
}
public static void main(String []args) throws Exception {
       ByteBuffer buffer = ByteBuffer.allocateDirect(1024 * 1024 * 100);
       System.out.println("start");
       sleep(10000);
       clean(buffer);
       System.out.println("end");
       sleep(10000);
}
cleaner释放对外内存

本例中申请100M堆外内存,10s后释放。

该博客有很多关于JVM的知识。

 该文章 对内存分配介绍

原文地址:https://www.cnblogs.com/legion/p/8759475.html