元空间:从jdk1.8开始的叫法,其实就是以前的方法区;但是和方法区也有区别;方法区的数据保存在JVM内存中,元空间的数据保存在物理磁盘上;
.Java文件转换成.class文件,通过类加载子系统 加载到内存中去(方法区),所有的代码都在元空间
- 类加载子系统:将所有的.class文件数据加载到元空间,以方便运行调用;
- 程序执行引擎:执行代码,并会将执行到的代码的行数记录到程序计数器中
- 程序计数器:记录当前代码运行到了哪一行
- 本地方法栈:服务于本地(native)方法的本地方法内存的所有局部变量都保存到本地方法栈中,其内部结构和栈相同,都是为调用的方法分配栈帧区域,该方法内部的局部变量保存在这个栈帧中
- 栈:叫虚拟机栈或者线程栈,即会为每个线程分配一个区域,在该线程内部调用方法时,会在该区域中为方法开辟一块栈帧区域,方法的内部的局部变量都保存在该栈帧区域中
- 堆:存放对象
堆:
内部结构JDK1.8:
采取分代思想,堆中分为年轻代和老年代
年轻代:老年代=1:2;
老年代保存的对象:
1.创建时太大的对象会直接保存到年老代中
2.从年轻代中产生,年代数达到15的对象
年轻代:
Eden区(伊甸园区):新创建的任何对象都在这里
经过GC清理过后仍幸存的对象存在幸存者区
当伊甸园区内存不足时会触发minnor gc,当伊甸园区出发GC之前会通过可达性分析算法得到当前使用的对象,会把使用的对象复制到s区,随机一个,俩个不是同时开启的,进去之后年代数增1,minnor gc会把伊甸园区和另一个s区清空;在运行在产生新对象,以此类推,就是这个迭代循环过程,当s区的年代数达到15时(一般不容易),会把它存放到老年代中,这个对象即将长久存在
年轻代工作原理总结:
新创建的对象会保存在Eden区,当Eden区内存不足时,会触发minnor gc,会对整个年轻代进行回收,再回收之前,会使用可达性分析算法,从栈开始,标记所有正在使用的对象,将使用的对象保存到s0区,然后堆Eden和s1区进行回收,保存到s区的对象年代数会加1.后续若再次Eden内存不足时,将正在使用的对象会存入到另一个s(s1)区,然后对Eden和s0进行回收,当对象的年代数达到15,会移入年老代中
s(suvivor 幸存者)0区:
s(suvivor 幸存者)1区:
伊甸园区:s0:s1=8:1:1
老年代:
老年代中保存到的对象和年代数达到15的对象,当老年代内存不足时,会触发full gc,会堆整个堆内存进行回收,且会造成STW(stop the world),用户会有卡顿体验,若频繁的触发full gc,用户的体验非常差,此时就需要进行JVM优化
注: minor gc和full gc都会出发STW,但是minor gc回收内存小,所以造成的卡顿几乎感觉不到,所以minor gc触发频发频率可以高,但是full gc是对整个堆内存的回收,造成的卡顿用户感觉很明显,所以尽可能的减少full gc 触发;
栈:
mian栈帧:
int i=1;
int b=4;
change(i,b);
........
change()
int a=1;
int b=2;
int c=a+b;
再点class文件中运行:
为mian线程分配的栈空间:
栈帧内部的四块区域
- 局部变量表:保存我们一直一直知道的局部变量,包括他的数据
- 操作数栈:保存的是中间过程可能涉及到的任何操作数;任何操作数如果要取都得出栈,如果 产 生 都得进行入栈操作
- 动态链接:所有方法上的代码都是保存到元空间的,保存一行行的数据;保存当前方法在元空间的地址,如果别人想调用,来动态链接一看,就可以去元空间查找
- 方法出口: 保存当前方法执行结束要返回原来方法的某个行号,它会保存其他每个方法的行号(程序器技术器调用),保存的是字节码中的行号
JVM调优措施:
1.尽可能减少大对象的产生
------------操作文件时,尽可能多次操作
2.尽可能让对象在年轻代在年轻代被回收走
-------------尽可能的扩大年轻代的大小
- 直接扩大堆内存大小
- 调整年轻代的比例
------可以调整Eden和俩个s区的比例
--------调整年轻代和老年代的比例(慎用)
3.更换GMSGC为G1GC
JVM堆内存的大小调整
永久代:元空间,并不存在于堆
GC的分类:
SerialGC:单线程
ParalleGC: 并发情况下作用的GC
ConcMarkSweepGC:并发情况下作用的GC
------JDK1.5开始默认提供的
G1GC: 从JDK1.9开始默认提供的
G1GC回收机制:
有一个后台线程记录当前回收利用率最高的块,将其作为最优先回收的块,当内存不足时,
对该块进行回收,若回收后够用,则不再继续回收,大大降低STW的时间
注意:每个块在下次使用时作为不同的去使用
Gc垃圾回收机制常用算法:
- 复制算法----minor gc使用
- 标记---清除算法 特点:回收后的内存不连续,内存利用率低
- 标记---整理算法 ---回收后将使用的对象进行整理,然后将可利用的内存整理到一起,实现内存连续