0
点赞
收藏
分享

微信扫一扫

JVM专题 1:java直接内存DirectByteBuffer与垃圾回收

三次方 2021-09-25 阅读 48

先上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();




关键就在这里,显示调用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(此时,只有发生堆内存回收的时候,才会顺带的回收直接内存)

举报

相关推荐

0 条评论