堆外内存处理和回收

一、堆外内存

Jdk8中原来的方法区变成了元空间,并且使用的是堆外内存,那么堆外内存是如何进行回收的

操作系统并不会自动释放Java程序使用的堆外内存。这是因为这些内存区域不是由Java虚拟机的垃圾回收器管理的,而是由Java程序直接通过本地方法或Unsafe等手段分配的。因此,一旦分配了堆外内存,就需要在不再使用它时显式释放。

堆内存由JVM自己管理,堆外内存必须要由我们自己释放
堆内存的消耗速度远远小于堆外内存的消耗,但要命的是必须先释放堆内存中的对象,才能释放堆外内存,但是我们又不能强制JVM释放堆内存。

Direct Memory的回收机制:

Direct Memory是受GC控制的,例如
ByteBuffer bb = ByteBuffer.allocateDirect(1024),

这段代码的执行会在堆外占用1k的内存,Java堆内只会占用一个对象的指针引用的大小,
堆外的这1k的空间只有当bb对象被回收时,才会被回收,这里会发现一个明显的不对称现象,
就是堆外可能占用了很多,而堆内没占用多少,导致还没触发GC,
那就很容易出现Direct Memory造成物理内存耗光。

Direct ByteBuffer回收机制

分配出去的内存其实也是由GC负责回收的,而不像Unsafe是完全自行管理的,
HotspotGC时会扫描Direct ByteBuffer对象是否有引用,如没有则同时也会回收其占用的堆外内存。

二、Direct Memory是什么?

直接内存(Direct Memory)是 Java 虚拟机(JVM)中的一种内存分配方式,主要用于提高 I/O 操作的性能。
与 Java 堆内存不同,直接内存的分配和释放不受Java堆大小的限制,而是通过本地方法接口(Native API)直接调用底层【操作系统】的【内存分配函数】来实现。

缺点:
1、分配和释放的开销较高: 与堆内存相比,直接内存的分配和释放通常更昂贵,因为涉及到与底层操作系统的交互。
2、容易导致内存泄漏: 直接内存的垃圾回收不受 JVM 的控制,因此需要开发者手动释放内存。如果不谨慎管理,容易导致内存泄漏。
3、不受Java堆限制: 直接内存的分配和释放不受 Java 堆大小的限制,因此需要特别注意防止过度使用直接内存导致系统资源耗尽。

小结:不受Java堆限制,并且需要手动释放

三、Direct ByteBuffer是什么?

四、Direct ByteBuffer和Direct Memory区别

Direct ByteBufferDirect Memory 都涉及到直接访问系统内存,但它们是不同的概念

Direct Memory是一个很大的概念,可以理解Direct ByteBuffer他的一种实现

五、申请堆外内存和释放堆外内存-案例

通过ByteBuffer.allocateDirect()方法分配堆外内存。看下allocateDirect方法的实现。

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

主要逻辑位于DirectByteBuffer类的构造方法中,在这个构造方法中设计到了内存的申请,释放。构造方法的主要执行流程和逻辑如下:

1、调用Unsafe.allocateMemory()方法正式地分配内存,查看HotSpotnative代码,
容易发现是调用了C语言的malloc()函数。

2、调用Unsafe.setMemory()方法将分配到的内存区域初始化为全0,自然是对应C语言的memset()函数。

3、调用Cleaner.create()方法创建一个sun.misc.Cleaner实例
(其中包含有DirectByteBuffer的内部类Deallocator)该实例具体负责后面的堆外内存回收

DirectByteBuffer是一个轻量级的对象,主要的信息都维护在静态内部类Deallocator中,包括内存基地址、大小等。
Cleaner是单独维护的。由以下代码可见,Deallocator还实现了Runnable接口,当它被执行时,会调用Unsafe.freeMemory()方法(对应C语言的free()函数)释放掉它持有的堆外内存。

涉及到内存的手动释放,就要用到C语言的函数来手动指定了。

原文跳转

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

信仰_273993243

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值