news 2026/6/1 2:56:06

JVM的类加载和垃圾回收

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
JVM的类加载和垃圾回收

二.类加载

  1. 类加载的基本流程(熟练背诵)
    java代码会被编译成.class文件(包含成一些字节码),Java程序要想运行起来就需要让jvm读取到这些.class文件,并把这里面的内容构造成类对象,保存到内存的方法区中。
    类加载的过程分以下步骤
  • 加载:找到.class文件,打开文件,读取文件内容 。
    //jvm会根据java.lang.String,java,util.ArrayList这种类名在一些指定的目录范围进行查找

  • 验证:.class文件是一个二进制的格式(某个字节都是有某些特定含义的)
    就需要验证你当前的这个格式是否符合要求的,如图为.class文件要遵守的格式

  • 准备:给类对象分配内存空间(最终的目标就是构造出类对象)
    //public static int value=123;
    //这里只是分配内存空间,还没有初始化呢,此时这个空间上的内存的数值就是全0的

  • 解析:针对类对象中的包含的字符串常量进行处理,进行一些初始化操作
    // final Sring s=“test”
    也就是把“符号引用”(文件偏移量)替换成“直接引用 ”(内存地址),因为在文件中不涉及到内存地址,因此初始化的语句会被设置为一个”文件的偏移量“,通过偏移量就能找到这个字符串所在的位置

  • 初始化: 针对类对象进行初始化,把类对象中需要的各个属性都设置好~~
    还需要 初始化static成员,需要执行静态代码块,以及还可能需要加载一下父类

2 . 双亲委派模型

属于类加载中,第一个步骤加载中的一个环节,根据全限定类名找到.class文件

  • 从Application ClassLoader作为入口,开始执行查找的逻辑,它不会立即去扫描自己负责的
    ( 负责的是搜索项目当前的目录和第三方库对应的目录), 而是把它的查找的任务交给他的父亲
  • Extension ClassLoader,也不会立即扫描自己的负责的目录,(负责的是JDK中的一些扩展库对应的目录),把它的查找的任务交给他的父亲
  • BootStrap ClassLoader,也不想立即扫描自己的负责的目录,(负责的是标准库的目录),但是它没有父亲,只能亲自负责扫描标准库的目录
    如果给的类不是标准库的类,任务仍然会交给它的孩子来执行,如果还没有扫描到就会抛出一个异常。
    搞这个流程是为了确保标准库的类被加载的优先级最高,其次是扩展库,然后是自己写的和第三方库

三.垃圾回收

GC(垃圾回收机制):让JVM自行判定,某个内存是否不再使用,然后就会自动回收了
1.引用计数(python和php)
单独安排一块空间来保存一个计数器。这个计数器描述了有多少个引用指向它。
缺点是: 比较浪费内存,如果对象小并且很多计数器,占据的空间就难以忽视,存在循环引用问题
2.Java采取的是可行性分析
可达性分析,本质上时间换空间这样的手段~~
有一组线程周期性的扫描我们代码中所有的对象出发,尽可能的进行访问的遍历,把所有能够访问道德对象,都标记成“可达”,反之经过扫描之后未被标记的对象就是垃圾了。
而这里的可达性分析都是周期性进行的,当前某个对象是否是垃圾,是随着代码的执行会发生改变的
回收垃圾的三种方式:

  1. 标记消除:把标记的对象直接删除掉。

    缺点:

    1. 效率问题:标记和清除这两个过程的效率都不⾼
    2. 空间问题:标记清除后会产⽣⼤量不连续的内存碎⽚,空间碎⽚太多可能会导致以后在程序运⾏中需要分配较⼤对象时,⽆法找到⾜够连续内存⽽不得不提前触发另⼀次垃圾收集
  2. 复制算法:通过复制的方式,把有效的对象归类在一起,再统一释放剩下的空间


2,4复制到右边,其他统一释放

缺点: ① 内存要浪费一半,利用率不高② 如果有效对象多,拷贝的开销大

  1. 标记整理:既能解决内存碎片问题,又能处理复制算法中利用率

    处理后

缺点:搬用的开销仍然很大

实际上JVM采取的释放思路是上述基础思路结合,通过区域划分实现不同区域和不同的垃圾回收策略

分代回收:
新生代:刚new的新对象放到这,从诞生到第一轮可达性分析扫描,这个虽然不长,但大部分对象都会成为垃圾

  1. 伊甸区–>幸存区复制算法,每一轮GC扫描之后,都把有效对象复制到幸存区,然后伊甸区就可以释放了
  2. GC扫描线程也会扫描幸存区,就会把活过GC扫描的对象拷贝到幸存区的另一个部分。幸存区之间的拷贝每一轮会拷贝多个对象,也会淘汰一批(随着时间的推移,有的对象就成了垃圾)
  3. 当对象在幸存区经历多轮 GC 扫描后,JVM 会判定该对象短时间内难以被释放,进而将其拷贝至老年代。
  4. 进入老年代的对象仍会被 GC 扫描,但老年代 GC 扫描频率远低于新生代;主要用标记整理。
    按经验规律:新生代对象更容易被回收,老年代对象更容易持续存活,这样设计是为了降低 GC 扫描的开销。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/1 2:54:15

GPT2-small-spanish:终极西班牙语文本生成AI模型完全指南

GPT2-small-spanish:终极西班牙语文本生成AI模型完全指南 【免费下载链接】gpt2 项目地址: https://ai.gitcode.com/hf_mirrors/Tianjin_Ascend/gpt2 想要掌握西班牙语AI文本生成技术吗?GPT2-small-spanish 是一款专为西班牙语设计的先进语言模型…

作者头像 李华
网站建设 2026/6/1 2:50:57

当风控PM,你到底需要会点什么?

📚 《风控PM记》系列文章目录 订阅关注,不错过系列更新。 欢迎在评论区留下你感兴趣的话题。 入门篇 当风控PM,你到底需要会点什么?《电商风控入门:我们到底在“防”什么?不只是薅羊毛!》 方法…

作者头像 李华
网站建设 2026/6/1 2:43:56

【文字三国志:第六篇】天命重构,UI组件设计细节

深入浅出UI组件设计 所有组件均基于 shadcn/ui 构建,这意味着它们天然地拥有良好的可访问性(ARIA、键盘导航),让我们能更专注于业务逻辑和用户体验。 1. 宏观架构: 首先,让我们从宏观上把握应用的整体布局。如下图所示,整个应用的骨架由 Layout 组件负责搭建,它包含…

作者头像 李华
网站建设 2026/6/1 2:36:58

Python 函数专项练习:6 道编程题从入门到精通

配套专栏:Python 全栈修炼之路 第 07 篇《函数 —— 代码复用的基石》 难度分布:⭐ → ⭐⭐ → ⭐⭐ → ⭐⭐⭐ → ⭐⭐⭐ → ⭐⭐⭐⭐ 核心覆盖:*args/**kwargs、闭包、装饰器、递归、lru_cache、高阶函数、LEGB 作用域、延迟绑定 题目一:通用函数调用器 ⭐ 📌 题目描述…

作者头像 李华
网站建设 2026/6/1 2:33:36

告别混乱日志!用CAPL的setLogFileName函数,实现自动化测试日志的精准归档

告别混乱日志!用CAPL的setLogFileName函数实现自动化测试日志的精准归档在汽车电子测试领域,日志文件就像黑匣子记录仪——它们承载着测试过程中每一个关键信号和异常事件。但当数百个测试用例产生的日志文件散落在不同目录,命名毫无规律时&a…

作者头像 李华