1:当我们写的java文件经过编译器编译后生成class文件。class文件里面包含了各种java语言规范的特定语法。可以通过javap -v -private xxx.class
例如:
javap -v -private Gas.class
Classfile /D:/project/ike-springboot-carbonzero-v2/springboot-bms-api/target/classes/ike/cz/bms/importGas/Gas.classLast modified 2024-1-26; size 2598 bytesMD5 checksum ade0f6bf4e5a00e0845d157d728f4cdaCompiled from "Gas.java"
public class ike.cz.bms.importGas.Gasminor version: 0major version: 61flags: ACC_PUBLIC, ACC_SUPER
Constant pool:#1 = Methodref #2.#3 // java/lang/Object."<init>":()V#2 = Class #4 // java/lang/Object
..........
2:由jvm的类加载器,负责将这些class文件进行加载。
加载通过父类双亲委派机制,(向上查找,向下加载。)jvm的类加载器由:Bootstrap ClassLoader(负责加载JAVA_HOME中jre/lib/rt.jar里所有的class
) =>Extension ClassLoader(JAVA_HO ME中jre/lib/*.jar或-Djava.ext.dirs指定目录下的jar包
) =>App ClassLoader(加载classpath中指定的jar包及目录中class
) => Custom ClassLoader(用户自定义的ClassLoader
)。
父类双亲委派机制:(先去看自己缓存有没有这个class,如果没有则向上委托查找。)
首先会看Custom ClassLoader中的缓存中是否存在,如果不存在,则向上父类的App ClassLoader加载,如果App ClassLoader缓存里没有,则向Extension ClassLoader加载,如果Extension ClassLoader缓存里没有,则Bootstrap ClassLoader加载,然后Bootstrap ClassLoader先看缓存里有没。没有则让子类进行加载,一直找,找不到则报 类找不到异常(class not found exception)。
3:加载完成后,由运行期系统进行解释执行
。解释
:(包括字节码解释器:(一条一条地读取,解释并且执行字节码指令),即时编译器:(把整段字节码不加筛选的编译成机器码不论其执行频率是否有编译价值,在程序响应时间的限制下,没有达
到最大的优化。),jvm通常采用混合模式,结合两者优点进行
),执行
:jvm会先把解释后的进行执行。
执行就会涉及到jvm内存模型:用于存放不同的数据。
jvm内存模型
:线程独享区
(程序计数器,本地方法栈,虚拟机栈)和线程共享区
(方法区,java堆)
程序计数器
:用于存储下一条指令的地址,用于程序逻辑控制,线程交替执行。并且唯一一个不会oom的地方。
虚拟机栈
:栈帧,存放在局部变量
,操作数栈
,动态链接,方法出口。每一个方法的调用过程就是一个栈帧再虚拟机栈中入栈到出栈的过程
调优参数:-Xss
1024m,g,kb。(单位选择m,g,kb),如果StackOverflowError,可能为循环调用深度太深导致(这个会涉及到压栈和出栈)。建议检查代码的合理性
本地方法栈
:与虚拟机栈相似,但是只服务于本地(Native) 方法服务。
java堆
:存放对象实例,和数组。垃圾回收发生的地方。堆
里面分为(新生代
分为(eden,s0,s1),老年代
),调优参数有:-Xms
6m:设置堆的初始大小为6
m,-Xmx
6m:堆最大内存值为6m。-Xms
和-Xmx
通常设置为相同。-Xmn
:年轻代大小
方法区
:存放类信息,常量,接口方法字段等
以下为GC相关学习记录:
STW
时间 : (“Stop The World”)垃圾回收时暂停用户线程
的时间。
JDK1.8默认
使用使用的垃圾回收器
:
年轻代
使用:Parallel
Scavenge又称Parallel。
1.年轻代使用复制算法、并行回收、STW机制。
2.吞吐量可控制。
3.拥有自适应调节策略(能够根据程序需求自动分配内存空间)。
4.回收年轻代的并行垃圾回收器。
年老代使用Parallel Old
作用在老年代,和Parallel配合使用 采用标记-压缩算法、并行回收、STW机制
如何判断一个对象是否应该被回收?
判断一个对象是否可达,不可达对象就将被回收,所谓可达就是从
GCROOT
开始是否是可以找到该对象 GCROOT是什么?
1、虚拟机栈中引用的对象(本地变量表)
2、方法区中静态属性引用的对象
3、方法区中常量引用的对象
4、本地方法栈中引用的对象(Native Object)
GC类型:
Eden内存空间进行清理的GC我们称之为Minor GC
2.Old区的GC我们称作为Major GC
3.新生代(Minor GC)+老年代(Major GC) Full GC
堆内存空间:分为年轻代
和老年代
,年轻代gc+老年代gc = full gc
新生代(Young)与老年代的比例值为 1:2(该值可以通过参数 -XX:NewRatio来指定)。
年轻代分为:Eden区,s0,s1区:Minor GC也称(Young GC)发生的地方,采用复制清理算法
1.Eden区(伊甸园,新生命初创的地方):对象刚刚创建的地方,当Eden快满时采用
复制清理
算法触发Minor GC也称(Young GC),把不会清楚的对象复制到S0区或者S1区。然后删除Eden区+s0或者s1区
,并且每次会对幸存的对象进行+1操作。
2.s0和s1区:当s0或者s1区快满了,并且当超过某个次数后(默认15-XX:MaxTenuringThreshold
”来设置),就把s0或者s1区的对象放入老年代。
3.假如说当前放对象的Survivor区域里,一批对象的总大小大于了这块Survivor区域的内存大小的50%,
那么此时大于等于这批对象年龄的最大值对象,就可以直接进入老年代了
4.年轻代分为了Eden,s0,s1。默认比值为:8:1:1(可以通过参数-XX:SurvivorRatio
来设定)。
老年代 Major GC,采用标记清除和标记整理算法。
垃圾进入老年代的触发条件
1.当s0或者s1区快满了,并且当超过某个次数后(默认15
-XX:MaxTenuringThreshold
”来设置),就把s0或者s1区的对象放入老年代。
2.假如说当前放对象的Survivor区域里,一批对象的总大小大于了这块Survivor区域的内存大小的50%,
3.大对象直接进入老年代
4.Minor GC后的对象太多
Minor GC后的对象太多无法放入Survivor区 这个时候就必须得把这些对象直接转移到老年代去
GC垃圾回收算法:
标记清除:先标记垃圾对象,后清除。
内存碎片化严重
。
复制清除:内存分为两部分:存活对象放一边,回收对象放一边。然后回收。内存使用率低
标记整理:先标记,然后存活的对象都向一端移动,然后直接清理掉端边界以外的内存,这种算法可以有效地减少内存碎片,提高内存的利用率。。如下图:
垃圾回收器
是这些GC垃圾回收算法
的执行者。
垃圾回收器的分类
根据线程的数量来分:
单线程(串行)垃圾回收器 :Serial、Serial Old;
多线程(并行)垃圾回收器:Parnew、Parallel Scavenge、Parallel Old
根据工作内存来分:
新生代垃圾回收器:Serial、Parnew、Parallel Scavenge;
老年代垃圾回收器:Serial Old、Parallel Old、CMS。
根据工作模式分:
独占式垃圾回收器:Serial、Parnew、Parallel Scavenge;
并发式垃圾回收器:CMS、G1。
HotSpot垃圾回收器
图中展示了 7 种作用于不同分代的收集器,如果两个收集器之间存在连线, 则说明它们可以搭配使用。虚拟机所处的区域则表示它是属于新生代还是老年代收集器。
CMS垃圾回收器
CMS基于标记清除算法
,因此会产生内存碎片,当大作业到来时,可能会提前触发Full GC。
标记整理算法是需要移动对象的,但是CMS在清理垃圾的时候是与用户线程并发执行的。其他两个是采用了标记整理算法
的