美文网首页JVM专题
JVM专题 1:java直接内存DirectByteBuffer

JVM专题 1:java直接内存DirectByteBuffer

作者: 北交吴志炜 | 来源:发表于2018-12-20 14:37 被阅读0次

    先上test代码

    public class DirectMemoryTest {
    
    public static void main(String[] args) {
    
    ByteBuffer buffer =null;
    
    try {
    
    long startTime=System.currentTimeMillis();
    
    for(int i=0;i<100;i++){
    
    buffer = ByteBuffer.allocateDirect(1024 *1024 *250);
    
    //clean(buffer);
    
                }
    
    long endTime=System.currentTimeMillis();
    
    System.out.println("程序运行时间: "+(endTime-startTime)+"ms");
    
    //System.out.println(null+"");
    
            }catch (Exception e) {
    
    e.printStackTrace();
    
    }
    
    }
    
    public static void clean(final ByteBuffer byteBuffer) {
    
    if (byteBuffer.isDirect()) {
    
    ((DirectBuffer)byteBuffer).cleaner().clean();
    
    }
    
    }
    
    }
    

    运行使用的jvm参数 打印gc日志,直接内存设置最大1G

    -XX:+PrintGCDetails -XX:+UseConcMarkSweepGC  -XX:MaxDirectMemorySize=1024M
    

    不调用clean()方法的时候,会频繁的发生由于system.gc()造成的full gc,此时老年代并未使用很多

    [Full GC (System.gc()) [CMS: 0K->657K(87424K), 0.0104483 secs] 2801K->657K(126720K), [Metaspace: 3390K->3390K(1056768K)], 0.0105395 secs] [Times: user=0.00 sys=0.02, real=0.01 secs] 
    [Full GC (System.gc()) [CMS: 657K->652K(87424K), 0.0054286 secs] 658K->652K(126848K), [Metaspace: 3391K->3391K(1056768K)], 0.0055050 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
    [Full GC (System.gc()) [CMS: 652K->652K(87424K), 0.0048721 secs] 1354K->652K(126848K), [Metaspace: 3391K->3391K(1056768K)], 0.0049353 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
    [Full GC (System.gc()) [CMS: 652K->652K(87424K), 0.0055415 secs] 652K->652K(126848K), [Metaspace: 3391K->3391K(1056768K)], 0.0056139 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
    
    

    当调用了clean()方法的时候,却不会发生任何一次fullGC

    这是为什么呢?继续上代码,DirectByteBuffer初始化的时候,内部会显示调用System.gc();


    image.png
    image.png

    关键就在这里,显示调用System.gc(),当jvm发现直接内存MaxDirectMemorySize=1024M所剩无几的时候,就会触发fullGC。
    现在大概是1G直接内存,每次申请250M,可以发现3个循环之后会触发一次fullgc.如果每次申请的大小继续增大,比如400
    m,可以发现2个循环之后就会fullgc。

    这也就解释了,为什么当调用了clean()方法的时候,却不会发生任何一次fullGC,因为每一次都会手动的释放内存,jvm即使接到

    System.gc()命令,但是认为没必要进行gc,就不会触发。

    解决:1.手动释放 ((DirectBuffer)byteBuffer).cleaner().clean()
    2.禁用System.gc(),参数 -XX:-+DisableExplicitGC 有可能会导致,直接内存得不到回收,发生OOM(此时,只有发生堆内存回收的时候,才会顺带的回收直接内存)

    相关文章

      网友评论

        本文标题:JVM专题 1:java直接内存DirectByteBuffer

        本文链接:https://www.haomeiwen.com/subject/dhuykqtx.html