Deprecated: imwpcache\f884414bce24ee67f\f73723ec7b1919fa5::__construct(): Implicitly marking parameter $YECBGYFECGEAFWHA as nullable is deprecated, the explicit nullable type must be used instead in /www/wwwroot/www.chuangxiangniao.com/wp-content/plugins/imwpcache-dist/build/f884414bce24ee67ff73723ec7b1919fa5.php on line 2

Deprecated: imwpcache\f884414bce24ee67f\f73723ec7b1919fa5::__construct(): Implicitly marking parameter $BBWFDDBHHYHDXXAB as nullable is deprecated, the explicit nullable type must be used instead in /www/wwwroot/www.chuangxiangniao.com/wp-content/plugins/imwpcache-dist/build/f884414bce24ee67ff73723ec7b1919fa5.php on line 2
JVM内存与垃圾回收篇第11章直接内存_创想鸟

JVM内存与垃圾回收篇第11章直接内存

第 11 章 直接内存

1、直接内存概述

直接内存不属于虚拟机运行时数据区的一部分,也不是《java虚拟机规范》中定义的内存区域。它是java堆外的、直接向系统申请的内存区间。直接内存来源于nio,通过存在堆中的directbytebuffer操作native内存。通常,访问直接内存的速度会优于java堆。因此,出于性能考虑,读写频繁的场合可能会考虑使用直接内存。java的nio库允许java程序使用直接内存,用于数据缓冲区。

/**  * IO                  NIO (New IO / Non-Blocking IO)  * byte[] / char[]     Buffer  * Stream              Channel  *  * 查看直接内存的占用与释放  * @author shkstart  shkstart@126.com  * @create 2020  0:22  */public class BufferTest {    private static final int BUFFER = 1024 * 1024 * 1024;//1GB    public static void main(String[] args){        //直接分配本地内存空间        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(BUFFER);        System.out.println("直接内存分配完毕,请求指示!");        Scanner scanner = new Scanner(System.in);        scanner.next();        System.out.println("直接内存开始释放!");        byteBuffer = null;        System.gc();        scanner.next();    }}

呐,直接占用了 1G 的本地内存

JVM内存与垃圾回收篇第11章直接内存

释放后,Java程序的内存占用明显减少

JVM内存与垃圾回收篇第11章直接内存

2、BIO 与 NIO

原来采用BIO的架构,在读写本地文件时,我们需要从用户态切换成内核态

JVM内存与垃圾回收篇第11章直接内存

NIO 直接操作物理磁盘,省去了中间商赚差价

JVM内存与垃圾回收篇第11章直接内存

测试代码:分别使用 BIO 和 NIO 复制大文件,看看用时差别

/**  * @author shkstart  shkstart@126.com  * @create 2020  0:04  */public class BufferTest1 {    private static final String TO = "F:test异界BD中字.mp4";    private static final int _100Mb = 1024 * 1024 * 100;    public static void main(String[] args) {        long sum = 0;        String src = "F:test异界BD中字.mp4";        for (int i = 0; i 

深入 ByteBuffer 源码

ByteBuffer.allocateDirect() 方法

public static ByteBuffer allocateDirect(int capacity) {    return new DirectByteBuffer(capacity);}

DirectByteBuffer 类的构造器用到了 Unsafe 类分配本地内存

DirectByteBuffer(int cap) {                   // package-private    super(-1, 0, cap, cap);    boolean pa = VM.isDirectMemoryPageAligned();    int ps = Bits.pageSize();    long size = Math.max(1L, (long)cap + (pa ? ps : 0));    Bits.reserveMemory(size, cap);    long base = 0;    try {        base = unsafe.allocateMemory(size);    } catch (OutOfMemoryError x) {        Bits.unreserveMemory(size, cap);        throw x;    }    unsafe.setMemory(base, size, (byte) 0);    if (pa && (base % ps != 0)) {        // Round up to page boundary        address = base + ps - (base & (ps - 1));    } else {        address = base;    }    cleaner = Cleaner.create(this, new Deallocator(base, size, cap));    att = null;}

3、直接内存与 OOM

直接内存也可能导致OutofMemoryError异常。由于直接内存在Java堆外,因此它的大小不会直接受限于-Xmx指定的最大堆大小,但是系统内存是有限的,Java堆和直接内存的总和依然受限于操作系统能给出的最大内存。直接内存的缺点为:分配回收成本较高,不受JVM内存回收管理。直接内存大小可以通过MaxDirectMemorySize设置。如果不指定,默认与堆的最大值-Xmx参数值一致。

代码示例 1

/**  * 本地内存的OOM:  OutOfMemoryError: Direct buffer memory  *  * @author shkstart  shkstart@126.com  * @create 2020  0:09  */public class BufferTest2 {    private static final int BUFFER = 1024 * 1024 * 20;//20MB    public static void main(String[] args) {        ArrayList list = new ArrayList();        int count = 0;        try {            while(true){                ByteBuffer byteBuffer = ByteBuffer.allocateDirect(BUFFER);                list.add(byteBuffer);                count++;                try {                    Thread.sleep(100);                } catch (InterruptedException e) {                    e.printStackTrace();                }            }        } finally {            System.out.println(count);        }    }}

本地内存持续增长,直至程序抛出异常:java.lang.OutOfMemoryError: Direct buffer memory

JVM内存与垃圾回收篇第11章直接内存

异常信息

"C:Program FilesJavajdk1.8.0_144injava" "-javaagent:C:Program FilesJetBrainsIntelliJ IDEA 2017.3.1libidea_rt.jar=1296:C:Program FilesJetBrainsIntelliJ IDEA 2017.3.1in" -Dfile.encoding=UTF-8 -classpath "C:Program FilesJavajdk1.8.0_144jrelibcharsets.jar;C:Program FilesJavajdk1.8.0_144jrelibdeploy.jar;C:Program FilesJavajdk1.8.0_144jrelibextccess-bridge-64.jar;C:Program FilesJavajdk1.8.0_144jrelibextcldrdata.jar;C:Program FilesJavajdk1.8.0_144jrelibextdnsns.jar;C:Program FilesJavajdk1.8.0_144jrelibextjaccess.jar;C:Program FilesJavajdk1.8.0_144jrelibextjfxrt.jar;C:Program FilesJavajdk1.8.0_144jrelibextlocaledata.jar;C:Program FilesJavajdk1.8.0_144jrelibextashorn.jar;C:Program FilesJavajdk1.8.0_144jrelibextsunec.jar;C:Program FilesJavajdk1.8.0_144jrelibextsunjce_provider.jar;C:Program FilesJavajdk1.8.0_144jrelibextsunmscapi.jar;C:Program FilesJavajdk1.8.0_144jrelibextsunpkcs11.jar;C:Program FilesJavajdk1.8.0_144jrelibextzipfs.jar;C:Program FilesJavajdk1.8.0_144jrelibjavaws.jar;C:Program FilesJavajdk1.8.0_144jrelibjce.jar;C:Program FilesJavajdk1.8.0_144jrelibjfr.jar;C:Program FilesJavajdk1.8.0_144jrelibjfxswt.jar;C:Program FilesJavajdk1.8.0_144jrelibjsse.jar;C:Program FilesJavajdk1.8.0_144jrelibmanagement-agent.jar;C:Program FilesJavajdk1.8.0_144jrelibplugin.jar;C:Program FilesJavajdk1.8.0_144jrelibesources.jar;C:Program FilesJavajdk1.8.0_144jrelibt.jar;C:UsersHeygoDesktopJVMDemooutproductionchapter11" com.atguigu.java.BufferTest2180Exception in thread "main" java.lang.OutOfMemoryError: Direct buffer memoryat java.nio.Bits.reserveMemory(Bits.java:694)at java.nio.DirectByteBuffer.(DirectByteBuffer.java:123)at java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:311)at com.atguigu.java.BufferTest2.main(BufferTest2.java:21)Process finished with exit code 1

代码示例 2

代码:直接通过 Unsafe 类申请本地内存

/**  * -Xmx20m -XX:MaxDirectMemorySize=10m  * @author shkstart  shkstart@126.com  * @create 2020  0:36  */public class MaxDirectMemorySizeTest {    private static final long _1MB = 1024 * 1024;    public static void main(String[] args) throws IllegalAccessException {        Field unsafeField = Unsafe.class.getDeclaredFields()[0];        unsafeField.setAccessible(true);        Unsafe unsafe = (Unsafe)unsafeField.get(null);        while(true){            unsafe.allocateMemory(_1MB);        }    }}

JVM 参数

-Xmx20m -XX:MaxDirectMemorySize=10m

抛出 OOM 异常

"C:Program FilesJavajdk1.8.0_144injava" "-javaagent:C:Program FilesJetBrainsIntelliJ IDEA 2017.3.1libidea_rt.jar=1362:C:Program FilesJetBrainsIntelliJ IDEA 2017.3.1in" -Dfile.encoding=UTF-8 -classpath "C:Program FilesJavajdk1.8.0_144jrelibcharsets.jar;C:Program FilesJavajdk1.8.0_144jrelibdeploy.jar;C:Program FilesJavajdk1.8.0_144jrelibextccess-bridge-64.jar;C:Program FilesJavajdk1.8.0_144jrelibextcldrdata.jar;C:Program FilesJavajdk1.8.0_144jrelibextdnsns.jar;C:Program FilesJavajdk1.8.0_144jrelibextjaccess.jar;C:Program FilesJavajdk1.8.0_144jrelibextjfxrt.jar;C:Program FilesJavajdk1.8.0_144jrelibextlocaledata.jar;C:Program FilesJavajdk1.8.0_144jrelibextashorn.jar;C:Program FilesJavajdk1.8.0_144jrelibextsunec.jar;C:Program FilesJavajdk1.8.0_144jrelibextsunjce_provider.jar;C:Program FilesJavajdk1.8.0_144jrelibextsunmscapi.jar;C:Program FilesJavajdk1.8.0_144jrelibextsunpkcs11.jar;C:Program FilesJavajdk1.8.0_144jrelibextzipfs.jar;C:Program FilesJavajdk1.8.0_144jrelibjavaws.jar;C:Program FilesJavajdk1.8.0_144jrelibjce.jar;C:Program FilesJavajdk1.8.0_144jrelibjfr.jar;C:Program FilesJavajdk1.8.0_144jrelibjfxswt.jar;C:Program FilesJavajdk1.8.0_144jrelibjsse.jar;C:Program FilesJavajdk1.8.0_144jrelibmanagement-agent.jar;C:Program FilesJavajdk1.8.0_144jrelibplugin.jar;C:Program FilesJavajdk1.8.0_144jrelibesources.jar;C:Program FilesJavajdk1.8.0_144jrelibt.jar;C:UsersHeygoDesktopJVMDemooutproductionchapter11" com.atguigu.java.MaxDirectMemorySizeTestException in thread "main" java.lang.OutOfMemoryErrorat sun.misc.Unsafe.allocateMemory(Native Method)at com.atguigu.java.MaxDirectMemorySizeTest.main(MaxDirectMemorySizeTest.java:20)Process finished with exit code 1

JVM内存与垃圾回收篇第11章直接内存

以上就是JVM内存与垃圾回收篇第11章直接内存的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/19884.html

赞 (0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
win11便笺内容不见了怎么找回_win11便笺内容丢失恢复方法
上一篇 2026年8月31日 00:28:39
Elasticsearch嵌套数组筛选:如何高效查找指定年份内特定事件数量不小于N的文档?
下一篇 2026年8月31日 00:32:31

相关推荐

发表回复

登录后才能评论
关注微信