JVM

Author Avatar
kevin
发表:2024-05-28 17:07:00
修改:2024-10-09 17:06:55

JVM

jvm笔记

类加载器

启动类加载器(Bootstrap):

在Java环境下看不到,核心类

扩展类加载器(Extension):

扩展功能的一些 jar 包,类似第三方

应用类加载器(AppClassLoader):

程序员自己写的类

双亲委派机制

从上到下加载

先到启动类加载器查找,找到,执行,找不到,向下查找

如果应用程序类加载器同样找不到要加载的类,那么会抛出ClassNotFoundException

  • 避免类的重复加载:父加载器加载了一个类,就不必让子加载器再去查找了。同时也保证了在整个 JVM 范围内全类名是类的唯一标识。
  • 安全机制:避免恶意替换 JRE 定义的核心 API

方法栈

方法栈并不是某一个 JVM 的内存空间,而是我们描述方法被调用过程的一个逻辑概念。

栈帧

方法在本次执行过程中所用到的局部变量,形参等信息

  • 本地变量(Local Variables):输入参数和输出参数以及方法内的变量。
  • 栈操作(Operand Stack):记录出栈、入栈的操作。
  • 栈帧数据(Frame Data):包括类文件、方法等等

栈帧的结构

方法每调用一次就生成一个栈帧

  • 局部变量表:方法执行时的参数、方法体内声明的局部变量
    • 0下标是this占用
  • 操作数栈:存储中间运算结果,是一个临时存储空间
  • 帧数据区:保存访问常量池指针,异常处理表

images

栈空间的线程私有

线程对栈内存空间的使用方式是彼此隔离的。每个线程都是在自己独享的空间内运行

某个栈溢出异常不会影响其他栈

堆空间

images

  • 新创建的对象:进入 Eden 区。
  • Eden 区的对象经过 GC 后没有被释放:进入 Survivor 区。
  • Survivor 区分成 from 区和 to 区两个部分。
  • Survivor 区在执行 GC 时:
    • 将不释放的对象从 from 区复制到 to 区。
    • 将 from 区整个标记为空闲。
    • 交换 from 和 to 这两个指针。
    • 口诀:复制必交换,谁空谁为 to。
  • 新生代中的对象默认经历 15 次 GC 后,如果还幸存,则直接进入老年代。
  • 如果幸存者区已经满了,即使某个对象尚不到 15 岁,仍然会被移动到老年代

垃圾回收

不再使用或获取不到的对象是垃圾对象。

没有引用的对象就是要清理的对象

GC 算法

内存碎片

不连续的存储空间

程序暂停(stop the world)

标记清除法

堆中的有效内存空间被耗尽的时候,就会暂停、挂起整个程序

标记:从根对象开始遍历所有的对象,然后将所有存活的对象标记为可达的对象。

清除:清除的过程将遍历堆中所有的对象,将没有标记的对象全部清除掉。

  • 优点:实现简单
  • 缺点:效率低,因为标记和清除两个动作都要遍历所有的对象
  • 垃圾收集后有可能会造成大量的内存碎片
  • 垃圾回收时会造成应用程序暂停

复制算法

将原有的内存空间一分为二,

from区和to区,to区每次都是空的

每次只用其中的一块,在垃圾回收时,将正在使用的对象复制到另一个内存空间中,并依次排列,然后将该内存空间清空,交换两个内存的角色,完成垃圾的回收。

  • 优点2:清理后,内存无碎片
  • 缺点:浪费了一半的内存空间
评论