JVM
2021-08-11 15:35:35 0 举报
登录查看完整内容
JVM原理
作者其他创作
大纲/内容
线程共享
将代码优化编译
类加载--解析过程
解析
网络等途径
应用加载器其他class
4核8G服务器JVM传统GC配置(可依据实际情况进行调优)“-Xms4096M -Xmx4096M -Xmn3072M -Xss1M -XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=256M -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFaction=92 -XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=0 -XX:+CMSParallelInitialMarkEnabled -XX:+CMSScavengeBeforeRemark -XX:+DisableExplicitGC -XX:+PrintGCDetails -Xloggc:gc.log -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/usr/local/app/oom”JVMG1配置(主要针对-XX:MaxGCPauseMills(默认200ms)进行调优)“-Xms4096M -Xmx4096M -Xss1M -XX:PermSize=256M -XX:MaxPermSize=256M -XX:+UseG1GC“
初始化
其他语法糖处理
加载
不论是年轻代还是老年代都是基于标记复制的算法。年轻代GC:年轻代GC并不只是一直创建对象到60%阈值之后,然后一次性GC,达到阈值之后会进行minorGC。但是还会依据设置的暂停时间来动态GC,默认200ms。若G1评估某些区域回收时间接近这个暂停时间了,就会去触发一次minorGC。所以,GC时机是还是基于所期望的暂停时间的。老年代GC:老年代GC当空间大于阈值45%时,就会触发mixedGC,具体步骤类似CMS,先初始标记,再并发标记,再最终标记,再mixedGC。区别就在最后一步mixedGC。mixedGC不仅回收老年代还会回收年轻代,也是依据期望暂停时间自动选择回收区域。若回收空间依旧不满足空间,则会使用单线程标记清除整理回收。
javac编译器
元数据区(1.8之后替代方法区,直接内存)存放元数据信息,每个类的运行时常量池,class文件编码等生命周期与加载器相同
字符串常量池
分配内存:普通对象分配到eden的region区域,大对象分配到大对象专属region(某些大对象可能会占据多个region)对象晋升:达到GC年龄就会放入老年代region,包含参数配置和动态年龄(年龄占内存大小超过survivor的50%,则自动晋升),对象太大也会直接晋升。内存角色交换:一块区域回收清除后变空闲,可以分配给其他角色,比如老年代。GC后的survivor的region可能角色变成了eden,再分配新的region给survivor
可达性分析:通过GCRoots开始往下遍历,若不可达则回收。GCRoots包含虚拟机栈中变量,以及堆中静态变量
文件IO
双亲委派加载所有class的加载都会先将加载请求给父级加载器加载,如果父类加载不了,才会自己加载。作用:确保同一个类只会被加载一次。避免被串改核心类
何时回收?
G1回收器逻辑
复制清除:标记存活的对象,拷贝到新的空闲区域,然后清除原对象区域标记清除:标记已死亡的对象,然后执行清除(容易产生内存碎片,需要定期整理)标记整理:先标记所有存活的对象,转移到内存的一端,然后将分界点之外所有对象全部清除按老年代和年轻代进行分代收集,不同区域可针对使用垃圾回收算法。
如何回收?
class文件
代码热部署以及模块化热部署等
即时编译
虚拟机栈
泛型类型擦除
栈帧1
启动加载器jdk的lib
内存运作
三层加载模型
栈帧2:局部变量操作数栈动态链接方法出口……
tomcat类加载(同应用间的隔离)
自定义加载器
方法区(1.8之后不存在)运行字符串常量池,1.7转移到了堆中class对象,1.7转移到了堆中(元数据区的内容)
加载、验证、准备、初始化和卸载这五个阶段的开始顺序是确定的,实际执行可能交错
回收哪些?
网络IO
本地服务接口(如数据库连接等)服务,在rt包中,由启动加载器加载,但是需要调用具体实现,启动加载器无法加载这部分,所以只能是将启动加载器放到线程上下文中传递过去加载。
java文件
使用
GC运行原理
本地方法栈
类或接口解析:如果不是数组,则加载其class。如果是数组,则先加载其class,再在内存生成一个数组class对象。校验访问权限。
将所有堆区域默认分为2048个region区域,每个region区域大小相同。内存分为:空闲区域,年轻代eden,年轻代survivor*2,老年代region,大对象region。但是每个region不是固定所属对应区域,角色一直在变。年轻代eden与survivor的区域数量比例依旧8比1比1,年轻代初始默认占比5%,默认最大占比60%。
类加载
生成
1.2版本之前的兼容导致的破坏
传统GC逻辑
句柄池(若是句柄结构)
运行时内存结构
验证
接口方法解析:从下往上找实现的接口所继承接口的方法
class文件二进制流
内存结构
卸载
符号引用替换为直接引用,共7种类或接口解析字段解析方法解析接口方法解析···动态相关
系统内核线程
生成class对象,方法区访问入口
整体来讲,当请求内存时,发现内存不够就会触发垃圾回收。详细讲,分代时,minor GC和full GC触发流程:当创建对象时,在eden区分配空间,若年轻代空间不够,则触发minor GC。当有对象晋升或者其他逻辑需要在老年代分配空间给对象时,发现老年代空间不够,则触发fullGC。若老年代使用CMS收集器,到达阈值也会执行fullGC。minor GC之前,如果发现:1,如果老年代空间担保没打开(1.6之后默认打开),年轻代空间大于老年代空间时。2,年轻代往常的收集之后进入老年代大小大于老年代剩余空间时。3,年轻代存活对象总大小大于survivor区,那么晋升老年代时,老年代空间不足时。将会先执行一次fullGC。
只为类变量(static)分配内存并赋初始值如0。若同时定义为final,则这一步直接赋值到位
优化方向
扩展加载器lib下的ext
执行clinit方法:包含了所有static修饰的,类变量以及语句块。按顺序执行
双亲加载打破产生原因:因为1.2之前不是此模型,所以为了兼容过往版本,此JVM规范不是强制,而是大多数情况下默认的
验证文件格式验证元数据:语义(关键字语义)验证字节码:语法(语句合法性)验证符号引用:解析开始后的验证访问权限
java9之后模块化
压缩包中获取
方法解析:从下往上找继承类的方法
用户线程
准备
字段解析:解析字段对应的类或者接口。如果字段所属类有实现接口,则会先从接口方向依次向上层继承的父接口解析。再判断是否有继承非object类,逐渐从下往上解析父类
java实例对象
堆
数据库读取
class对象
JVM
此回收器最好是内存较多时使用,内存大部分参数不需要变动。方向是使得年轻代尽量GC,减少进入老年代,避免mixedGC的stoptheworld。主要调整:1,调整总堆大小。2,调整期望暂停时间。此值过小,会导致GC频率太高,停顿次数过多,而且很多对象无法得到回收,会晋升老年代。此值过大,会导致,一次累计过多数据进行GC,每次暂停也太久,感知明显。
程序计数器
0 条评论
回复 删除
下一页