【面试 JVM】【第六篇】JVM调优
六部分内容:
一。内存模型
1.程序计数器,方法区,堆,栈,本地方法栈的作用,保存那些数据
可以画个大图出来,很清晰
jvm内存模型主要指运行时的数据区,包括5个部分。
栈也叫方法栈,是线程私有的,线程在执行每个方法时都会同时创建一个栈帧,用来存储局部变量表、操作栈、动态链接、方法出口等信息。调用方法时执行入栈,方法返回时执行出栈。
本地方法栈与栈类似,也是用来保存线程执行方法时的信息,不同的是,执行java方法使用栈,而执行native方法使用本地方法栈。
程序计数器保存着当前线程所执行的字节码位置,每个线程工作时都有一个独立的计数器。程序计数器为执行java方法服务,执行native方法时,程序计数器为空。
栈、本地方法栈、程序计数器这三个部分都是线程独占的。
堆是jvm管理的内存中最大的一块,堆被所有线程共享,目的是为了存放对象实例,几乎所有的对象实例都在这里分配。当堆内存没有可用的空间时,会抛出OOM异常。根据对象存活的周期不同,jvm把堆内存进行分代管理,由垃圾回收器来进行对象的回收管理。
方法区也是各个线程共享的内存区域,又叫非堆区。用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据,
jdk1.7中的永久代和1.8中的metaspace都是方法区的一种实现。
面试回答此知识点相关问题时,要答出两个要点:一个是各部分的功能,另一个是哪些线程共享,哪些独占。
二。类加载机制
1.双亲委派的加载机制
2.常用类加载器以及作用
3.双亲委派加载机制好处
4.如何判断是同一个class
三。GC垃圾回收
1.分代回收的思想和依据
java堆内存被分代管理,主要是为了方便垃圾回收。
因为,第一,大部分对象很快就不使用了
第二,有一部分不会立即无用,但也不会持续很长的时间!
所以堆内存进行分代管理的划分!
2.不同垃圾回收算法实现的思路以及适用的场景
按类型分为3种:
引用计数法:通过对象被引用的次数来确定对象是否被使用,缺点无法解决循环引用的问题!
复制算法:需要from和to两块大小相同的内存空间。对象分配只在from块,回收时把存活对象复制到to块,清空from,然后调换职权!from变成to,to变成from!缺点,内存使用率低!
标记清除算法:分为标记对象和清除不再使用的对象 两个阶段! 缺点,会产生内存碎片!
jvm中,年轻代回收算法serial、parNew、parallel scavenge都是复制算法!
CMS、G1、zgc都属于标记清除算法!
四。性能调优
1.常用jvm优化参数的作用
2.参数调优的依据
3.了解常用的jvm分析工具能分析哪类问题,以及使用方法
五。执行模式
1.解释,编译,混合模式的优缺点
2.了解java7提供的分层编译技术
3.知道JIT即时编译技术和OSR栈上替换
4.知道C1,C2编译器针对的场景,其中C2针对server模式,优化更激进
5.java10提供的由java实现的graal编译器
六。编译优化
1.前端编译器javac的编译过程
2.AST抽象语法书
3.编译期优化
4.运行期优化
5.编译优化的常用技术
包括公共子表达式的消除,方法内联,逃逸分析,栈上分配,同步消除等!明白了这些,才能写出对编译器友好的代码!
1.JVM内存模型
- Java堆:线程共享的,唯一目的就是用于存放对象实例,是垃圾收集器管理的主要区域;
- Java虚拟机栈:线程私有的,每个方法在执行的同时都会创建一个栈帧用于存储局部变量等,局部变量表存放了编译器可知的各种基本数据类型和对象引用;
- 本地方法栈:和虚拟机栈类似,不过它是为Native方法服务;
- 程序计数器:线程私有的,可以看作是当前线程所执行的字节码的行号指示器,以便线程切换后恢复执行使用;
- 方法区:线程共享的,用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据;该区域的内存回收主要是针对常量池的回收和类型的卸载(特别是要注意一些动态字节码框架和自定义ClassLoader的场景下);在HotSpot里经常被称为永久代,在Java 8里已被废除了,被元空间取代;
===============================================================
2.JVM内存回收机制
1》堆内存
堆内存是所有线程共有的,可以分为两个部分:年轻代和老年代。下图中的Perm代表的是永久代,但是注意永久代并不属于堆内存中的一部分,同时jdk1.8之后永久代也将被移除。
2》垃圾回收主要作用在堆内存
3》新生代(Young Generation):用于存放新创建的对象,采用复制回收方法,如果在s0和s1之间复制一定次数后,转移到年老代中。这里的垃圾回收叫做minor GC;
4》老年代(Old Generation):这些对象垃圾回收的频率较低,采用的标记整理方法,这里的垃圾回收叫做 major GC。
拓展:1.在进行垃圾回收的时候,怎么判断哪些对象是垃圾,要被回收
通过两种方式
1》引用计数【但是引用计数的方式无法解决循环引用的问题】
2》可达性分析
拓展:2.什么叫对象可达,什么叫对象不可达,什么是可达性分析
通过一系列称为“GC Roots”的对象(比如虚拟机栈引用的对象、方法区中的类静态属性和常量引用对象)作为起点,从这些节点一直往下搜索,走过的路径称为引用链;而那些没有与引用链相连的对象即为不可达,会被回收。
拓展:3.判断对象可以回收的情况
1》对象显式的置空null
2》局部引用指向的对象
3》弱引用关联的对象
===============================================================
3.什么是GC,常用的GC算法有哪些?
1》GC就是垃圾回收机制,就是JVM对内存中的对象进行管理的一个过程
2》GC的过程如下:
1. Eden区最大,对外提供堆内存。当Eden区快要满了,则进行Minor GC,把存活对象放入Survivor A区,清空Eden区;
2. Eden区被清空后,继续对外提供堆内存;
3. 当Eden区再次被填满,此时对Eden区和Survivor A区同时进行Minor GC,把存活对象放入Survivor B区,同时清空Eden 区和Survivor A区;
4. Eden区继续对外提供堆内存,并重复上述过程,即在Eden区填满后,把Eden区和某个Survivor区的存活对象放到另一个Survivor区;
5. 当某个Survivor区被填满,且仍有对象未被复制完毕时或者某些对象在反复Survive 15次左右时,则把这部分剩余对象放到Old区;
6. 当Old区也被填满时,进行Major GC,对Old区进行垃圾回收。
3》新生代采用的GC算法是 复制算法,而老年代采用的是标记-清除算法
4》复制算法就是 eden区往s0复制,或者往s1复制的过程,默认次数15次
5》标记-清除算法 是老年区依旧在用的对象标记可可达对象 清除就是清除不可达的对象。
拓展:GC触发条件
GC类型 | 触发条件 | 触发时发生了什么 | 注意 | 查看方式 |
YGC | eden空间不足 |
清空Eden+from survivor中所有no ref的对象占用的内存 重新调整Eden 和from的大小(parallel GC会触发此项) |
全过程暂停应用 是否为多线程处理由具体的GC决定 |
jstat –gcutil gc log |
FGC |
old空间不足 |
清空heap中no ref的对象 permgen中已经被卸载的classloader中加载的class信息 如配置了CollectGenOFirst,则先触发YGC(针对serial GC) 如配置了ScavengeBeforeFullGC,则先触发YGC(针对serial GC) |
全过程暂停应用 是否为多线程处理由具体的GC决定 是否压缩需要看配置的具体G |
===============================================================
4.你是通过什么方式实现JVM优化的?
1》调整新生代、s0、s1比例以及调整新生代 老年代的大小,目的是减少GC次数
2》不要显示的调用system.GC()
3》对象不用的时候显式的置为null
4》尽量减少局部变量的使用
5》尽量使用基本数据类型而不使用封装类
6》尽量少使用静态变量,因为静态变量属于类的变量,是全局变量,会一直占用资源
7》尽量分散的创建对象,不要一次性创建多个对象。
8》https://www.cnblogs.com/sxdcgaq8080/p/10649367.html
===============================================================
5.内存溢出和内存泄漏的区别
https://www.cnblogs.com/panxuejun/p/5883044.html
===============================================================