116.Java深入学习之JVM二

news/2025/12/9 20:00:44/文章来源:https://www.cnblogs.com/gaodiyuanjin/p/19327526

今天整理的内容为 直接内存和垃圾回收

直接内存

image

正常来说需要一步一步才能访问到jvm的堆内存

但是直接内存:
过 java.nio(java I/O库)直接缓冲区直接分配
绕过堆,由操作系统直接管理的本地内存区域,主要用于提升高性能I/O操作的速度
回收成本高不受JVM内存回收管理 读写性能高

这样就可以直接访问jvm的堆内存
image

其语句为:

ByteBuffer byteBuffer = ByteBuffer.allocateDirect(); 开辟分配直接内存

同样这样也会造成内存溢出问题

我们来验证其直接内存的过程原理:

public class 直接内存 {static int _1G = 1024 * 1024 * 1024;public static void main(String[] args) throws IOException {ByteBuffer byteBuffer = ByteBuffer.allocateDirect(_1G);System.out.println("分配");//等待用户输入EnterSystem.in.read();System.out.println("释放");//失去所有对直接缓冲区的引用byteBuffer = null;System.gc();System.in.read();}
}

大致就是看到直接内存如何分配和gc回收是否会释放掉它(注:我们需要在任务管理器中查看进程变化)
创建分配出来
image

然后gc回收 发现释放掉了
image

关于过程:

需要我们进入直接内存分配方法中
image

创建了DirectByteBuffer
image

对应关联了cleaner
image

然后GC触发后 就执行cleaner.run
UNSAFE.freeMemory释放直接内存
image

大致流程就是:
触发GC回收->DirectByteBuffer->关联Cleaner->Cleaner.run() UNSAFE.freeMemory->释放native堆上内存


垃圾回收

关于这个是重点也是难点 我尽量理解这样的
image

首先一个对象能不能回收JVM如何知道

1.引用计数算法 给对象添加一个引用计数器 引用失效减1 当变为0可被回收
但是如果两个对象循环引用 就永远不会为0 JVM不采用这个
2.可达性分析算法  从GC Roots 为开始点 然后搜索 能搜索到的对象都是存活的 不可搜索到的可被回收
JVM采用此算法 线程栈中的局部变量 静态字段(static) 锁(synchronized)/JNI、本地线程 ThreadLocal 上的值

可达性分析算法 就是从根开始找 找不到的对象就是不可存活对象 可回收掉
image

1.五种引用类型

  • 强引用

new 对象(); 即为强引用
被强引用关联的对象不可被回收
image
之前关于字符串常量池那些整理也有

  • 软引用
    被软引用关联的对象 内存不足的情况下会被回收(也未被强引用引用)
    SoftReference<对象> sf = new SoftReference<对象>(obj);
  • 弱引用
    (未被强引用引用) 一定会被回收掉
    WeakReference wf = new WeakReference(obj);
  • 虚引用
    其引用的对象被回收后 其会被先放入队列中 随后被回收(未被强引用引用)
  • 终结器引用
    用来追踪并把实现 finalize() 的对象放入终结器队列,等其 finalize 方法执行完后再由 GC 释放其内存
  • 上述五种引用我们来关联垃圾回收验证其内存溢出问题:

    验证强引用-软引用内存溢出问题:
    public class Ying_yong {static final int _4MB = 4 * 1024 * 1024;public static void main(String[] args) {//强引用ArrayList<byte[]> list = new ArrayList<>();for (int i = 0; i < 5; i++) {list.add(new byte[_4MB]);}
    //        soft();}//软引用 内存不足后 触发GC回收掉了public static void soft() {ArrayList<SoftReference<byte[]>> list = new ArrayList<>();for (int i = 0; i < 5; i++) {SoftReference<byte[]> sf = new SoftReference<>(new byte[_4MB]);list.add(sf);}for (SoftReference<byte[]> softReference : list) {System.out.println(softReference.get());}}
    }
    

    注:我们设置堆大小20M
    image

    首先运行强引用 内存溢出 垃圾回收未触发
    image

    运行软引用 触发了GC垃圾回收 并打印出了东西 前面几个对象已经被回收掉了
    image

    2.垃圾回收算法

    • 标记-清除

    标记存活的对象(即GC Roots搜索到的对象) 清除掉未被标记(即可回收)的对象
    速度效率很快 但是缺点在于内存空间造成不连续大量碎片
    image
    这个很简单理解 GC Roots标记存活对象 没被标记的即可回收的对象 被回收

    • 标记-整理

    所有存活对象向一侧移动 然后移动的时候清理掉可回收的对象
    速度效率慢 但是整体紧凑 不会出现大量碎片空间
    image

    • 复制

    分成两块内存大小一样 然后将第一块标记好的存活对象复制到第二块
    清除掉第一块只剩下的可回收对象 交换以此反复
    缺点就是占用双倍内存空间 也不会造成内存碎片
    image
    至于from区和to区是举例用的 后面分代回收会着重讲

    接下来是重点即分代回收
    首先分为新生代(年轻代)和老年代
    image

    新生代存放新创建的对象 采用复制算法 Minor GC
    老年代存放多次使用存活时间长的对象 采用标记-清除/整理 算法 Full GC

    分代回收的过程在复制算法讲过就是如下:

    首先将eden和from区可存活的对象放入to区 年龄+1
    若对象寿命达到阈值则移到老年代
    然后清空eden和from区可回收的垃圾
    交换from和to区 以此反复
    分代回收过程

    大部分时间只会进行 Minor GC 只有内存极端不足或老年代对象占用过多时才触发 Full GC
    Minor GC 通过复制算法快速清理大部分垃圾,避免了 Full GC 的开销
    Full GC 只在必要时才触发,采用 mark‑compact(标记‑压缩)以解决老年代碎片问题

    我们当然需要代码实际中来验证:

    public class Test_GC_options {static final int _7MB = 7 * 1024 * 1024;static final int _10MB = 10 * 1024 * 1024;public static void main(String[] args) {}
    }
    

    加入参数 打印参数观察

    堆大小20M 新生代10M   单线程垃圾收集器 打印GC基础信息
    -Xms20m -Xmx20m -Xmn10m -XX:+UseSerialGC -XX:+PrintGCDetails -verbose:gc
    

    不加入任何对象 运行
    image

    我们拿出来打印信息Heap堆def new generation新生代 我们设置的10M   total 9216K, used 2352K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)eden space 8192K,  28% used [0x00000000fec00000, 0x00000000fee4c010, 0x00000000ff400000)from space 1024K,   0% used [0x00000000ff400000, 0x00000000ff400000, 0x00000000ff500000)
    to   space 1024K,   0% used [0x00000000ff500000, 0x00000000ff500000, 0x00000000ff600000)tenured generation 老年代 10M   total 10240K, used 0K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)the space 10240K,   0% used [0x00000000ff600000, 0x00000000ff600000, 0x00000000ff600200, 0x0000000100000000)
    Metaspace   元空间    used 579K, committed 768K, reserved 1114112K
    class space    used 36K, committed 128K, reserved 1048576K
    

    我们发现eden区已经用了28%

    这个时候我们强引用加入存活对象 看变化

            ArrayList<byte[]> list = new ArrayList<>();list.add(new byte[_7MB]);
    

    加入7M后 因为eden区不够了 放入了from区 实际上是放到了to区 然后from区和to区互换了
    image

    这个时候我们在加入10M 这个时候新生代肯定顶不住了

            list.add(new byte[_10MB]);
    

    首先肯定溢出了 总共才20M 然后我们发现新生代不够了 就放入了老年代
    image

    至此验证完毕

    3.GC参数和垃圾收集器

    关于GC参数大概就是jvm的设置参数
    我记得的:
    -Xms 初始堆大小 -Xmx堆最大大小
    两个设为相同 避免运行时扩容带来的停顿
    -Xmn 新生代大小
    -XX:+PrintGCDetails -verbose:gc 打印详细GC信息 基础GC打印
    -XX:+UseSerialGC 单线程垃圾收集器

    更多参考:https://pdai.tech/md/java/jvm/java-jvm-param.html

    1.串行垃圾回收器Serial(复制算法)  Serial Old(标记-整理算法)
    -XX:+UseSerialGC
    只使用一个线程进行垃圾回收工作 前者工作于新生代 后者老年代
    2.吞吐量优先垃圾回收器
    -XX:+UseParallelGC	  大多数jdk8+版本默认并行GC
    并行多线程工作
    3.响应时间优先处理器 CMS 收集器
    XX:+UseConcMarkSweepGC	采用标记-清除算法 JDK18+已移除
    四个阶段
    初始标记: 仅仅只是标记一下 GC Roots 能直接关联到的对象 速度很快 需要停顿
    并发标记: 进行 GC Roots Tracing 的过程 它在整个回收过程中耗时最长 不需要停顿
    重新标记: 为了修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录 需要停顿
    并发清除: 不需要停顿
    

    这里还需要介绍一个G1(Garbage-First):

    首先我们需要区别一个东西 一中总结的GC(1)表示的这次GC的序号
    而不是接下来我们要说的G1
    image

    核心就是:把堆划分为若干相等大小的Region
    (整体标记-整理算法实现 局部(两个Region之间)复制算法实现)
    image

    关于每个Region区 过程类似分代回收但也有区别
    1.先在Young Region对象分配 达到阈值分配到老年代 触发Minor GC
    2.若老年代也达到阈值就触发并发标记
    3.有条件性的垃圾回收

    另外插一嘴:大小达到甚至超过分区大小一半的对象称为巨型对象
    GC会把它直接放进老年代 可减少(新生代处理时)停顿

    4.GC调优

    我就说俩问题 具体调优不是一成不变的 会根据环境和机器的情况调整
    【新生代是否越大越好吗
    不一定 可能会导致新生代的Minor GC停顿时间变长
    若晋升率过高可能触发更多的Full GC

    Full GC和Minor GC频繁
    空间内存不足导致 解决方案均衡新生代和老年代大小比例】

    更多调优参考:https://pdai.tech/md/java/jvm/java-jvm-oom.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/995462.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

第五十八篇

今天是12月9号,上了英语

洛谷 P1203 [USACO1.1] 坏掉的项链 Broken Necklace 题解 最短代码|详细

事情是这样的: 今天我在洛谷上刷题,遇到一个UASCO的题,虽然是橙题,但是还是很有滋味的 看了看大佬的思路发现太抽象了,评论区不是%%%就是orz,因此有了这篇题解题解原文 这绝对是最短的题解了。。。(难理解别打我…

2025年12月佛山二手房拍卖机构标杆推荐:佛山房屋拍卖推荐佛山市中正易拍拍卖有限公司

随着司法拍卖机制日益规范、信息透明度持续提升,以及购房者对高性价比房产的关注度不断上升,法拍房市场在2025年迎来新一轮发展契机。尤其在佛山等珠三角核心城市,法拍住宅因价格优势、房源多样等特点,逐渐成为刚需…

第五十七篇

今天是12月8号。上了数据,建模语言和Java

2025年唐老狮:游戏开发教育商业模式深度解析与性价比评估

本文将从商业模式与性价比这一核心维度出发,对唐老狮游戏开发教学体系进行系统性剖析。当前在线职业教育市场鱼龙混杂,课程定价从免费到数万元不等,质量参差不齐。在此背景下,唐老狮凭借独特的价值定位与运营策略,…

2025年12月河南驻马店气体配送优质厂家推荐:河南宏源气体,氧气气体配送、氮气气体配送、氦气气体厂家、二氧化碳气体配送、氩气气体公司、高纯气体配送、多品类气体供应新标杆

随着工业生产精细化升级、各行业对气体品质要求提升及物流配送效率需求增加,专业气体配送服务已从传统工业领域逐步拓展至医疗、食品、化工、制造等多个行业,2025 年市场需求预计持续增长。但市场扩容也带来厂商服务…

开放式互联互通的路上,希望畅联云越走越顺

畅联云是一个开放的互联互通的云,能接入各种视频设备,物联网设备,让客户直接使用即可,不用再做底层每个设备的对接了。所谓开放,是针对萤石云、针对小米这样的封闭平台的。毕竟萤石云只能接入海康或者萤石的视频设…

2025年唐老狮:游戏开发教育领域深度解析与行业竞争力权威揭秘

引言:本文将聚焦于市场定位与竞争优势这一核心维度,对唐老狮在游戏开发教育领域的商业逻辑、竞争壁垒及行业价值进行系统性剖析,为学习者、教育从业者及行业观察者提供具备决策参考价值的客观分析。 背景与概况:唐…

吴恩达深度学习课程四:计算机视觉 第一周:卷积基础知识(二)卷积参数

此分类用于记录吴恩达深度学习课程的学习笔记。 课程相关信息链接如下:原课程视频链接:[双语字幕]吴恩达深度学习deeplearning.ai github课程资料,含课件与笔记:吴恩达深度学习教学资料 课程配套练习(中英)与答案…

2025年唐老狮:游戏开发课程体系全景解析与行业应用价值深度评估

引言:本文将从课程体系完整性与进阶路径设计这一核心维度出发,对唐老狮的游戏开发教学体系进行系统性剖析,重点评估其课程架构的逻辑性、技能覆盖的全面性以及学习路径的科学性,为有意向进入游戏开发领域的学习者提…

2025年法式高端家具TOP10榜(东莞深圳广州惠州专向版)

2025 东莞洛可可家具TOP10深度评估:珠三角高端法式家居的产业样本 在珠三角的高端家居市场里,法式、宫廷、洛可可家具这两三年又火了回来。尤其是东莞、深圳、广州、佛山、惠州一带的大平层、别墅、会所项目里,设计…

2025年唐老狮:游戏开发教学领域的深度解析与行业影响力权威评估报告

引言:本文将聚焦教学体系与课程设计方法论这一核心维度,系统剖析唐老狮在游戏开发教育领域的独特价值与行业影响,为学习者与从业者提供具备参考价值的客观分析。 背景与概况:唐老狮是游戏开发教学领域极具口碑的知…

链路追踪基础SkyWalking/Zipkin认知与分布式系统问题定位实战

一、为什么分布式系统离不开链路追踪? 半夜接到用户投诉 “下单页面加载超时”,打开日志却陷入混乱:服务 A 显示正常响应,服务 B 全是零散请求 ID,数据库告警慢查询但找不到关联请求 —— 这是分布式系统排障的典…

2025年12月多光谱相机厂家推荐,多光谱成像仪、高光谱成像系统、小型多光谱相机、微型多光谱相机、机载多光谱相机、便携多光谱相机、聚焦遥感测绘领域专业解决方案

随着遥感技术在农业、林业、科研等领域的应用不断深化,多光谱与高光谱相机作为核心传感设备,市场需求持续攀升。2025 年,行业对设备的便携性、成像精度、场景适配性提出了更高要求,但市场中设备厂商的技术实力与服…

为什么会诞生流形的概念?

这是一个非常深刻的问题,也是从“古典数学”迈向“现代数学”的关键门槛。 你的困惑在于:为什么我们不能总是用上帝视角(外部直角坐标系)来看问题,而非要搞出“流形”这个复杂的概念? 我们要分三个层次来回答:维…

2025年12月东营搬家公司推荐:双福搬家,东营搬家搬厂、东营河口搬家、东营垦利搬家、东营市搬家、东营单位搬家、东营设备搬运、全场景搬迁服务标杆

随着东营地区城市化进程加快、企业搬迁需求升级及家庭移居频率提升,搬家服务已从基础运力服务逐步向专业化、全场景化延伸,2025 年本地搬家市场规模预计稳步增长。但市场扩容也带来服务质量、专业度、安全保障等方面…

2025年唐老狮全面盘点:游戏开发课的行业积淀与服务价值

唐老狮是2025年游戏开发教学领域极具口碑的知名UP主,尤其是专注于Unity、UE4游戏开发课程教学,其官方网站“游习堂”(www.yxtown.com)及B站、小红书、YouTube等平台长期输出优质免费内容,凭借系统化教学、扎实干货…

day16-Trae开发飞机大战并上线

今日内容 1 Trae介绍安装和配置 1.1 常见的AI编辑器 # 什么是AI编辑器?-之前python开发,使用pycharm---》代码完全由我们自己编写--》自己调试--》自己修改bug--》直到开发完成-有了ai编辑器后,Trae---》代码完全由…

2025年12月丝杆升降机标杆厂家最新推荐:德州德特机械,螺旋升降机、sjb螺旋升降机、zimm螺旋升降机、SJA螺旋升降机、联动丝杆升降机、螺旋丝杆升降机、专注精密传动新标准

随着工业自动化升级、精密制造要求提升及设备可靠性需求增加,丝杆升降机已从传统重工领域扩展至新能源、智能制造、生产线改造等多个场景,2025年市场规模预计持续增长。但市场扩张也带来产品精度、耐久性、适配方案参…

2025年唐老狮权威解读:游戏开发课的体系化构建优势

唐老狮是游戏开发教学领域极具口碑的知名UP主,专注于Unity、UE4游戏开发课程教学,其官方网站“游习堂”(www.yxtown.com)及B站、小红书、YouTube等平台长期输出优质免费内容,凭借系统化教学、扎实干货与高性价比,…