JVM基础知识整理

JVM

1.java运行时数据区域

堆:线程共享,主要存放对象实例和数组,内部会划分出多个线程私有的分配缓冲区

虚拟机栈:线程私有,生命周期和线程一致。描述的是java执行方法的内存模型:每个方法在执行时都会创建一个栈帧用于存储:局部变量表、操作数栈、动态链接、方法出口等信息,每一个方法从执行到结束就对应着一个栈帧在虚拟机中从入栈到出栈的过程

注:局部变量表存储基本类型数据(byte、int、short、long、float、double、char、boolean)、对象的引用

本地方法栈:为虚拟机使用到的native方法服务

方法区:属于共享内存区域,存放着已经被虚拟机加载的类信息、常量、局部变量、即时编译器编译后的代码等数据。

程序计数器:内存空间小、线程私有。字节码解释器就是通过改变这个计数器的值来选取吓一跳需要执行的字节码指令。分支、循环、跳转、异常处理、线程恢复等基础功能都是通过程序计数器来实现。

2.垃圾回收策略

2.1 回收算法

2.1.1按照基本回收策略

引用计数:比较古老的回收算法。原理是对象有一个引用则增加一个计数,删除一个引用则减少一个计数。垃圾回收时只回收计数为0的对象。此算法的问题是无法处理循环引用。

标记-清除:此算法执行分为两段。第一阶段从引用根节点开始标记所有被引用的对象,第二阶段,遍历整个堆,把未标记的对象清除。此算法会暂停整个应用,同时会产生大量内存碎片

在这里插入图片描述

copy算法:此算法把内存空间划分为两个相等的区域,每次只是用其中的一片区域。垃圾回收时,遍历当前是用的区域,把正在使用的对象复制到另一片区域。算法每次只处理正在使用中的对象,所以复制成本比较小,同时复制过去后还能进行内存整理,不会出现碎片问题。此算法的缺点就是需要两倍的内存空间

在这里插入图片描述

标记-整理:此算法执行同样是分为两段,第一阶段从引用根节点开始标记所有被引用的对象,第二阶段,遍历整个堆,清除未标记的对象同时把堆中存活的对象压缩到堆的一边,按顺序排列。此算法避免了标记清除的碎片问题,同时也避免的复制算法的空间问题。

在这里插入图片描述

分代回收算法:

引用根节点包括(CG Roots):
1.虚拟接栈中引用的对象
2.方法区中静态属性引用的对象
3.方法区中常量引用的对象
4.本地方法栈中引用的对象
2.1.2 按照分区对待的方式

增量收集:实时垃圾回收算法,即:在应用进行的同时进行垃圾回收

分代回收算法:基于对象生命周期分析后得出的垃圾回收算法。把对象分为年轻代、老年代、持久代,对不同生命周期的对象采用不同的基本回收策略。现在的垃圾回收器都是使用这种算法

2.1.3 按照系统线程

串行收集:使用单线程处理所有的垃圾回收工作,因为无需短线成交互,容易实现、且效率比较高。局限性也比较明显,无法使用多处理器的优势,所以此收集方式适合单处理器机器,或者小数据量(100M左右)的多处理器机器

并行收集:使用多线程处理垃圾回收工作,因而速度快、效率高、切理论上CPU数目越多,越能体现并行收集器的优势

并发收集:相对于串行收集和并行收集,前两者在垃圾回收时需要暂停整个运行环境,只有垃圾回收程序在运行,因此系统在进行垃圾回收时会有明显的暂停,而且暂停时间会随着堆越大而越长

2.2 判断对象是否为垃圾的方法

1.引用计数器:给对象添加一个引用计数器,但是无法解决循环的问题

2.可达性分析法:从所有的CG Roots 对象作为起点,从这些节点出发所有的路径成为引用链。当一个对象到CG Roots没有任何的引用链时,说明对象没有被引用可以作为垃圾回收。

可达性分析算法未标记到的对象也并非真正的死亡,一个对象的真正死亡至少要经历两次标记过程。第一次标记时会对对象进行筛选,筛选条件是此对象是否有必要执行finalize()方法,当对象没有覆盖finalize()方法,或者finalize()方法已被虚拟机调用过,虚拟机将这两种情况都视为没有必要执行;如果对象被判断有必要执行finalize()方法,那么这个对象会被放置在一个叫做F-Queue的队列中,并在稍后由虚拟机自动创建的、低优先级的Finzlize线程去执行它,这里的执行是指虚拟机会触发这个方法,稍后GC会对F-Queue队列中的对象进行第二次小规模的标记,若此时对象存在于CG Root的引用链便不会被回收了。

2.3 引用类型

强引用:声明对象时虚拟机生成的引用,强引用化境下,垃圾回收需要严格的判断当前对象是否被强引用,如果被强引用则不会被回收。

软引用:软引用一般会作为缓存来使用。软引用在垃圾回收时,虚拟机会根据当前系统的剩余内存来判断是否对软引用进行回收,如果剩余内存比较紧张,虚拟机会回收软引用所引用的空间,如果剩余内存比较富裕,则不会进行回收。虚拟机在发生OutOfMemory时,是肯定没有软引用的。

弱引用:与软引用一样一般作为缓存来使用,不一样的是垃圾回收时弱引用会被直接全部回收

虚引用:无法通过虚引用来获取一个对象实例,为对象设置虚引用关联的唯一目的就是为了使对象在被收集器回收时,能收到一个系统通知。

2.4 分代回收算法

2.4.1 优点

不同对象的生命周期是不一样的,因此不同生命周期的对象可以使用不同的回收算法从而提高效率

2.4.2 如何分代

虚拟机中共划分为三个代:年轻代、老年代、持久代。其中持久代主要存放java类的类信息,与垃圾收集关系并不大。年轻代和老年代的划分对垃圾收集的影响比较大。

年轻代:所有新生成的对象首先都是放在年轻代的,年轻代的目的就是尽可能块的回收掉生命周期短的对象。

年轻代主要分为三个区:一个eden区,两个survivor区。大部分对象在eden区生成,当eden区满时,还存活的对象将被复制到一个survivor区中,当这个survivor区满了的时候,依然存活的对象将被复制到两外一个survivor区中,默认这样来回复制(默认15次),最后存活的对象将进入老年代。

老年代:在年轻代中复制了n次仍然存活的对象进入老年代,所以可以认为老年代存放的都是一些生命周期比较长的对象

2.5 触发垃圾回收的条件

新生代GC(Minor GC): Eden区满了的时候,survivor区满了的时候,次数较多,花费时间短

老年代GC(Major GC/ full GC) : 花费时间长,尽量减少full GC次数

1.老年代被写满

2.持久代被写满

3.System.gc()被调用

4.上一次GC后堆的各域分配策略动态变化

2.6垃圾回收器

serial收集器:串行收集器是最古老,最稳定效率高的收集器,但可能会产生较长时间的停顿,使用一个线程去回收。

ParNew收集器:serial收集器的多线程版~~~

Paraller收集器:并行收集器

**CMS收集器:**是一种以获取最短回收停顿时间为目标的收集器。它需要消耗额外的CPU和内存资源,在CPU和资源紧张、CPU较少时会加重系统负担。CMS无法处理浮动垃圾。CMS的标记清除算法会产生大量的内存空间碎片

浮动垃圾:由于在应用运行的同时进行垃圾回收,所有有些垃圾可能会在垃圾回收结束后产生,这些垃圾就称为浮动垃圾,一般要等到下次垃圾回收时才能回收掉。所以并发收集器一般会预留20%的空间来存放这些浮动垃圾

**G1收集器:**是一款面向服务器的垃圾收集器。主要针对配备多个处理器及大容量内存的机器。以极高概率满足GC停顿时间要求的同时,还具备高吞吐量性能特征。

3.一些参数配置

-Xmx1024M:最大可用内存1024M
-Xms1024M:初始化堆内存大小为1024M,尽量和最大可用内存保持一致
-Xmn512M:年轻代大小为512M
-Xss1M:每个线程堆栈大小为1M
-XX:NewRatio=4 年轻代和老年代内存的比值为1:4 即,年轻代占对内存的1/5
-XX:SurviorRation=4 年轻代中Eden区和一个survivor区的比值为4:1 即,一个survivor区占年轻代大小的1/6
-XX:MaxPermSize=64M 设置持久代的大小为64M
-XX:+useConcMarkSweepGC 老年代使用CMS收集器
-XX:CMSFullGCBeforeCompaction=5 由于并发收集器不能对空间碎片进行压缩,此值为垃圾回收多少次后对空间进行压缩
-XX:useCMSCompactionAtFullCollection 打开老年代的空间压缩,可能会影响性能,但是可以消除空间碎片
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值