栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

JVM【day5】

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

JVM【day5】

内存结构 直接内存

定义:操作系统内存,常见于NIO操作时,用于数据缓冲区,分配回收成本较高,但读写性能高,不受JVM内存回收管理

用以下代码来演示ByteBuffer和IO读写性能差别:

public class Demo_9 {
    static final String From="C:\Test_buff\学习雷锋.qlv";
    static final String To="D:\学习雷锋.qlv";
    static final int _1MB=1024*1024;
    public static void main(String[] args) {
        io();
        directBuffer();
    }
    private static void directBuffer(){
        long start=System.nanoTime();
        try(FileChannel from=new FileInputStream(From).getChannel();
            FileChannel to=new FileOutputStream(To).getChannel();
        ){
            ByteBuffer bb=ByteBuffer.allocateDirect(_1MB);//在系统内存和java堆内存划分出一块共用区域(direct memory)
            while (true){
                int len=from.read(bb);
                if(len==-1){
                    break;
                }
                bb.flip();
                to.write(bb);
                bb.clear();
            }
        }
        catch (IOException e){
            e.printStackTrace();
        }
        long end=System.nanoTime();
        System.out.println("directBuffer用时:"+(end-start)/1000_000.0);
    }
    private static void io(){
        long start=System.nanoTime();
        try(FileInputStream from=new FileInputStream(From);
            FileOutputStream to=new FileOutputStream(To);
        ){
            byte[] buf = new byte[_1MB];
            while (true){
                int len=from.read(buf);
                if(len==-1){
                    break;
                }
                to.write(buf,0,len);
            }
        }
        catch (IOException e){
            e.printStackTrace();
        }
        long end=System.nanoTime();
        System.out.println("io用时:"+(end-start)/1000_000.0);
    }
}

运行结果如下:

这里演示用的文件比较小,文件大一点,差别就可以很明显的体现处来

为什么使用Bytebuffer后,大文件的读写效率变高?
IO文件读写过程如图:

因为经过了两个缓存区(java缓存区和系统缓存区),所以造成不必要的数据复制
使用直接缓存区的过程如下图:

直接内存溢出

直接内存溢出在java中所报的错误信息:java.lang.OutOfMemoryError: Direct buffer memory
用以下代码进行测试(jdk版本1.8)

public class Demo_10 {
    static int _100MB=1024*1024*100;

    public static void main(String[] args) {
        List list=new ArrayList<>();
        int i=0;
        try {
            while (true){
                ByteBuffer byteBuffer = ByteBuffer.allocateDirect(_100MB);
                list.add(byteBuffer);
                i++;
            }
        }finally {
            System.out.println(i);
        }
    }
}

直接内存释放原理:Unsafe类(非常底层类,不建议使用)分配直接内存:

long base=unsafe.allocateMemory();//返回分配直接内存的地址
unsafe.setMemory(base,_1GB,(byte,0));//_1GB表示大小为1GB的快捷

释放直接内存

unsafe.freeMemory(base);

通过上面的代码验证直接内存的分配和释放是通过unsafe,而不是垃圾回收
直接内存的释放是借助的虚引用对象(Cleaner),特点是:当关联的对象(DirectByteBuffer)被回收时,会触发虚引用的clean方法,当ByteBuffer对象被垃圾回收后,会触发Cleaner的clean方法,然后执行任务对象,再调用unsafe.freeMemory();

在JVM调优时,经常会加一条参数:-XX:+DisableExplicitGC,意义是禁用显示的垃圾回收,就是让代码中的System.gc()无效,因为System.gc()触发的是一次Full GC,比较影响性能,但是会影响直接内存的释放

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/736826.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号