JVM–基础篇

虚拟机的组成

  • 编译器 把程序员编写的代码转化成字节码文件
  • 类加载器 把字节码文件加载到运行时数据区
  • 执行引擎(垃圾回收器、及时编译器、解释器
  • 本地方法

字节码文件

字节码文件就是.class文件

文件组成:文件头(判断文件类型)、属性、常量、静态变量

i++/++i istore

类的生命周期

编译、加载、检查、链接、初始化???

final修饰的附上初值

在什么时候会初始化?

类的回收(垃圾回收机制

类加载器

启动类加载器

应用程序加载器

版本

双亲委派机制

如何打破双亲委派机制:自定义加载器???

优缺点:避免重复加载,安全///

场景

运行时数据区

一个线程 分配一个栈

私有区

  • 虚拟机栈
  • 本地方法栈

对象 常量池 字符串常量池

方法区

xxxx

直接内存

什么时候申请直接内存

释放

程序计数器

私有

垃圾回收

java是自动垃圾回收

方法区回收

一般不需要回收。JSP等技术会通过回收类加载器去回收方法区中的类。

堆内存的回收

  • 引用技术法

xxx

  • 可达性分析法
软引用

常用于缓存,若内存不足,会先回收软引用

软引用的使用于回收???

SoftReference提供了一套队列机制

–>也看了好几遍 创建的软引用的引用放到 集合里面 不让回收, 内存被回收的放到队列里,使用的时候得去集合遍历 不为空的才可用

–>这里的意思是如果堆内存不够,会把软引用的空间释放掉,但是软引用这个对象你还没释放,如果用置null的方式,如果没回收那就搞错了

–>Java提供一个机制,就是构造软引用的时候传一个队列进去,当哪个软引用空间被释放的时候,就会把引用对象放进队列,这时候可以通过队列元素置null来实现释放

队列总结:软引用空间置null,队列对象置null

软引用的使用场景-缓存

如果软引用对象被回收那么这个对象k-v的hashcode也应该被回收

软引用总结

软引用相对于强引用是一种比较弱的引用关系,如果一个对象只有软引用关联到它,当程序内存不足时就会将软引用的数据进行回收

弱引用

一般不使用,与软引用基本一致。回收也要用队列

与软引用的差别:不管内存够不够都要回收!!

虚引用和终结器引用
  • 开发中不会使用
  • 虚引用:释放申请的直接内存
  • 终结器引用:一个对象被回收时 放在队列里 后执行finalize方法,第二次被回收时才会真正被回收(绑定强引用自救???
强引用

最常见的方式。通过可达性算法来判断。

  • 垃圾回收算法

1.找到存活对象

2.回收不再存活的对象

标记-清除算法 两个阶段。第一阶段从GCRoot对象开始使用可达性分析法遍历 第二阶段就是删除(每个要维护一个标志为 缺点:内存碎片+分配速度慢(要遍历空闲链表,容易不满足要求而遍历到最后

复制算法 堆空间=From+To 每次分配对象只能使用其中一块 1.将GCRoot和GCRoot关联的对象搬运到To 然后清除From 互换空间名字 优点:吞吐高+无碎片化 缺点:内存利用低

标记-整理算法:标记后将存活的移动到一起,然后再清理 优点:无碎片化+内存利用率高 缺点:整理慢,遍历次数多(整理算法)

分代GC:Young区(Eden+S0+S1) + Old区 伊甸区:对象刚出生的时候放的地方 Y区指存活时间短的对象

 -XX:+UserSeialGC//手动指定垃圾回收器
memory  //arthas命令
-xms  //堆最小>1mb
-xmx  //堆最大 >2mb
-xmm  //新生代的大小(老年代可计算)
-XX:SurvivorRatio //Eden与(S1+S0)的比例

–>对象回收执行流程:伊甸园要满的时候MinorGC/Young GC==》回收的回收,余下的放在S1 执行复制算法 s1与s0 to与from==》互换再执行复制算法 最后对象到了s0 gc一次年龄+1,最大年龄15==》晋升老年代 ==》老年代又满了(年轻代满了也minorGC不了,也会放入老年代)先尝试minor GC 还是不足 触发Full GC(stw) ==》 还是不足out of memory异常

–>为什么分代!有些很快就会被回收+老年代存长期存活的(bean)+新生代<<老年代

–>优点:可以设置比例+两代可以设置不同的垃圾回收算法+基本不用FullGC而是minorGC stw减少

*STW:停滞的过程 GC线程有部分阶段需要停止所有的用户线程 所以STW越短越好 一个场景,用户在下单刚好遇到程序垃圾回收导致下单失败

回收算法评判标准

1.吞吐量(执行用户代码时间/cpu总执行时间)越高,垃圾回收效率越高。

2.最大暂停时间 越小越好

3.堆使用效率 标记清除算法优于复制算法 前者可用堆大

*三种不能兼得 堆越大 暂停时间越长 减少暂停时间会降低吞吐量

*不同的场景下,使用不同的垃圾回收算法

垃圾回收器

垃圾回收器的组合关系 3种组合关系、G1

  • 组合1
年轻代-Seria

特点:单线程 复制算法

优点:单CPU吞吐量出色

缺点:多CPU就不行了

老年代-SeriaOld

标记整理算法

其余同上

  • 组合2
年轻代-ParNew

特点:多线程 复制算法

缺点:吞吐量和停顿时间不如G1

老年代-CMS

特点:标记-清除算法 关注暂停时间-可以并行
缺点:内存碎片问题+退化(内存不足)+浮动垃圾(并发清理阶段)吞吐量会下降
适用:大系统 高请求

步骤:初始标记+并发标记+重新标记+并发清理

  • 组合3
年轻代-Parallel Scavenge

特点:复制算法

优点:吞吐量高 动态调参

缺点:不能保证单次停顿时间

场景:后台任务 大数据大文件处理

允许用户设置最大暂停时间

老年代-P O

特点:标记-整理算法

优点:并发,高效率,多核CPU

缺点:暂停时间长

场景:与P C配套使用

在使用组合3的时候最好不设置堆内存的最大值 会动态调整

  • G1

G1之前内存是连续的。而G1是零散分布开来的,每个单位区称之为Region范围是1~32m。(画外音:有端联想>闪闪的儿科医生 头骨塑形手术术式 对头骨进行切割后的样子

Region:eden+old+survivor三个区 区域不是连续的

流程:新创建的在eden区 阈值60% 产生YoungGC(会记录耗时)、标记E和S区存活的、将存活的放在新的S区,年龄+1、后续再发生YoungGC就再搬运、多次搬运>=15会放入old区

*若一个对象大小>1/2(region)直接放入老年代的Humongous

若总共到达阈值45% 触发MixedGC

混合回收流程:初始标记、并发标记、最终标记、并发清理

与CMS不一样!!!!

  • 初始标记 标记GCRoots引用的对象为存活
  • 并发标记 第一次标记的对象引用的对象
  • 最终标记 不同之处(只标记漏掉的标记,不管新创建的,不再关联的对象(比CMS快
  • 并发复制清理 复制 没有内存碎片

选择存活率低的区域回收 G1

没有空区域用来复制 清理就会出现Full GC 单线程编辑-整理算法影响效率 要避免这种情况出现

jdk9之后建议使用G1 jdk8之前不成熟

优点:延迟可控、没有内存碎片、并发标记算法效率高SATB优于CMS

适用于较大的堆


评论

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

Translate »