堆缓冲和直接缓冲区、
堆内存可以使用工具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 ×/
运行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); }
本例中申请100M堆外内存,10s后释放。
该博客有很多关于JVM的知识。
该文章 对内存分配介绍