[个人笔记] JVM

1. 虚拟机运行时数据区

jvm运行时数据区包括堆,方法区,虚拟机栈,本地方法栈,程序计数器,其中堆和方法区是共享区,栈和程序计数器/本地方法栈区是归JVM的
在这里插入图片描述

程序计数器
内存空间小,通过改变这个计数器的值来选取下一条需要执行指令的字节码指令
虚拟机栈
生命周期和线程一致。描述的是java方法执行的内存模型:每个方法在执行的时候都会创建一个栈帧用于存储局部变量表(存放编译期可知的各种基本类型,对象引用和return address的类型,指向了一条字节码指令的地址),操作数栈,动态链接,方法出口等信息。
本地方法栈
虚拟机栈为了虚拟机执行java方法服务,而本地方法栈则为了虚拟机使用到的native方法服务
java堆
大多数应用这个区域是jvm管理内存中最大的一块,线程共享,主要是存放对象实例和数组
方法区
存储已经被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据

java之所以能够一次编译处处运行的原因就是java屏蔽了很多的操作系统平台相关信息,只需要生成在jvm虚拟机运行的目标代码也就是所说的字节码就可以在多种平台运行

2. 类加载器:

主要负责加载class文件,是否执行主要取决于execution engine,负责执行被加载类中包含的指令

2.1 类的加载机制

类的生命周期一共分为5个阶段,
加载
主要完成3件事件,1.通过类的全限定名来获取定义此类的二进制字节流,2.将这个类字节流代表的静态存储结构转为方法区的运行时数据结构,3.在堆中生成一个代表此类的java.lang.Class对象,作为访问方法区这些数据结构的入口。这个过程主要是类加载器完成的。
连接
这个过程分3个阶段(校验,准备,解析)完成。首先是校验,此阶段主要校验class文件包含的信息是否符合jvm的规范。具体的校验通过对文件格式,元数据,字节码,符号引用验证来完成。然后是准备,此阶段为类变量分配内存,并将其初始化为默认值。最后是解析,即把类型中的符号引用转换成为直接引用。具体的解析有4种,1.类或接口的解析,2.字段解析,3.类方法解析,4.接口方法解析。完成这3个阶段就完成了类的连接。
初始化
即执行类的构造器方法的过程。有5种方法可以完成初始化:1.调用new方法,2.使用Class类的newInstance方法(反射机制),3.使用Constructor类的newInstance方法(反射机制),4.使用Clone方法创建对象,5.使用(反)序列化机制创建对象
使用
完成类的初始化后,就可以对类进行实例化,在程序中进行使用了
卸载
当类被加载,连接和初始化后,它的生命周期就始了,当代表类的class对象不在被引用时,class对象就会结束生命周期,类在方法区内的数据就会被卸载。因此一个类何时结束生命,取决于代表它的class对象何时结束生命。

3. 垃圾回收机制

3.1 判断对象是否已死

引用计数法:给对象添加一个引用计数器,不能解决循环引用的问题
可达性分析:通过一系列GC roots的对象作为起始点,从这些节点所走过的路径称为引用链,当一个对象到GC roots没有任何引用链相连的时候说明对象不可用
可以作为GC roots的对象:

虚拟机栈(栈帧中的本地变量表)中引用的对象
方法区中类静态属性引用的对象
方法区中常量引用的对象
本地方法栈中 JNI(即一般说的 Native 方法) 引用的对象

3.2 堆的分类

java堆从GC的角度可以细分为:新生代(Eden 区、From Survivor 区和 To Survivor 区)和老年代。
在这里插入图片描述

3.2.1 新生代

是用来存放新生的对象。一般占据堆的 1/3 空间。由于频繁创建对象,所以新生代会频繁触发MinorGC 进行垃圾回收。新生代又分为 Eden 区、ServivorFrom、ServivorTo 三个区。
Eden 区
Java 新对象的出生地(如果新创建的对象占用内存很大,则直接分配到老年代)。当 Eden 区内存不够的时候就会触发 MinorGC,对新生代区进行一次垃圾回收。
ServivorFrom
上一次 GC 的幸存者,作为这一次 GC 的被扫描者。
ServivorTo
保留了一次 MinorGC 过程中的幸存者。
MinorGC 的过程(复制->清空->互换)
MinorGC 采用复制算法

1:把 Eden 和 ServivorFrom 区域中存活的对象复制到 ServicorTo 区域(如果有对象的年龄以及达到了老年的标准,则赋值到老年代区),同时把这些对象的年龄+1(如果 ServicorTo 不够位置了就放到老年区);
2:清空 Eden 和 ServicorFrom 中的对象;
3:ServicorTo 和 ServicorFrom 互换 原 ServicorTo 成为下一次 GC 时的 ServicorFrom区。

3.3 垃圾回收算法

标记清除算法
效率不高,空间会产生大量的碎片
复制算法
把空间分成两块,每次只对其中一块进行GC。这个内存使用完之后,还存活着的对象就复制到另一块上
空间利用率低下
标记整理
把存活着的对象移到内存的一端
分代回收
新生代:每次垃圾回收都有大量的对象死去,只有少量存活,使用复制算法
老年代:对象存活率比较高,没有额外的空间分配对它进行担保,使用标记-清除或者标记-整理算法回收

3.4 java四种引用类型

强引用
在 Java 中最常见的就是强引用,把一个对象赋给一个引用变量,这个引用变量就是一个强引用。当一个对象被强引用变量引用时,它处于可达状态,它是不可能被垃圾回收机制回收的,即使该对象以后永远都不会被用到 JVM 也不会回收。因此强引用是造成 Java 内存泄漏的主要原因之一
软引用
软引用需要用 SoftReference 类来实现,对于只有软引用的对象来说,当系统内存足够时它不会被回收,当系统内存空间不足时它会被回收。软引用通常用在对内存敏感的程序中。
弱引用
弱引用需要用 WeakReference 类来实现,它比软引用的生存期更短,对于只有弱引用的对象来说,只要垃圾回收机制一运行,不管 JVM 的内存空间是否足够,总会回收该对象占用的内存。
虚引用
虚引用需要 PhantomReference 类来实现,它不能单独使用,必须和引用队列联合使用。虚引用的主要作用是跟踪对象被垃圾回收的状态。

3.5 垃圾收集器

hotspot中垃圾收集器
在这里插入图片描述

serial垃圾收集器(单线程,复制算法)

最基本的垃圾收集器,是一个单线程的收集器,它不但只会使用一个 CPU 或一条线程去完成垃圾收集工作,并且在进行垃圾收集的同时,必须暂停其他所有的工作线程,直到垃圾收集结束。
Serial 垃圾收集器虽然在收集垃圾过程中需要暂停所有其他的工作线程,但是它简单高效,对于限定单个 CPU 环境来说,没有线程交互的开销,可以获得最高的单线程垃圾收集效率,因此 Serial垃圾收集器依然是 java 虚拟机运行在 Client 模式下默认的新生代垃圾收集器。

ParNew 垃圾收集器(Serial+多线程)

ParNew 垃圾收集器其实是 Serial 收集器的多线程版本,也使用复制算法,除了使用多线程进行垃圾收集之外,其余的行为和 Serial 收集器完全一样,ParNew 垃圾收集器在垃圾收集过程中同样也要暂停所有其他的工作线程。
ParNew 收集器默认开启和 CPU 数目相同的线程数,可以通过-XX:ParallelGCThreads 参数来限制垃圾收集器的线程数。【Parallel:平行的】
ParNew虽然是除了多线程外和Serial 收集器几乎完全一样,但是ParNew垃圾收集器是很多 java虚拟机运行在 Server 模式下新生代的默认垃圾收集器。

Parallel Scavenge 收集器(多线程复制算法、高效)

Parallel Scavenge 收集器也是一个新生代垃圾收集器,同样使用复制算法,也是一个多线程的垃圾收集器,它重点关注的是程序达到一个可控制的吞吐量(Thoughput,CPU 用于运行用户代码的时间/CPU 总消耗时间,即吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间)),高吞吐量可以最高效率地利用 CPU 时间,尽快地完成程序的运算任务,主要适用于在后台运算而不需要太多交互的任务。自适应调节策略也是 ParallelScavenge 收集器与 ParNew 收集器的一个重要区别。

Serial Old 收集器(单线程标记整理算法 )

Serial Old 是 Serial 垃圾收集器年老代版本,它同样是个单线程的收集器,使用标记-整理算法,这个收集器也主要是运行在 Client 默认的 java 虚拟机默认的年老代垃圾收集器。
在 Server 模式下,主要有两个用途:

  1. 在 JDK1.5 之前版本中与新生代的 Parallel Scavenge 收集器搭配使用。
  2. 作为年老代中使用 CMS 收集器的后备垃圾收集方案。

Parallel Old 收集器(多线程标记整理算法)

Parallel Old 收集器是Parallel Scavenge的年老代版本,使用多线程的标记-整理算法,在 JDK1.6才开始提供。

CMS 收集器(多线程标记清除算法)

Concurrent mark sweep(CMS)收集器是一种年老代垃圾收集器,其最主要目标是获取最短垃圾回收停顿时间,和其他年老代使用标记-整理算法不同,它使用多线程的标记-清除算法。
最短的垃圾收集停顿时间可以为交互比较高的程序提高用户体验。

G1 收集器

Garbage first 垃圾收集器是目前垃圾收集器理论发展的最前沿成果,相比与 CMS 收集器,G1 收集器两个最突出的改进是:

  1. 基于标记-整理算法,不产生内存碎片。
  2. 可以非常精确控制停顿时间,在不牺牲吞吐量前提下,实现低停顿垃圾回收。

G1 收集器避免全区域垃圾收集,它把堆内存划分为大小固定的几个独立区域,并且跟踪这些区域的垃圾收集进度,同时在后台维护一个优先级列表,每次根据所允许的收集时间,优先回收垃圾最多的区域。区域划分和优先级区域回收机制,确保 G1 收集器可以在有限时间获得最高的垃圾收集效率。
GC触发条件

  1. minorgc触发条件:属于新生代gc,在eden内存不够的时候触发
  2. fullgc触发条件:调用system.gc的时候,系统建议执行fullgc,但是不是必然执行;;方法区空间不足;老年代空间不足:
    通过Minor GC后进入老年代的平均大小大于老年代的可用内存;
    由Eden区、From Space区向To Space区复制时,对象大小大于To Space可用内存,则把该对象转存到老年代,且老年代的可用内存小于该对象大小。

新生代对象升入老年代
每躲过一次GC,年龄+1,年龄=15时升入老年代;
由Eden区、From Space区向To Space区复制时,对象大小大于To Space可用内存,则把该对象转存到老年代。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值