JVM(内存划分+类加载+GC)

news2024/11/28 22:53:51

目录

🐲 1. JVM 内存划分

🐲 2. JVM 类加载

🦄 2.1 类型加载是干啥的

🦄 2.2 类加载的简略流程           

🦄 2.3 什么时候会进行类加载

🦄 2.4 双亲委派模型

🐲 3. GC 垃圾回收机制

🦄 3.1 GC 是什么

🦄 3.2 GC 回收哪部分内存

🦄 3.3 GC 具体是怎么回收的

🦖 3.3.1 怎么判定某个对象是否是垃圾 (引用计数/可达性分析) 

🦖 3.3.2 具体是怎么回收的 (标记清除/复制算法/标记整理/分代回收)


JVM是一个比较大的话题,但面试主要从这三个方面考

  1.  JVM 内容划分
  2.  JVM 类加载
  3.  JVM 的垃圾回收

🐲 1. JVM 内存划分

Java程序, 就是一个名字为 Java 的进程. 这个进程就是所说的 "JVM"

JVM 就会先从操作系统这里申请一大块内存空间,在这个基础上再把这个内存空间划分成几个小的区域

区域划分:

  1. 堆: 放的是 new 的对象
  2. 方法区: 放的是 类对象 (加载好的类)
  3. 栈: 放的是方法之间的调用关系 (虚拟机栈: java 里面用来保存调用关系的内存空间;         本地方法栈: 本地方法,也就是 JVM 内部 C++ 写的代码,调用关系的内存空间)
  4. 程序计数器: 放的是下一个要执行的指令的地址 


🐲 2. JVM 类加载

🦄 2.1 类型加载是干啥的

Java 程序在运行之前,需要先编译    .java -->  .class文件(二进制字节码文件)

运行的时候,   .java进程(JVM) 就会读取对应的   .class文件,并且解析内容,在内存中构造出类对象并进行初始化

类 从 文件 加载到 内存 中

 类对象: 在前面中类对象出现在反射,jackson,synchronized 中

主要就是描述了这个类是啥样子的

有哪些属性(属性名字,类型,private/public)

有哪些方法(方法名字,参数个数,类型,返回值类型,private/public)

继承自哪个父类,实现哪些接口

类对象也是创建实例的具体依据


🦄 2.2 类加载的简略流程           

1. 加载: 找到 .class 文件,读取文件内容, 并且按照 .class 规范的格式来解析

2. 连接

     1. 验证: 检查看当前的 .class 里的内容格式是否符合要求

                   (不同版本的 JDK 得到的 .class 是不兼容的)

     2. 准备: 给类中的静态变量分配内存空间

     3. 解析: 初始化字符串变量,把 符号引用(占位符)  替换成 直接引用(内存地址) 

3. 初始化: 针对类进行初始化, 初始化静态成员, 执行静态代码块, 并且加载父类

🦄 2.3 什么时候会进行类加载

使用到一个类的时候,就触发类加载

(类并不一定是程序一启动就加载了,而是第一次使用才加载 [有点类似于懒汉模式])

使用一个类,这里指的是

  1. 创建这个类的实例
  2. 使用了类的静态方法 / 静态属性
  3. 使用类的子类 (加载子类会触发加载父类)

🦄 2.4 双亲委派模型

决定了按照啥样的规则来在哪些目录里去找 .class 文件

也就是描述了加载器相互配合的工作过程,就是双亲委派模型

JVM 加载类, 是由 类加载器 (class loader) 这样的模块来负责的

JVM 自带了多个类加载器,每个类加载器各自负责一个区域

  1. Bootstrap ClassLoader (负责加载标准库中的类)
  2. Extension ClassLoader (负责加载 JVM 扩展库的类(语言规范中没有,但是JVM实现的))
  3. Application ClassLoader (负责加载我们自己项目中的自定义的类)

按照这样的顺序加载, 最大的好处在于

如果我们自己写个类,刚好 全限定类名和标准库中的类名冲突了,(比如我们自己写个类就叫,java.lang.Thread)

此时仍然可以保证类加载时,可以加载到标准库的类,防止代码加载错了带来问题 


🐲 3. GC 垃圾回收机制

🦄 3.1 GC 是什么

GC (垃圾回收) 是一个主流的内存回收的方案, Java/Python/JS/GO/PHP 都是使用GC

我们只需要负责申请内存, 而释放内存的工作, 交给 JVM 来完成, JVM 会自动判定当前的内容是啥时候需要释放, 当认为这个内存不再使用了, 就自动释放了


🦄 3.2 GC 回收哪部分内存

JVM 主要内存分为这几个部分

  • 堆 : 存放的时 new 的对象 (GC 主要就是针对堆来进行回收)
  • 栈 : 保存方法之间的调用关系(释放时机确定, 不必回收)
  • 方法区 : 放的是 类对象 (类加载, 加载之后也不太会卸载)
  • 程序计数器 : 保存下一条要执行的指令地址 (固定内存空间, 不必回收)


🦄 3.3 GC 具体是怎么回收的

  1. 先找出垃圾 (看看谁是垃圾)
  2. 再回收垃圾 (释放内存)

🦖 3.3.1 怎么判定某个对象是否是垃圾 (引用计数/可达性分析) 

如果一个对象不再用了,就说明是垃圾了

在 Java 中,对象的使用,需要凭借 引用

假设如果有一个对象,已经没有任何引用能够指向他了,这个对象自然也就无法再被使用了

所以最关键的要点就是:

通过引用来判定当

前对象是否还能被使用了,没有引用指向就视为是无法被使用

两种常见的,判定对象是否存在引用的方法

1. 引用计数 [不是 JVM 采取的方法, 比如 Python,PHP]

给每个对象都加上个计数器,这个计数器就表示 "当前的对象有几个引用"

当引用计数器, 数值为 0 时, 就说明当前这个对象已经无人能够使用了,此时就可以进行释放了

引用计数的优点: 简单,容易实现,执行效率比较高

缺点:

  (1) 空间利用率比较低, 尤其是小对象

       (比如,计数器是个 int, 如果你的对象本身里面只有一个 int 成员,利用率低)

  (2) 可能会出现循环引用的情况 

2. 可达性分析 [是 JVM 采用的方法, java]

约定一些特定的变量,成为 "GC roots"

每隔一段时间,从 GC toots 出发, 进行遍历, 看看当前哪些变量是能够被访问到的

能被访问到的遍历就称为是 "可达" (否则就是 "不可达")


🦖 3.3.2 具体是怎么回收的 (标记清除/复制算法/标记整理/分代回收)

  1. 标记清除
  2. 复制算法
  3. 标记整理
  4. 分代回收

(1) 标记清除

这种方式有一个最大的问题: 内存碎片

会导致整个内存 "支离破碎"

比如假设上述每个深色的区域是 1k,此时整个有 4k 空闲空间,但是由于此时内存是分散的,导致如果想申请 2k 的内存空间,是申请不了的

(2) 复制算法

复制算法,可以很好的解决 标记清除 带来的 内存碎片问题

但是 复制算法 的缺点是:

  1. 空间利用率更低了 (用一半丢一半)
  2. 如果一轮 GC 过去,大部分对象要保留,只有少部分对象要回收,此时这个复制的开销就很大了

(3) 标记整理

类似于 顺序表 删除元素,   标记整理主要就是  搬运操作

这个方式,相对于上述的复制算法来说,空间利用率比之前高,同时也还是能够解决内存碎片问题,但是搬运操作是比较耗时的

(4) 分代回收

上面的三种方式,都是很非常好的方法,都有各自的特点

所以就需要根据实际的场景,选择对应的解决方法

这就有了 "分代回收" 的策略, 就是把上面的方法都综合在一起

根据对象不同的特点,采取不同的回收方式

这里的根据对象不同的特点: 是根据对象的年龄(依据 GC 的轮次来算的)来划分的

有一组线程,周期性的扫描代码中所有的对象,如果一个对象,经历了一次 GC 没有被回收,就认为年龄 +1

根据对象的年龄进行分类,把堆中的对象分为了,

新生代(年龄小的对象)    和    老年代 (年龄大的对象)

但是还有个特殊情况就是

如果对象是一个非常大的对象,则直接进入老年代

因为对一个大的对象进行复制算法,开销太大了

并且这是一个比较大的对象, 既然能创建这么大的对象,那肯定也不是立即就销毁的 

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

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

相关文章

图像的OTSU阈值化、双阈值化、半阈值化的原理及OpenCV代码实现

本文的基础是OpenCV的函数threshold(),关于函数threshold()的详细介绍,大家可以参考下面这篇博文: https://www.hhai.cc/thread-162-1-1.html 一、图像的OTSU阈值化 在阈值化处理中,OTSU是一种常用的算法,中文译为大津…

JavaEE-多线程初阶2

✏️作者:银河罐头 📋系列专栏:JavaEE 🌲“种一棵树最好的时间是十年前,其次是现在” 目录Thread类及常见方法获取当前线程引用休眠当前线程线程的状态线程的所有状态线程状态多线程的意义多线程带来的的风险-线程安全…

Python课程设计题目

文章目录1.基于Python的XX管理系统。2.基于Python的XX工具开发1.基于Python的XX管理系统。 实例要求:采用面向对象或是字典保存实例的属性信息。 功能要求:提供增加,删除,修改,单个查询,查询所有&#xff…

NFC标签 “ PN29_S

产品参数产品参数 产品型号 PN29_S 产品尺寸 (mm) 9546.45.4 显示技术 E ink 显示区域 (mm) 29(H)66.9(V) 分辨率 (像素) 296128 像素尺寸(mm) 0.2270.226 显示颜色 黑/白 视觉角度 180 工作温度 0℃ - 50℃ 电池 无需电池 工作频率 13.56 MHZ NF…

数据结构单循环链表

循环链表的特点是无须增加存储量,仅对表的链接方式稍作改变,即可使得表处理更加方便灵活。 【例】在链表上实现将两个线性表(a1,a2,…,an)和(b1,b2,…,bm)连接成一个线性表(a1&…

智云通CRM:那些令你无法控制的销售局面(一)

销售的复杂性并不仅仅是指购买者得人数很多。复杂销售的定义在最近的十年里有了突破性的变化和发展,这种变化和发展中出现了很多挑战,不仅业务员,就连业务经理都难以应对。因此,唯有制定简化处理程序的计划才能妥善应对这一局面。…

利用if语句求解成绩等级问题

1 问题 成绩进行划分等级,人工划分容易出错,且数量庞大。 2 方法 public class Text06 { public static void main(String[] args) { int score100; System.out.println("score"); // 1.成绩大于等于85 if (sc…

前端_Vue_4.类与样式绑定、条件渲染

文章目录一、Class与Style绑定1.1. 绑定HTML class1.1.1. 绑定对象1.1.2. 绑定数组1.1.3. 在组件上使用1.2. 绑定内联样式1.2.1. 绑定对象1.2.2. 绑定数组1.2.3. 自动前缀1.2.4. 样式多值二、条件渲染2.1. v-if2.2. v-else2.3. v-else-if2.4. \<template\> 上的 v-if2.5.…

电脑开不了机系统应该如何恢复正常

电脑不仅携带方便&#xff0c;而且功能也十分强大&#xff0c;不过电脑使用时会时不时出现问题&#xff0c;如果电脑开不了机怎么办 怎么回事?这是我们经常会遇到的这种的问题&#xff0c;今天小编就和大家分享电脑开不了机了的原因及解决方法。 工具/原料&#xff1a; 系统…

outlook中抄送操作和163撤回邮件

(1)CC和BCC 电子邮件中的CC 英文全称是 Carbon Copy(抄送)。 电子邮件中的BCC英文全称是 Blind Carbon Copy(暗抄送)。 两者的区别在于在BCC栏中的收件人可以看到所有的收件人名(TO&#xff0c;CC&#xff0c;BCC)&#xff0c;而在TO和CC栏中的收件人看不到BBC的收件人名。 …

Android 代码混淆Proguard

混淆概念 Android代码混淆&#xff0c;又称Android混淆&#xff0c;是伴随着Android系统的流行而产生的一种APP保护技术&#xff0c;用于保护APP不被破解和逆向分析。 在Android的具体表现就是打包时&#xff0c;将项目里的包名、类名、变量名根据混淆规则进行更改&#xff0c…

【POJ No. 1743】音乐主题 Musical Theme

【POJ No. 1743】音乐主题 Musical Theme 北大OJ 题目地址 【题意】音乐旋律被表示为N &#xff08;1≤N ≤20000&#xff09;个音符的序列&#xff0c;它们是[1, 88]内的整数&#xff0c;每个音符都代表钢琴上的一个键。许多作曲家都围绕一个重复的主题谱写音乐&#xff0c;该…

建木HA部署

背景 在建木v2.6.1之前&#xff0c;建木Server仅支持单机部署&#xff0c;如果出现单机故障&#xff0c;难以应用于在线场景&#xff0c;并且单机压力过大时&#xff0c;会影响系统延展性。 什么是HA HA&#xff08;High Availability Cluster&#xff09;是高可用集群系统的…

【软件测试】开发人员不鸟自己?看看资深测试如何做的......

目录&#xff1a;导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09;前言 测试人员经常抱怨开…

jsp+servlet+mysql实现的新闻发布管理系统源码+运行教程+文档

今天给大家演示一下一款由jsp servlet mysql实现的新闻发布管理系统&#xff0c;主要实现了前台游客浏览新闻、评论新闻&#xff0c;后台管理员管理新闻等功能&#xff0c;新闻有热点新闻、最新更新等方式在首页展示&#xff0c;还有幻灯片展示重大新闻等功能&#xff0c;满足了…

一招解决开发环境问题——远程容器开发指南

前言 使用C作为主要开发语言的程序猿们应该会认同搭建开发环境是一件烦人的事情。为了编译一个程序不仅需要下载各种依赖包&#xff0c;还可能面临本地系统不兼容、编译器版本不一致、包版本冲突等各种问题。笔者在运营iLogtail开源社区的过程中发现开发和调试环境问题也是成员…

web网页设计期末课程大作业——HTML+CSS+JavaScript美食餐饮文化主题网站设计与实现

&#x1f468;‍&#x1f393;静态网站的编写主要是用HTML DIVCSS JS等来完成页面的排版设计&#x1f469;‍&#x1f393;,常用的网页设计软件有Dreamweaver、EditPlus、HBuilderX、VScode 、Webstorm、Animate等等&#xff0c;用的最多的还是DW&#xff0c;当然不同软件写出的…

为云原生插上翅膀,天翼云弹性存储CStor-CSI助力容器腾飞

云原生是一种新型技术体系&#xff0c;已成为云计算未来的发展方向&#xff0c;越来越多的数字化项目与云原生紧密相连。作为云原生的基座&#xff0c;容器是必不可少的核心技术。然而&#xff0c;以Docker为代表的容器引擎&#xff0c;并不能满足大批量的容器业务需求&#xf…

推荐一套yyds的Java学习资料(非常经典)

Java 是全球最受欢迎的编程语言之一&#xff0c;在世界编程语言排行榜 TIOBE 中&#xff0c;Java 一直霸占着前三名&#xff0c;有好多年甚至都是第一名。 最近几年&#xff0c;全球约有 1/3 的专业程序员将 Java 作为主要编程语言&#xff0c;这一比例在我国更是高达 1/2&…

CTFSHOW web入门 java反序列化篇 web855

web855 得到源码后看到readObject里面有两条路可以走 1、写文件&#xff0c;文件名固定&#xff0c;文件内容开头固定后面内容可以通过write写入 2、执行命令&#xff0c;但是shellcodoe是不可控的&#xff08;static&#xff09; 如果两条路分开来看都没啥可利用的价值&…