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

导读:本篇文章讲解 JVM(内存划分+类加载+GC),希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

目录

🐲 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. 程序计数器: 放的是下一个要执行的指令的地址 

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

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


🐲 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. 解析: 初始化字符串变量,把 符号引用(占位符)  替换成 直接引用(内存地址) JVM(内存划分+类加载+GC)

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

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

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

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

使用一个类,这里指的是

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

🦄 2.4 双亲委派模型

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

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

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

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

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

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

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

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

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


🐲 3. GC 垃圾回收机制

🦄 3.1 GC 是什么

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

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

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


🦄 3.2 GC 回收哪部分内存

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

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

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


🦄 3.3 GC 具体是怎么回收的

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

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

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

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

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

所以最关键的要点就是:

通过引用来判定当

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

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

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

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

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

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

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

缺点:

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

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

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

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

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

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

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

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

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


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

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

(1) 标记清除

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

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

会导致整个内存 “支离破碎”

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

(2) 复制算法

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

但是 复制算法 的缺点是:

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

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

(3) 标记整理

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

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

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

(4) 分代回收

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

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

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

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

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

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

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

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

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

但是还有个特殊情况就是

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

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

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

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/91194.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!