武邑网站建设公司,采购网哪个平台比较好,在百度上做公司做网站,wordpress 能商用#xff08;1#xff09;直接内存_基本使用
下面我们看一下使用了ByteBuffer直接内存#xff0c;大文件的读写效率是非常的高 Java本身并不具备磁盘读写的能力#xff0c;它需要调用操作系统的函数#xff0c;需要从java的方法内部调用本地方法操作系统的方法#xff0c…1直接内存_基本使用
下面我们看一下使用了ByteBuffer直接内存大文件的读写效率是非常的高 Java本身并不具备磁盘读写的能力它需要调用操作系统的函数需要从java的方法内部调用本地方法操作系统的方法设计到了cpu的用户状态变为内核态切换到内核态以后由cpu的函数去读取磁盘文件的内容会在操作系统中划出来一份缓冲区叫做系统缓冲区磁盘内容读取到系统缓冲区用系统缓冲区分次读取内容Java这边会在堆内存中分配一个java的缓冲区从系统缓冲区间接读取到java的缓冲区然后再去调用下一个状态输出流的写入操作这样反复读写
这样有两个缓冲区先读取到系统缓冲区然后在读取到java的缓冲区这样造成了不必要的复制效率不高下面我们看使用了 当调用allocateDirect方法的时候会分配一块直接内存这个方法调用以后会在操作系统那边划分一块缓冲区direct memory 这个区java代码是可以直接读取这个区的可以直接访问是系统可以访问java代码也可以访问是两个共享的一个区域叫做直接内存
磁盘文件可以读取到直接内存java代码可以直接访问直接内存比上面少了一次缓冲区的复制操作速度得到了成倍提升
它适合做这个文件的io操作
2直接内存_内存溢出 循环分配占用内存 爆了直接内存溢出 3直接内存_释放原理
直接内存不受我们虚拟机管理那么它分配的内存会不会正确回收底层是怎么实现的 不用java工具去检测了因为java工具只能看到java管理的堆堆内存直接内存不受java管理我们通过系统的任务管理器java进程对内存的占用 运行代码多了一个进程 进行释放把ByteBuffte设为空ByteBuffte的回收会不会把直接内存占用的内存回收掉呢看左侧那个java进程也没有了 System.gc() 垃圾回收怎么会导致直接内存回收的呢不是上面说不受jvm垃圾回收的管理吗
ByteBuffer底层的分配和释放内存的相关的类型是java中的非常底层的类unfafe 程序运行分配一个1g的内存 回车释放内存 这样我们就验证了直接内存的分配和释放是通过一个Unsafe对象来管理的并不是垃圾回收垃圾回收只能释放java的内存垃圾回收只能对java中无用的对象释放是自动的不需要手动来调用任何方法直接内存不同他需要主动来调用unsafe.freeMemory的方法才能完成对内存的释放
4ByteBuffer原码 进去这个方法发现它的构造器直接调用的上面我们学的unsafe对象 Cleaner对象关联Deallocator回调任务对象主动释放直接内训 Cleaner是一个特殊的类型叫做虚引用类型它的特点是它所关联的对象被回收时Cleaner会触发它的一个clean方法他关联的是this就是ByteBuffer 当ByteBuffer这个java对虚拟机回收时触发clean方法这个clean方法会触发任务对象的run方法
clean这个方法不是在主线程中执行的是在后台一个叫referenceHandler的线程专门检测虚引用对象当虚引用对象关联的DirectByteBuffer被回收掉以后会调用虚引用对象里面的clean方法然后去执行任务对象中的run方法去调用freeMemory方法区释放内存
所以我们直接内存的释放是借助了java中虚引用的机制 5直接内存_禁用显示回收对直接内存的影响 有一个问题
Full GC不仅要回收新生代还要回收老年代
-XX:DisableExplicitGC:禁用显示的垃圾回收 让System.gc无效 加上那个设置参数后可能会影响直接内存的回收
加了禁用参数后虽然写了但是System.gc是无效的不会触发java的垃圾回收ByteBuffer由于内存充裕这个对象就不会呗回收它所对应的那块直接内存也没有被回收
ByteBuffer只能等到真正的垃圾回收时它对应的那块直接内存才能被释放掉就会导致直接内存占用较大长长得不到释放 怎么解决呢可以直接使用Unsafe对象手动的直接管理