但是我们需要注意的是我们的jvm的回收功能对系统内存是没有管辖权力的
所以回收ByteBuffer的类另有他人:
package cn.itcast.jvm.t1.direct;import sun.misc.Unsafe;import java.io.IOException;import java.lang.reflect.Field;/** * 直接内存分配的底层原理:Unsafe */public class Demo1_27 {static int _1Gb = 1024 * 1024 * 1024;public static void main(String[] args) throws IOException {// unsafe正常情况下不会使用,因为系统内存通常由系统自动控制,我们这里采用暴力反射获取Unsafe unsafe = getUnsafe();// 分配内存(base实际上是该内存的地址,所以我们在释放时同样提供该base地址)long base = unsafe.allocateMemory(_1Gb);unsafe.setMemory(base, _1Gb, (byte) 0);System.in.read();// 释放内存unsafe.freeMemory(base);System.in.read();}// 暴力反射获得unsafe对象public static Unsafe getUnsafe() {try {Field f = Unsafe.class.getDeclaredField("theUnsafe");f.setAccessible(true);Unsafe unsafe = (Unsafe) f.get(null);return unsafe;} catch (NoSuchFieldException | IllegalAccessException e) {throw new RuntimeException(e);}}}然后我们就可以通过DirectMemory的源码来查看为什么它会收到jvm控制:
// Primary constructor// DirectByteBuffer构造器里面直接调用了unsafe类来进行直接内存的控制DirectByteBuffer(int cap) {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 boundaryaddress = base + ps - (base & (ps - 1));} else {address = base;}// cleaner会自动检测directMemory是否还存在,若不存在调用该方法// 这里采用cleaner,直接创建一个新的类型的Deallocator,跳转到下面的类中cleaner = Cleaner.create(this, new Deallocator(base, size, cap));att = null;} // cleaner操作跳转的类,继承了Runnableprivate static class Deallocatorimplements Runnable{private static Unsafe unsafe = Unsafe.getUnsafe();private long address;private long size;private int capacity;private Deallocator(long address, long size, int capacity) {assert (address != 0);this.address = address;this.size = size;this.capacity = capacity;}// 被清理时调用下述方法,采用unsafe.freeMemory(address)来清理直接内存,所以我们的垃圾回收才能清理直接内存public void run() {if (address == 0) {// Paranoiareturn;}unsafe.freeMemory(address);address = 0;Bits.unreserveMemory(size, capacity);}}禁用显式回收的影响其实在正常情况下我们的显式回收是不被允许开启的,因为可能会导致我们的部分信息损失:
package cn.itcast.jvm.t1.direct;import java.io.IOException;import java.nio.ByteBuffer;/** * 禁用显式回收对直接内存的影响 */public class Demo1_26 {static int _1Gb = 1024 * 1024 * 1024;/** -XX:+DisableExplicitGC 禁止显式回收配置*/public static void main(String[] args) throws IOException {ByteBuffer byteBuffer = ByteBuffer.allocateDirect(_1Gb);System.out.println("分配完毕...");System.in.read();System.out.println("开始释放...");byteBuffer = null;System.gc(); // 显式的垃圾回收,Full GC 这时这个操作是无效的System.in.read();// 那么直接内存只能等到系统内存满了之后自动调用被动垃圾回收,但那样直接内存会占用大量空间// 但是我们又希望清除掉这个直接内存,那么我们这时就只能手动采用unsafe的方法了,这里就不做代码展示了~// unsafe.freeMemory(address);}}结束语到这里我们JVM的内存结构篇就结束了,希望能为你带来帮助~
附录该文章属于学习内容,具体参考B站黑马程序员满老师的JVM完整教程
这里附上视频链接:01_什么是jvm_哔哩哔哩_bilibili
经验总结扩展阅读
- 【lwip】08-ARP协议一图笔记及源码实现
- 用一台笔记本电脑如何赚钱(笔记本电脑赚钱的办法)
- 小米笔记本Pro15增强版评测_小米笔记本Pro15增强版评测表现
- 笔记本电脑CF中烟雾头怎么调(win10cf新版本烟雾保护头怎么调)
- 笔记本电脑配置高低怎么区分(笔记本电脑看什么配置判断好坏)
- 四 【单片机入门】应用层软件开发的单片机学习之路-----ESP32开发板PWM控制电机以及中断的使用
- pytorch、paddlepaddle等环境搭建 深度学习环境搭建常用网址、conda/pip命令行整理
- 三十九 Java开发学习----SpringBoot整合mybatis
- 2023年圣诞节学习运有所提升的星座智慧多多成绩提升
- 电脑开不了机怎么办简单方法(笔记本电脑开不了机)
