什么是jvm
java虚拟机,保证java跨平台的核心
jre和jdk的区别:
jdk包含jre,jre包含虚拟机jvm,jre是java运行环境,而jdk是java开发工具包
优化jvm:
所谓优化就是配置一些参数,让jvm运行时使用这些参数,让jvm运行的程序更优
jdk自带工具 VisualVM ,在jdk目录下bin下面,还有jconsole
通过使用 Java本地接口书写程序,可以确保代码在不同的平台
上方便移植
jvm大致分成以下组件:
1.类加载器子系统
2.运行时数据区
3.执行引擎
4,本地方法库
java用类加载器来进行类加载
每一个类,都需要和它的类加载器一起确定其在jvm中的唯一性
类加载的过程:
类加载的过程包括了加载、验证、准备、解析和初始化五个步骤
类加载器:都遵循双亲委派机制
启动类加载器
|
扩展类加载器
|
应用程序类加载器
|
自定义类加载器
其中,启动类加载器负责加载java_home/lib下的
扩展类加载器负责加载java_home/lib/ext下的
应用程序加载器负责加载classpath下的
双亲委派机制:我们的程序本来要通过应用类加载器来加载,但不会优先加载,会先委托给自己的父亲
(扩展类加载器),他的父亲在委托给启动类加载器,也就是委托给他的两个亲人,所以叫双亲委派,优先
委托使用爷爷加载,没有再没加载到就用父亲加载,如果在没有加载到,就自己加载。
意义:1.防止我们轻易覆盖系统提供功能
2.也让我们扩展自己的功能
运行时方法区:jdk1.7
jdk1.8
运行时数据区分为程序计数器,虚拟机栈,本地方法栈,堆区,方法区(元数据区)
java虚拟机栈:
java虚拟机栈也是线程私有的,每个普通方法执行都会创建一个栈帧,局部变量就放在栈帧中
本地方法栈:
用来执行本地库接口,第三方方法调用的
通过使用 Java本地接口书写程序,可以确保代码在不同的平台
上方便移植
堆内存:
堆是一个所有线程共享,存放对象的区域,也是GC的主要区域。
堆内存主要用于存放对象和数组,他是jvm管理的内存中最大的一块区域,堆内存和方法区(jdk1.8后
取消)都被所有线程共享,在虚拟机启动时创建。在垃圾收集的层面上来看,由于现在收集器基本都采用
分代收集算法,因此堆还分为新生代和老年代
gc:
分代收集算法 Generational Collection
根据对象存活周期的不同将内存划分为几块。
新生代:大批对象死去,少量存活,使用复制算法
老年代:对象存活率高,没有额外空间进行分配担保,使用 标记清除或者标记压缩算法
次数上频繁收集Young区
较少收集Old区
基本不动Perm区
gc收集四个算法:
1,引用计数算法 基本不用
2,复制算法: 新生代中使用的是Minor GC,这种GC算法采用的是复制算法
原理:
从根集合 GC Root开始,通过Tracing从Survive From中找到存货对象,拷贝到Survive To中
From、To交换身份,下次内存从To开始,重复复制的操作
优点:
没有标记和清除的过程,效率高
没有内存碎片,可以利用bump-the-pointer实现快速内存分配
缺点:需要双倍空间.
3,标记清除 Mark-Sweep
原理:
标记 Mark,从跟集合开始扫描,对存活的对象进行标记
清楚 Sweep,扫描整个空间,回收未被标记的对象,使用free-list记录可以区域
优点:
不需要两倍的内存
缺点:
需要扫描两次,耗时严重,效率低
在进行GC时,需要停止应用程序,会导致用户体验差
内存不连续,会产生内存碎片,需要存入大容量对象时,不得不再次进行GC.
4,标记压缩 Mark-Compact / 标记整理
原理:
标记 Mark,与标记清除一样
压缩 Compact,再次扫描,并往一端滑动存活对象
缺点:
效率不高,不仅要标记所有粗诺对象,还要整理所有存活对象的引用地址,效率要低于复制算法.
5,标记清除压缩 Mark-Sweep-Compact 老年代一般使用标记清除或者标记清除与标记整理混合实现
原理:
Mark-Sweep和Mark-Compact的结合
和Mark-Sweep一致,当进行多次GC后才Compact.
内存效率对比:
复制算法>标记清除算法>标记压缩算法(此处的效率只是对比时间复杂度,不是真是情况)
内存整齐度 复制算法=标记压缩算法>标记清除算法