JVM 直接内存和堆内存

分配方式

  • 直接内存是通过 ByteBuffer.allocateDirect() 方法来分配的,它是通过操作系统的本地方法直接分配内存的,不受 Java 堆大小的限制。
  • 普通内存是通过 Java 虚拟机的堆内存来分配的,由 JVM 在堆内存中动态分配和回收内存,受到 Java 堆大小限制。

内存访问方式

  • 直接内存的访问方式是直接访问,即不需要将数据从 本地内存复制到JVM 的堆内存,而是直接在本地内存中进行操作。
  • 普通内存的访问方式是间接访问,即需要将数据从 JVM 的堆内存复制到 CPU 的缓存中才能进行操作,然后再将结果写回堆内存。

内存释放方式

  • 直接内存的释放通常由操作系统负责,无需 JVM 进行垃圾回收操作。
  • 普通内存的释放由 JVM 的垃圾回收器负责,需要等待垃圾回收器对不再使用的对象进行标记和回收操作

使用直接内存、非直接内存复制视频文件demo

最终直接内存比非直接内存速度快一倍。

package cn.itcast.protocol;

import cn.itcast.message.ChatRequestMessage;

import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

/**
 * @author Sherry Guo
 * @date 2024/2/1 16:35
 */
public class Demo {
    public static void main(String[] args) throws IOException {

        String sourceFilePath = "E:\\BaiduNetdiskDownload\\bytebuffer.mp4";
        String targetFilePath = "E:\\BaiduNetdiskDownload\\new.mp4";
        String target2FilePath = "E:\\BaiduNetdiskDownload\\new2.mp4";

        long start1 = System.currentTimeMillis();

        // 使用直接内存复制视频文件
        try (FileInputStream fis = new FileInputStream(sourceFilePath);
             FileOutputStream fos = new FileOutputStream(targetFilePath);
             FileChannel sourceChannel = fis.getChannel();
             FileChannel targetChannel = fos.getChannel()) {

            ByteBuffer buffer = ByteBuffer.allocateDirect(1024 * 1024); // 使用直接内存(1MB)
            while (sourceChannel.read(buffer) != -1) {
                buffer.flip();
                targetChannel.write(buffer);
                buffer.clear();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }


        long l = (System.currentTimeMillis() - start1);
        System.out.println(l);
        System.out.println("\n------------------------------------------");
        long start2 = System.currentTimeMillis();
        // 使用非直接内存复制视频文件
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
            fis = new FileInputStream(sourceFilePath);
            fos = new FileOutputStream(target2FilePath);
            byte[] buffer = new byte[1024 * 1024]; // 使用非直接内存(1MB)
            int bytesRead;
            while ((bytesRead = fis.read(buffer)) != -1) {
                fos.write(buffer, 0, bytesRead);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            fis.close();
            fos.close();
        }
        long l2 = (System.currentTimeMillis() - start2) ;
        System.out.println(l2);


    }
}

直接内存案例中使用 try-with-resources 语句时,流会在代码块执行完毕后自动关闭,无需手动在 finally 块中关闭。这是 try-with-resources 语句的一大优点,可以避免手动关闭流可能导致的错误或遗漏。

释放直接内存

直接内存不受JVM管理,可使用Unsafe进行释放。

  • 17
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值