7.怎么判断对象是否可以被回收
一般有两种方法来判断:
引用计数器:
所谓引用计数法就是给每一个对象设置一个引用计数器,每当有一个地方引用这个对象 时,就将计数器+1,引用失效时,计数器就-1。当一个对象的引用计数器为0时,说明此对象没有被引 用,也就是“死对象”,将会被垃圾回收. 引用计数法有一个缺陷就是无法解决循环引用问题,也就是说当对象 A 引用对象 B,对象B 又引用者对 象 A,那么此时 A,B 对象的引用计数器都不为零,也就造成无法完成垃圾回收,所以主流的虚拟机都没 有采用这种算法。
可达性分析:
该算法的思想是:从一个被称为 GC Roots的对象开始向下搜索,如果一个对象到 GCRoots 没有任何引用链相连时,则说明此对象不可用。 在 java 中可以作为 GC Roots 的对象有以下几种: 虚拟机栈中引用的对象 方法区类静态属性引用的对象 方法区常量池引用的对象 本地方法栈 JNI 引用的对象 虽然这些算法可以判定一个对象是否能被回收,但是当满足上述条件时,一个对象比不一定会被回收。
当一个对象不可达 GC Root 时,这个对象并不会立马被回收,而是出于一个死缓的阶段,若要被真正 的回收需要经历两次标记 如果对象在可达性分析中没有与 GC Root 的引用链,那么此时就会被第一次标记并且进行一次筛选, 筛选的条件是是否有必要执行 finalize()方法。当对象没有覆盖 finalize()方法或者已被虚拟机调用过,那 么就认为是没必要的。
如果该对象有必要执行 finalize()方法,那么这个对象将会放在一个称为 F-Queue 的对队列中,虚拟机 会触发一个 Finalize()线程去执行,此线程是低优先级的,并且虚拟机不会承诺一直等待它运行完,这 是因为如果 finalize() 执行缓慢或者发生了死锁,那么就会造成 FQueue 队列一直等待,造成了内存 回收系统的崩溃。GC 对处于 F-Queue 中的对象进行第二次被标记,这时,该对象将被移除”即将回收” 集合,等待回收。
8.java中都有哪些引用类型
强引用:默认声明的就是强引用,不会被垃圾回收被强引用的对象
软引用:用来描述一些非必须但仍有用的对象,除非内存不够,否则不会回收被软引用的对象
弱引用:无论内存是否足够,只要开始回收,那么被弱引用的对象都会被回收
虚引用(幽灵引用/幻影引用):就像没有任何引用一样,随时会被回收
9.说一下jvm有哪些垃圾回收算法
1. 标记-清除算法
定义:实现最简单的一种算法,用于在新生代中标记所有的不可用对象并且进行清除,最后保留可用 对象。清理效率高且实现容易,
缺点:会产生大量的内存碎片.通常用升级版:标记-整理算法
实现步骤:
1.标记所有的存活对象,执行垃圾回收的时候,
2.清理掉所有的垃圾对象,保留存活对象。
3.清理完成,残余大量的内存碎片空间。
2. 标记-整理算法
定义:是对标记-清除算法的改进,主要是在标记-清除后增加了一部整理的操作。它比标记-清除算法 要复杂很多,性能和效率也不高,所以通常作为老年代的算法使用。
实现步骤:
1.标记所有的存活对象,执行垃圾回收的时候,
2.清理掉所有的垃圾对象,保留存活对象。
3.将存活对象挪到一起,减少内存碎片。
3. 复制优化算法
定义:是新生代常用的回收算法,用在新生代中,把新生代划分为一个eden区和两个survivor区,当 eden区满了之后,就会把上一次的survivor1区和eden区的存活对象放到另一个survivor2区中,然后 清理掉该eden和survior1区中的垃圾对象,这样做可以保证每一次都会有一个survivor区是空着的,复 制后的内存空间比较规整,不会出现大量的内存碎片,而且清理效率也很高。
10.说一下jvm有哪些垃圾回收器
Serial:最早的单线程串行垃圾回收器。
Serial Old:Serial 垃圾回收器的老年版本,同样也是单线程的,可以作为 CMS 垃圾回收器的 备 选预案。
ParNew:是 Serial 的多线程版本。
Parallel 和 ParNew 收集器类似是多线程的,但 Parallel 是吞吐量优先的收集器,可以牺牲等 待 时间换取系统的吞吐量。
Parallel Old 是 Parallel 老生代版本,Parallel 使用的是复制的内存回收算法,Parallel Old 使用 的是标记-整理的内存回收算法。
CMS:一种以获得最短停顿时间为目标的收集器,非常适用 B/S 系统。
G1:一种兼顾吞吐量和停顿时间的 GC 实现,是 JDK 9 以后的默认 GC 选项。
(1)介绍一下CMS垃圾回收器
CMS,以牺牲吞吐量为代价来获得最短回收停顿时间的垃圾回收器。对于要求服务器响应速度的应用 上,这种垃圾回收器非常适合。在启动JVM的参数加上“-XX:+UseConcMarkSweepGC”来指定使用 CMS 垃圾回收器 CMS使用的是标记-清除算法实现的,所以在GC的时候会产生大量的内存碎片,当剩余内存不能满足程 序运行要求时,系统就会出现 Concurrent Mode Failure ,临时CMS会采用Serial Old回收器进行垃圾 回收,此时的性能会被降低。
(2)新生代和老年代垃圾回收器分别有哪些?有什么区别
1. 新生代:Serial、ParNew、Parallel Scavenge
2. 老年代:Serial Old、Parallel Old、CMS
3. 整堆回收器:G1 新生代垃圾回收器一般采用的是复制算法,效率高,内存利用率低;老年代回收器一般采用的是标记整理的算法进行垃圾回收,效率低,内存利用率高。
11.简述分代垃圾回收器是怎么工作的
分代回收器有两个分区:老生代和新生代,新生代默认的空间占比总空间的 1/3,老生代的默认占比是 2/3。
1. 在新生代使用复制算法(Minor GC): 新生代里有 3 个分区: Eden 、 To Survivor 、 From Survivor ,它们的默认占 比是 8:1:1,它 的执行流程如下:
1. 当eden区满了之后,会将上一次from区的存活对象和eden区存活对象放入to区
2. 清空eden区和from区
3. from区和to区进行交换,在这个过程中一定有一个surivor区为空 4. 每次在 From Survivor 到 To Survivor 移动时都存活的对象,年龄就 +1,当年龄到达 15(默认配置是 15)时,升级为老生代。大对象也会直接进入老生代。
2. 在老年代使用标记整理算法(Full GC):
1. 在老年代中标记所有的对象
2. 在垃圾回收时,清理所有垃圾对象,保留存活对象
3. 将存活对象整理到一起,减少内存碎片 这样循环往复就构成了分代垃圾回收的执行流程
12.说一下jvm的调优工具
java自带的常用调优工具有:JDK 自带了很多监控工具,都位于 JDK 的 bin 目录下,其中最常用的是 jconsole 和 jvisualvm 这两 款视图监控工具。
jconsole:用于对JVM中的内存、线程和类等进行监控
jvisualvm:JDK自带的全能分析工具,可以分析:内存快照、线程快照、程序死锁、监控内存的变 化、GC变化等。
13.说一下常用的jvm调优参数
-Xms2g:初始化堆大小为2g
-Xmx2g:堆最大内存为2g
-XX:NewRatio=4:设置年轻代和老年代的比例为1:4
-XX:SurvivorRatio=8:设置新生代Eden和Survivor的比例为8:2
-XX:+UserParNewGC:指定使用ParNew+Serial Old垃圾回收器组合
-XX:+UserParallelOldGC:指定使用ParNew+ParNew Old垃圾回收器组合
-XX:+UserConcMarkSweepGC:指定使用CMS+Serial Old垃圾回收器组合
-XX:+PrintGC:开启打印GC信息
-XX:+PrintGCDetils:打印GC详细信息