内存结构

程序计数器

  • 如果线程正在执行一个Java方法,则这个计数器记录的正在执行虚拟机字节码指令的地址;如果正在执行的是Native方法,则这个计数器的值为空(Undefined)

  • 线程私有

  • 不会存在内存溢出

Java虚拟机栈

  • 每个线程运行时所需要的内存,称为虚拟机栈
  • 每个栈由多个栈帧组成,对应着每次方法调用时所占用的内存
  • 每个线程只能有一个活动栈帧,对应着当前正在执行的那个方法

方法内局部变量是否安全:

  • 如果方法内局部变量没有逃离方法的作用范围,它是线程安全的
  • 如果是局部变量引用了对象,并逃离方法的作用范围,需要考虑线程安全

本地方法栈

  • 通过new创建的对象会使用堆内存
  • 线程共享,需要考虑线程安全
  • 有垃圾回收机制
  • jps
    • 查看当前系统中有哪些Java进程
  • jmap
    • 查看堆内存使用情况jmap -heap id
  • jconsole
    • 图形界面
  • jvisualvm

方法区

  • 线程共享

  • 存储和类相关的信息

  • 1.8前会导致永久代内存溢出,后会导致元空间内存溢出

    image-20230313153945250

常量池

  • 常量池就是一张表,虚拟机根据这张常量表找到要执行的类名、方法名、类型参数、字面量等信息
  • 运行时常量池,常量池是*.class文件中的,当该类被加载时,它的常量池信息就会放入运行时常量池,并发里面的符号地址变为真实地址

垃圾回收

判断对象可以回收

  • 引用计数法

  • 可达性分析算法

  • 四种引用

    • 强引用
    • 软引用
    • 弱引用
    • 虚引用

回收算法

  1. 标记清除
    • 会造成内存碎片
  2. 标记整理
    • 整理效率较低
  3. 复制
    • 占用双倍的内存空间

分代的垃圾回收

  • 新生代

    • 伊甸园
    • 幸存区from
    • 幸存区to
  • 老年代

image-20230315153338333

  • minor gc会触发STW,暂停其它用户的线程,等垃圾回收结束后,用户才恢复运行

  • 当对象寿命超过阈值时,会晋升到老年代,最大寿命是15(4bit)

  • 当老年代空间不足会先尝试触发minor gc,如果之后空间仍然不足,那么触发full gc,STW时间更长

VM相关参数

image-20230315153947578

垃圾回收器

串行

  • 单线程
  • 堆内存较小,适合个人电脑

吞吐量优先

  • 多线程
  • 堆内存较大,多核CPU
  • 让单位时间内STW的时间最短

响应时间优先

  • 多线程
  • 堆内存大,多核CPU
  • 尽可能让STW的时间最短

image-20230315170154330

G1

类加载

类加载的时机

image-20230316131902320