zoukankan      html  css  js  c++  java
  • 7 直接内存

    7 直接内存

    7.1 定义和介绍

    直接内存属于系统内存,并不属于jvm。属于操作系统内存管理。

    • 常见于BIO操作时,用于数据缓冲区

    • 分配回收成本较高,但读写性能高

    • 不受JVM内存回收管理

    使用传统的io和使用直接内存读取一个800M大小的文件对比

    思考:为什么使用直接内存,我们大文件的读写效率会这么高?

    先了解文件读写过程,java要调用操作系统提供函数才能读写。那么cpu的状态会从用户态变为内核态。当切换到内核态的时候,由cpu的函数去读取磁盘文件内容。他会在操作系统内存中划出一块系统缓冲区,磁盘的内容会先读到这个系统缓冲区。不肯把800M的东西直接读到内存,那内存会顶不住。利用缓冲区分次读取。注意系统缓冲器java不能读取,所以java在堆区划分一块java缓冲区,要想读取到数据,就把数据从系统缓冲区读到java缓冲区。之后cpu进入用户态,去调用输出流的写入操作,反复读写把文件复制。

    现在发现了问题:有2块缓冲区,那读取的时候数据会存两份。这样造成不必要的数据复制,效率低。

    如果使用直接内存:当我们调用allocateDirect(_1Mb),分配一块直接内存,代表着我会 在操作系统划出一块直接内存区,这块内存系统可以直接用,java代码也可以直接用,是共享的。比刚才的少一次缓冲区复制操作 ,效率提高。

     

    7.2 内存溢出

    因为不会被JVM管理,GC也回收不到这块内存。那会存在直接内存溢出的情况。

    7.3 内存释放原理

    直接内存在底层的分配和释放是通过unsafe管理的,一般jdk内部人员用到unsafe,我们用不着。image-20210919113749745

    那么bytebuffer如何和unsafe关联起来的呢?

    后台有一个线程监控着,虚引用机制,如果没人用直接内存了,那就主动执行任务去释放直接内存。

     

    7.4 禁用显示回收对直接内存的影响

    我们在JVM调优的时候,通常会加这句,让我们GC不工作

     -XX:+DisableExplicitGC

    System.GC()他不仅会回收新生代,还会回收老年代,造成程序暂停的时间比较长。为了防止一些程序员不小心写system.GC()触发垃圾回收影响性能。

    一旦禁用system.GC()以后啊,那我们bytebuffer关联的直接内存也不会被释放掉。造成直接内存长时间占用。那怎么办呢?

    可以用unsafe对象去调用freeMemory去释放直接内存

    手动管理这块直接内存

  • 相关阅读:
    timeouts _ golang
    select.go
    channel directions _ golang
    channel synchronization _ golang
    channel _ buffering
    servlet:共享资源造成的线程冲突
    java:多线程的 共享资源冲突问题
    jsp:通过过滤器进行网页的资源管理
    jsp:通过Session控制登陆时间和内部页面的访问
    java:数据结构
  • 原文地址:https://www.cnblogs.com/YXBLOGXYY/p/15396659.html
Copyright © 2011-2022 走看看