JVM
1、JDK与JRE
JDK:全称Java Development Kit Java开发工具箱,由Java程序设计语言,Java虚拟机,Java API三部分组成
JRE:全称Java Runtime Environment Java运行环境,由Java SE API,Java虚拟机组成
可见JRE是JDK的子集
2、Java未来的发展方向
多语言混合编程,多核并行
3、JVM运行时数据区(JVM内存模型)
线程私有
- 程序计数器:获取下一条程序指令,唯一没有规定内存溢出异常
- 虚拟机栈:每个方法执行时都会创建一个栈帧
- 本地方法栈:为本地方法服务
线程共享
- Java堆:存储所有的对象实例
- 方法区:存储类信息,常量池
4、内存泄漏与内存溢出的区别
内存泄漏:失去引用的对象,但又没有得到正确的清理
内存溢出:没有足够的内存来满足申请,内存泄漏可能导致内存溢出
5、如何判断对象可以被回收
- 引用计数器法:为每个对象引用计数,引用为零则回收,但此方法很难解决循环引用的问题
- 可达性分析:是否有从GC ROOTS到对象的一条路径。
常见的GCROOTS:方法区中的静态或常量引用的对象,栈帧本地变量表引用的对象。
如何判断对象已经死亡:判断死亡需要两次标记,第一次标记清除没有重写finalize()的对象,将重写finalize()方法的对象加入队列;第二次标记队列中
的对象进行清除。
6、Java中的引用类型
引用类型都有对应的实现类
- 强引用:new
- 软引用:内存不够了进行回收
- 弱引用:活不过下一次垃圾回收
- 虚引用:唯一的目的是在垃圾回收时得到一个系统通知
7、垃圾回收算法
- 标记—清除:效率不高,且会产生内存碎片
- 复制算法:将空间一分为二,适合用于有很多朝生夕死的对象,即新生代算法(新生代存活的少)
- 标记—整理:直接将存活对象向一端移
- 分代算法:新生代使用复制算法,老年代使用标记清除或者标记整理算法
8、垃圾收集器
Serial:新生代单线程垃圾回收器,简单高效
Serial Old:老年代单线程垃圾回收器
ParNew:Serial的多线程版本
Parallel Scavenge:多线程,目标在于提高系统吞吐量
Parallel Old:老年代
CMS:并行垃圾回收,目标就是获得最短的停顿时间,通过设置参数合并整理内存碎片
G1:并行并发缩短停顿时间,一个收集器收集新生代与老年代
9、频繁gc的原因
①看看参数设置是否合理,能不能调大
②程序中有没有大而短命的对象
③增大老年代空间
10、内存分配策略
- 对象优先在Eden上分配,Eden与Survivor8:1
- 大对象直接进入老年代
- 存活久的对象移入老年代
11、调优的工具
命令行工具
jps:进程状况工具
jstat:统计信息监视工具
jinfo:配置信息工具
jmap:内存映像工具
jhat:堆转储快照分析
jstack:堆栈跟踪
HSDIS:反汇编工具
可视化工具
JConsole:对虚拟机内存,线程,类进行监控
VisualVM:对内存快照,线程快照,内存死锁进行分析
12、常用的调优参数
-Xms2g:设置堆的初始大小为2g
-Xmx2g:设置堆的最大大小为2g
-Xmn1g:设置新生代大小
-XX:NewRatio=4:老年代与新生代4:1
-XX:SurvivorRatio=8:Eden:Survivor = 8:2
-XX:+UseParNewGC:使用ParNew+Serial Old
-XX:+UseParallelOldGC:使用Parallel + Parallel Old
-XX:+UseConcMarkSweepGC:使用Serial + CMS + Serial Old
-XX:+PrintGC:打印GC信息
-XX:+PrintGCDetails:打印GC详细信息
13、类加载的过程
①加载:根据全限定类名加载器class文件
②验证:检查class文件是否可以被正确的解析
③准备:为类变量设置初始值0,静态常量设置本来的值
④解析:将符号引用(方法字段的相关描述)解析为直接引用(即地址)
⑤初始化:执行类变量语句,和静态代码块,这时候类变量才有真正的初值
14、双亲委派模型
由类同类加载器在虚拟机中确定这个类的唯一性。
按照层次分为,启动类加载器,扩展类加载器,应用类加载器,用户自定义类加载器
每收到一个请求类加载器都会先委托其上层类加载器完成,若加载失败在有本层加载器加载,这样便可以保证Object类在各种加载环境中都是同一个类。