1. 什么是GC?为什么要有GC?
GC是垃圾回收的意思,内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或者系统的不稳定甚至奔溃,java提供的GC功能可以自动监测对象是否超过作用域从而达到垃圾回收的目的,Java语言目前没有提供已分配内存的显示操作方法。
2. 谈谈你是如何优化GC的?
优化GC我们可以从减少Full GC执行时间、也可以将老年代的对象数量降低一下,还有一个就是优化JVM的参数,像堆和栈的大小,对象的重用这些。
3. Minor GC是什么?触发条件是什么?过程是怎么样的?
Minor GC 是俗称,新生代(新生代分为一个 Eden区和两个Survivor区)的垃圾收集叫做 Minor GC。
当新生代的Eden区满的时候触发 Minor GC。
当发生 Minor GC时,Eden 区和 from 指向的 Survivor 区中的存活对象会被复制(此处采用标记 - 复制算法)到 to 指向的 Survivor区中,然后交换 from 和 to指针,以保证下一次 Minor GC时,to 指向的 Survivor区还是空的。
4. FullGC是什么?触发条件是什么?
FullGC是对整个堆的收集
触发条件包括:System.gc(手动GC),老年区/永久代空间不够的时候,空间分配担保失败或者不允许空间分配担保
5. 空间分配担保是什么?
在发生minor gc之前,虚拟机会检测老年代的最大可用连续空间是否大于新生代所有对象的总空间,如果这个条件成立,则这一次minor gc是安全的,如果小于,则需要检测-XX:HandlePromotionFailure设置不需要冒险,如果为True,允许担保失败,会继续检测老年代最大可用的连续空间大于历次晋升到老年代对象的平均大小,若大于则进行一次miniro gc,若失败,则重新进行一次full gc,若为false,则不需要冒险,则要进行full gc。
6. 什么时候对象进入老年代?
长期存活的对象进入老年代,大对象直接进入老年代。
7. 如何判断对象已死?GC Roots有哪些?
引用计数算法:给对象添加一个引用计数器,每当有一个地方引用它时,计数器就增加1,当引用失效时,计数器就减1,任何时刻计算器为0的对象就是不存在被使用。存在的问题:引起循环引用。
可达性分析算法:这个算法的基本思路就是通过一系列的称为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots 没有任何引用链相连时,则证明此对象是不可用的。
GC Roots:虚拟机栈(栈帧中的本地变量表)中引用的对象,方法区中类竞态属性引用的对象,方法区中常量引用的对象,本地方法栈中JNI(即一般说的native方法)引用的对象。
8. 对象的创建过程如何?对象的内存布局如何?
当java虚拟机遇到一条字节码new指令时,JVM首先对符号引用进行解析,如果找不到对应的符号引用,那么这个类还没有被加载,因此JVM便会进行类加载过程。符号引用解析完毕之后,JVM会为对象在堆中分配内存。内存分配完成以后,还需要对对象进行必要的设置(如对象是哪个类的实例,如果才能找到类的元数据信息等等),上面工作完成以后,从虚拟机的角度来看,一个新的对象已经产生,但是从jav程序的视角来看,才刚刚开始,然后执行构造方法就行初始化,这样一个真正可用的对象才能完全的构造出来。
对象的内存布局包括对象头,实例数据,对其填充。
对象头:存储对象自身的运行时数据(如哈希表,gc分代年龄等等)和类型指针(指向它的类型元数据的指针)
实例数据:对象真正存储的有效信息,即我们在程序代码里面所定义的各种类型的字段内容,无论是从父类继承下来的,还是从子类中定义的字段,这部分受虚拟机的分配策略参数影响。
对其填充:并不是必然存在的,也没有特别的含义,仅仅起到占位符的作用。
9. 对象的访问定位是什么?
通过句柄访问对象:java堆可能划分一部分内存来作为句柄池,reference中存储的就是对象的句柄地址,而句柄中包含了对象实例数据与类型数据各自具体的地址信息。
通过直接指针访问对象:若是采用指针访问对象,则reference中存储的就是对象的地址。两种各有好处,使用句柄的好处是对象被移动只会改变句柄的示例数据指针,使用直接指针的好处是速度更快,节省了一次指针定位的时间开销,由于对象方问在java十分频繁,所以HotSpot虚拟机采用此方法。
10. 说一下强引用,软引用,弱引用,虚引用 ?
强引用:强引用是最传统的“引用”定义,是指在程序代码之中普遍存在的引用赋值,无论在任何情况下,只要强引用关系存在,垃圾回收器就永远不会回收掉被引用的对象。
软引用:是用来描述一些还有用,但非必须的对象,只被软引用关联的对象,在系统将要发生内存溢出异常之前,会把这些对象进行二次回收,如果这次回收还没有足够的内存,才会抛出内存溢出异常。
弱引用:弱引用关联的对象只能生存到下一次垃圾收集发生为止。
虚引用:被称为幽灵引用或者幻影引用,不会对其生存时间构成影响,也无法通过虚引用来获得一个对象的实例,为一个对象设置虚引用关联的唯一目的是为了能在这个对象被垃圾回收器回收之前收到一个系统通知。
11. 垃圾回收算法有哪些?
分代收集理论:将java堆划分不同的区域,然后将对象依据其年龄分配到不同的区域中存储。
标记清除:首先标记所有需要回收的对象,在标记完成后统一回收所有被标记的对象。
缺点包括两个,一个是效率问题,清除和标记两个过程效率都不太高,另一个是清楚之后会有大量不连续的空间碎片,空间碎片太多导致加载较大对象时候,不能不提前触发垃圾回收。‘
标记复制:它将内存容量分为大小相等的两块,每次使用其中的一块,当这一块内存用完了,就将还存活的所有对象复制到另一块上去,然后将这块内存空间一次清除。
优点:内存分配不用考虑内存碎片问题,实现简单,运行高效。缺点:内存只有总内存的一半,代价太高。
标记清除整理:标记过程与标记复制算法一样,但后续不是直接将对象进行清除,而是让所有对象都向一段移动,然后直接清理掉端以外的内存。
12. 垃圾的回收器有哪些?
Serial收集器:新生代、老年代串行回收,新生代标记复制,老年代标记-整理。
ParNew收集器:新生代并行复制,老年代并行标记-整理。
Paraller Scavenge收集器:标记复制的新生代收集器,主要为了提高吞吐量可以用两个参数精准控制,-XX:MaxGCPauseMillis可以控制最大的垃圾收集停顿时间。-XX:GCTimeRation是直接控制吞吐量大小。
Serial Old收集器:Serial的老年代收集器。
Parnew old收集器:Parnew的老年代收集器。
CMS收集器:CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器。整个过程包括,初始标记,并发标记,重新标记,并发清除。
-XX:+UseConcMarkSweepGC 使用CMS收集器
-XX:+CMSFullGCsBeforeCompaction:进行几次Full GC以后进行一次碎片整理
-XX:ParallelCMSThreads:设定CMS线程数量
优点:并发收集,低停顿。
缺点:对CPU资源非常敏感,无法处理浮动垃圾,标记清除导致的空间碎片。
G1收集器:G1会跟踪各个Region里面的垃圾堆积的价值大小(回收所获得的空间大小以及回收所需时间的经验值),在后台维护一个优先列表,每次根据允许的收集时间,优先回收价值最大的Region(这也就是Garbage-First名称的来由)。
13. JVM性能监控工具有哪些?
Jps:可以列出正在运行的虚拟机进程。
Jinfo:可以实时的查看和调整虚拟机的各项参数。
Jhat:虚拟机堆转储快照分析工具。
Jconsole:java监视与管理控制台。
VisualVM:多合一故障处理工具。