JVM类加载和垃圾回收(详细)

文章目录

  • JVM
    • 介绍
      • JDK/JRE/JVM的关系
    • 内存结构
      • 程序计数器
      • 虚拟机栈
      • 本地方法栈
      • 本地内存
    • 类文件
      • 字节码文件
      • 结构
    • 类加载
        • 类的生命周期
        • 加载
          • 类加载器
          • 双亲委派模型
        • 链接
        • 初始化
        • 类卸载
    • 垃圾回收
      • 堆空间的基本结构
      • 内存分配和回收原则
      • 死亡对象判断方法
      • 垃圾收集算法
      • 垃圾收集器

JVM

介绍

JDK/JRE/JVM的关系

JDK:JRE+编译工具
JRE:JVM+基础类库
JVM

内存结构

image-20250211154647202

  • 存放对象实例

    对象

    1. 对象头:标记字段和类型指针

    2. 实例数据

    3. 对其填充

  • 字符串常量池:避免字符串的重复创建

  • 静态变量

程序计数器

作用:记住下一条jvm指令的执行地址

多线程的情况下,程序计数器记录当前线程的执行位置,当线程切换回来时能够知道运行到那里

tip:唯一一个不会内存溢出的内存区域,随线程的创建而创建,结束而死亡

虚拟机栈

作用:为虚拟机执行java方法服务

栈帧

  • 局部变量表:存放编译期可知的各种数据类型和对象引用

  • 操作数栈:存放方法执行过程中产生的中间计算结果

  • 动态链接:将类常量池中的符号应用转换为直接引用

  • 方法返回地址

    • 两种返回方式:正常返回和抛出异常

本地方法栈

作用:为虚拟机执行Native方法服务

本地内存

  • 元空间(方法区的实现类)

    • 运行时常量池:常量池表存放字面量和符号引用,在类加载后存放到方法的运行时常量池中
  • 直接内存

类文件

字节码文件

作用:

  1. 是不同语言和Java虚拟机之间的重要桥梁

  2. 是Java跨平台的重要原因(字节码不针对特定的机器,java程序无需重新编译就可以在不同操作系统的计算机上运行)

结构

image-20250211155125495

  1. 魔数:确定这个文件是否为一个能被虚拟机接收的Class文件(4字节)

  2. Class 文件版本号

    • 次版本号(2字节)
    • 主版本号(2字节)
  3. 常量池:存放字面量和符号引用

  4. 访问标志:识别一些类或接口层次的访问信息

  5. 当前类

  6. 父类

  7. 接口集合

  8. 字段表集合:成员变量(实例变量和类变量)

  9. 方发表集合

  10. 属性表集合

类加载

类的生命周期

image-20250211155929539

加载
  • 通过全类名获取定义此类的二进制字节流
  • 将字节流所代表的静态存储结构装换位方法区的运行时数据结构
  • 在内存中生成一个代表此类的Class对象,作为方法区中数据的访问入口
类加载器

定义:类加载器是一个加载类的对象;

每一个Java类都有一个引用指向加载它的ClassLoader;
数组类不是通过类加载器创建的(没有对应的二进制字节流),由JVM直接生成。

作用:加载Java类的class文件到JVM中(在内存中生成一个代表此类的Class对象)

加载规则:

  • 大部分类在使用时才会被加载

  • 一个类只会被加载一次

双亲委派模型

定义:ClassLoader实例会在尝试亲自查找类或资源之前,将查找类或资源的任务委托给父类加载器

tip:除了启动类加载器外,其他类加载器都有自己的父类加载器

各种类加载器之间的层次关系:

  • 启动类加载器:加载JDK内部的核心类库%JAVA_HOME%/lib,由C++实现

  • 扩展类加载器:加载%JRE_HOME%/lib/ext下的jar包和类

  • 应用程序类加载器:加载应用classpath下的所有jar包和类

  • 自定义类加载器:需要继承ClassLoader抽象类

    • findClass()根据二进制名称查找类

    • loadClass()加载指定二进制名称的类,实现了双亲委派机制

执行流程:

  • 判断是否被加载过

  • 将加载类的请求委托给父类加载器去完成(调用loadClass()方法)

  • 所有的父类加载器无法加载这个类时,子加载器会尝试自己去加载(调用findClass()方法)

  • 子类加载器也无法加载这个类,抛出ClassNotFoundException异常

    tip:判断两个Java类是否相同:
    1.类的全类名相同
    2.类的类加载器相同

好处:

  1. 避免了类的重复加载

  2. 保证Java核心API不被篡改

打破双亲委派模型的方法:自定义加载器,继承ClassLoader,重写loadClass()

链接

验证:保证Class文件的字节流中包含的信息符合全部约束要求,不会危害虚拟机自身安全

  • 文件格式验证

  • 元数据验证(字节码语义检查)

  • 字节码验证(程序语义检查)

  • 符号引用验证(类的正确性检查)

准备:为类变量分配内存并设置类变量初始值(在方法区分配)

tip:jdk7之后字符串常量池、静态变量等移动到了堆中

解析:将常量池中的符号引用转化为直接引用(虚拟栈中的动态链接)

初始化

执行初始化方法clinit()的条件:

  • new创建实例

  • getstatic访问类的静态变量

  • putstatic给静态变量复制

  • invokestatic调用类的静态方法

  • 需要初始化类的父类

  • 主类

类卸载

满足条件:

  • 给类的素有实例对象都已经被GC

  • 该类没有在其他地方被引用

  • 该类的类加载器的实例被GC

垃圾回收

堆空间的基本结构

堆是垃圾回收的主要区域,也称GC堆

结构:

  • 新生代
  • 老生代
  • 永久代(元空间)

image-20250211162743383

内存分配和回收原则

内存分配

  1. 对象优先在Eden区分配

  2. 大对象直接进入老年代

    • 大对象指需要大量连续内存空间的对象(比如:字符串、数组)
    • 避免将大对象放入新生代,减少新生代的垃圾回收频率和成本
  3. 长期存活的对象进入老年代

    • 当Survivor空间的对象达到晋升年龄阈值(默认15)时,会被放入到老年代中

主要进行gc的区域

  1. 部分收集Partial GC

    • 新生代收集Minor GC / Young GC:只对新生代进行垃圾收集

    • 老年代收集Major GC / Old GC:只对老年代进行垃圾收集

    • 混合收集Mixed GC:对整个新生代和部分老年代进行垃圾收集

  2. 整堆收集Full GC

空间分配担保:将新生代对象转移到老年代

死亡对象判断方法

  1. 引用计数法

    定义:当引用它时,+1;引用失效时,-1;计数器为0时,对象就不可能再被使用了

    缺点:无法解决对象之间循环引用的问题

  2. 可达性分析算法

    定义:判断对象到GC Roots是否可达(可达:存在引用链)

    可以作为GC Roots:

    • 方法区中静态变量、常量引用的对象

    • 虚拟栈中引用的对象

    • 本地方法栈中引用的对象

    • 所有被同步锁持有的对象

    • JNI(Java Native Interface)引用的对象

引用类型

  • 强引用:一定不会被回收

  • 软引用:内存空间不足的时候,回收

  • 弱引用:扫描到就会回收

  • 虚引用:用来跟踪对象被垃圾回收的过程,必须配合引用队列使用

垃圾收集算法

  1. 标记-清除算法:标记不需要回收的对象(可达对象),清除没有标记的对象

    缺点

    • 效率问题:标记和清除过程效率不高

    • 空间问题:回收后会产生大量不连续的内存碎片

  2. 复制算法:将内存划分为大小相同的两块,把存活的对象复制到另一块内存上,再把使用的空间全部清除

    缺点

    • 可用内存变小

    • 不适合老年代:如果存活对象比较大,复制性能会变差

  3. 标记-整理算法:先标记不需要回收的对象,然后让存活对象移动到一段,最后清除到端边界以外的内存

    缺点

    • 效率不高,适合老年代这种垃圾回收频率不高的场景
  4. 分代收集算法:根据对象存活周期不同划分为新生代和老年代,不同年代选择合适的垃圾收集算法

    新生代:复制算法,大量对象死亡,只需要复制少量对象
    老年代:标记-清除或标记-整理,对象存活率高,需要清除的较少

垃圾收集器

  1. Serial收集器:使用一条线程进行垃圾收集工作时,暂停其他所有工作线程

  2. Serial Old收集器:Serial收集器的老年代版本

  3. ParNew收集器:Serial收集器的多线程版本

  4. Parallel Scavenge收集器:提高CPU利用率

  5. Parallel Old收集器:Parallel Scavenge收集器的老年代版本

  6. CMS收集器:获得最短回收停顿时间的收集器,提高用户体验;真正意义上的并发收集器,垃圾收集线程和用户线程同时工作

    四个步骤

    • 初始标记:短暂停顿,标记可达对象

    • 并发标记:开启GC和用户线程,标记可达对象,但不包含所有可达对象,因为用户线程会导致标记变动

    • 重新标记:短暂停顿,修正并发标记期间的对象标记记录

    • 并发清除:开启GC和用户线程,对未标记区域进行清除

    优点

    • 并发收集

    • 低停顿

    缺点

    • 对CPU资源敏感

    • 无法处理浮动垃圾

    • 标记-清除算法,会产生大量空闲碎片

  7. G1收集器:面向服务器的垃圾收集器,针对于配备了多颗处理器的机器

    四个步骤

    • 初始标记:短暂停顿,标记可达对象

    • 并发标记:开启GC和用户线程,标记可达对象,但不包含所有可达对象,因为用户线程会导致标记变动

    • 最终标记:短暂停顿,修正并发标记期间的对象标记记录

    • 筛选回收:选择回收价值高的区域,复制存活对象到新区域,清楚旧区域

  8. ZGC收集器

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

算法——结合实例了解深度优先搜索(DFS)

一,深度优先搜索(DFS)详解 DFS是什么? 深度优先搜索(Depth-First Search,DFS)是一种用于遍历或搜索树、图的算法。其核心思想是尽可能深地探索分支,直到无法继续时回溯到上一个节点…

[c语言日寄]在不完全递增序中查找特定要素

【作者主页】siy2333 【专栏介绍】⌈c语言日寄⌋:这是一个专注于C语言刷题的专栏,精选题目,搭配详细题解、拓展算法。从基础语法到复杂算法,题目涉及的知识点全面覆盖,助力你系统提升。无论你是初学者,还是…

计算机视觉-局部特征

一、局部特征 1.1全景拼接 先用RANSAC估计出变换,就可以拼接两张图片 ①提取特征 ②匹配特征 ③拼接图像 1.2 点的特征 怎么找到对应点?(才能做点对应关系RANSAC) :特征检测 我们希望找到的点具有的特征有什么特…

实践记录-NAS入手前后的记录-关于设备选型的练习

快速回顾 知道nas是干啥的不,你买这东西准备干啥?你准备花多少预算啊?在配置性能/价格/需求之间做个取舍和平衡;看看设备到底怎么样?入手体验如何? 参考来源 服务器和网络设备的技术方案设计和设备选型的…

机器学习 - 词袋模型(Bag of Words)实现文本情感分类的详细示例

为了简单直观的理解模型训练,我这里搜集了两个简单的实现文本情感分类的例子,第一个例子基于朴素贝叶斯分类器,第二个例子基于逻辑回归,通过这两个例子,掌握词袋模型(Bag of Words)实现文本情感…

评估多智能体协作网络(MACNET)的性能:COT和AUTOGPT基线方法

评估多智能体协作网络(MACNET)的性能 方法选择:选择COT(思维链,Chain of Thought)、AUTOGPT等作为基线方法。 COT是一种通过在推理过程中生成中间推理步骤,来增强语言模型推理能力的方法,能让模型更好地处理复杂问题,比如在数学问题求解中,展示解题步骤。 AUTOGPT则是…

服务器中部署大模型DeepSeek-R1 | 本地部署DeepSeek-R1大模型 | deepseek-r1部署详细教程

0. 部署前的准备 首先我们需要足够算力的机器,这里我在vultr中租了有一张A16显卡一共16GB显存的服务器作为演示。部署的模型参数为14b的。如果需要部署满血版本671b的,需要更大的算力支持,这里由于是个人资金有限,就演示14b的部署…

chrome://version/

浏览器输入: chrome://version/ Google浏览器版本号以及安装路径 Google Chrome131.0.6778.205 (正式版本) (64 位) (cohort: Stable) 修订版本81b36b9535e3e3b610a52df3da48cd81362ec860-refs/branch-heads/6778_155{#8}操作系统Windows…

web集群(LVS-DR)

LVS是Linux Virtual Server的简称,也就是Linux虚拟服务器, 是一个由章文嵩博士发起的自由软件项 目,它的官方站点是 www.linuxvirtualserver.org。现在LVS已经是 Linux标准内核的一部分,在 Linux2.4内核以前,使用LVS时必须要重新编…

Python+appium实现自动化测试

目录 一、工具与环境准备 二、开始测试 1、插上手机,打开usb调试,选中文件传输,我这里用华为手机为例 2、启动Appium Server GUI​编辑 3、启动 Inspector Session 4、录制脚本 使用Python和Appium进行自动化测试是一种常见的移动应用…

光谱相机在天文学领域的应用

天体成分分析 恒星成分研究:恒星的光谱包含了其大气中各种元素的吸收和发射线特征。通过光谱相机精确测量这些谱线,天文学家能确定恒星大气中氢、氦、碳、氮、氧等元素的含量。如对太阳的光谱分析发现,太阳大气中氢元素占比约 71%&#xff0…

Java 设计模式之桥接模式

文章目录 Java 设计模式之桥接模式概述UML代码实现 Java 设计模式之桥接模式 概述 桥接模式(Bridge):将抽象部分与它的实现部分分离,使它们都可以独立地变化。通过桥接模式,可以避免类爆炸问题,并提高系统的可扩展性。 UML 核心…

Git | 相关命令

相关资料 官网Git 学习教程Git 入门指南Git 的奇技淫巧Git Extras git 命令行扩展工具配置 Git 处理行结束符Git 配置多个 SSH-Key下载相关 Windows 版下载镜像使用 jsdelivr 加速 Github 仓库资源 commit 常用的 type 常用 Git 命令 [xxx] 均为可选参数 git clone # 拷贝一…

【STM32】H743的以太网MAC控制器的一个特殊功能

调试743的MAC,翻阅手册的时候,发现了一个有意思的功能 混杂模式 H743的MAC控制器,可以设置为混杂模式,这就意味着它可以做一些网络监控的应用,譬如连接具备端口镜像功能的交换机,然后直接代替PC实现网络数据…

【Spring AI】基于SpringAI+Vue3+ElementPlus的QA系统实现(后端)

整理不易,请不要吝啬你的赞和收藏。 1. 前言 这篇文章将介绍如何基于 RAG 技术,使用 SpringAI Vue3 ElementPlus 实现一个 Q&A 系统。本文使用 deepseek 的 DeepSeek-V3 作为聊天模型,使用阿里百炼的 text-embedding-v3 作为向量模型&…

AI法理学与责任归属:技术演进下的法律重构与伦理挑战

文章目录 引言:智能时代的新型法律困境一、AI技术特性对传统法理的冲击1.1 算法黑箱与可解释性悖论1.2 动态学习系统的责任漂移1.3 多智能体协作的责任稀释二、AI法理学的核心争议点2.1 法律主体资格认定2.2 因果关系的技术解构2.3 过错标准的重新定义三、责任归属的实践案例分…

数值积分:通过复合梯形法计算

在物理学和工程学中,很多问题都可以通过数值积分来求解,特别是当我们无法得到解析解时。数值积分是通过计算积分区间内离散点的函数值来近似积分的结果。在这篇博客中,我将讨论如何使用 复合梯形法 来进行数值积分,并以一个简单的…

mybatis-plus逆向code generator pgsql实践

mybatis-plus逆向code generator pgsql实践 环境准备重要工具的版本供参考pom依赖待逆向的SQL 配置文件CodeGenerator配置类配置类说明 环境准备 重要工具的版本 jdk1.8.0_131springboot 2.7.6mybatis-plus 3.5.7pgsql 14.15 供参考pom依赖 <?xml version"1.0&quo…

RedHat8安装postgresql15和 postgis3.4.4记录及遇到的问题总结

安装包对照版本参考 UsersWikiPostgreSQLPostGIS – PostGIS 如果Red Hat系统上有旧版本的PostgreSQL需要卸载 在较新的Red Hat版本&#xff0c;使用dnf包管理器卸载&#xff1a;sudo dnf remove postgresql-server postgresql 旧版本&#xff0c;使用yum包管理器卸载 sudo y…

2024BaseCTF_week4_web上

继续&#xff01;冲冲冲 目录 圣钥之战1.0 nodejs 原型 原型链 原型链污染 回到题目 flag直接读取不就行了&#xff1f; 圣钥之战1.0 from flask import Flask,request import jsonapp Flask(__name__)def merge(src, dst):for k, v in src.items():if hasattr(dst, __geti…