JVM
2021-10-16 16:39:57 0 举报
JVM
作者其他创作
大纲/内容
Eden
Tomcat、Spring Boot部署启动系统的时候,JVM参数如何设置?Spring Boot其实就是启动的时候可以加上JVM参数,Tomcat就是在bin目录下的catalina.sh中可以加入JVM参数tomcat设置参数需要在tomcat/bin目录下的catalina.sh中添加jvm的参数springboot 在启动jar的时候添加jvm参数即可#前台运行java -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=128m -Xms1024m -Xmx1024m -Xmn256m -Xss256k -XX:SurvivorRatio=8 -XX:+UseConcMarkSweepGC -jar /jar包路径nohup java -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=128m -Xms1024m -Xmx1024m -Xmn256m -Xss256k -XX:SurvivorRatio=8 -XX:+UseConcMarkSweepGC -jar /jar包路径
幸存1区
Metaspace区域满了
ParNew回收器(多线程复制算法)
Tomcat自定义了Common、Catalina、Shared等类加载器,用来加载Tomcat自己的一些核心基础类库的
类加载双亲委派机制 为什么要先找父加载 而不是自己找?这种设计的好处是?
卸载
1.触发老年代空间分配担保规则2.执行Young GC之后又一批对象需要放入老年代,此时老年代没有足够的内存空间存放这些对象,则会立即触发一次Full GC3.老年代内存使用率超过92%,会直接触发Full GC,可以通过参数“-XX:CMSInitiatingOccupancyFaction”配置
验证
加载
初始化
Tomcat是打破了双亲委派机制的每个WebApp负责加载自己对应的那个Web应用的class文件,也就是写好的某个系统打包好的war包中的所有class文件,不会传导给上层类加载器去加载。
用来记录当前执行的字节码指令的位置的就是记录目前执行到了哪一条字节码指令
扩展类加载器Extension ClassLoader
给类变量赋值
应用程序类加载器Application ClassLoader
Java堆
启动类加载器Bootstrap ClassLoader
Young GC
类加载器和双亲委派机制
很耗时,因为需要进行对象的清理,但是也是跟系统程序并发运行的,所以其实也不影响系统程序的执行
线程隔离的数据区
动态对象年龄判断:Surevivor区域里,一批对象的总大小大于这块Survivor区域的内存大小的50%,那么此时大于等于这批对象年龄的对象,就直接进入老年代
JVM三个核心点
给类分配内存空间给类变量(static修饰的变量)分配内存空间和设置默认的初始值
Tomcat的类加载机制应该怎么设计,才能把动态部署进去的war包中的类,加载到Tomcat自身运行的JVM中,然后去执行那些写好的代码呢?
重新标记
WebApp类加载器
因为类加载器本身就是做的父子关系模型Java代码实现,他最底下的子类加载器,只能通过自己引用的父类加载器去找。如果直接找顶层类加载器,不合适的,那么顶层类加载器不就必须硬编码规定了吗。
并发清理
自动内存管理,主要回收运行时数据区域的堆内存里的数据
内存空间/数据变量字节
再次进行\"STW\",速度很快,其实就是对在第二阶段中被系统程序运行变动过的少数对象进行标记
准备
所有线程共享的数据区
存放在代码中创建的各种对象
老年代
新生代对象进入老年代条件
类加载器
幸存0区
把符号引用替换为直接引用这个部分内容很复杂,涉及到JVM底层
负责加载“ClassPath”环境变量所指定的路径中的类加载写好的那些类到内存里
JVM参数优化:-XX:InitialHeapSize:Java堆内存的大小-XX:MaxHeapSize:Java堆内存的最大大小-XX:NewSize:Java堆内存中的新生代大小-XX:MaxNewSize:Java堆内存中的新生代最大大小-Xss:每个线程的栈内存大小-XX:MetaspaceSize:元空间大小,JDK1.8之前为-XX:PermSize-XX:MaxMetaspaceSize:元空间最大大小,JDK1.8之前为-XX:MaxPermSize-XX:PretenureSizeThreshold:大对象阈值-XX:MaxTenuringThreshold:多少岁进入老年代-XX:+UseParNewGC:指定新生代用ParNew回收器-XX:+UseConcMarkSweepGC:指定老年代用CMS回收器-XX:SurvivorRatio:设置Eden区的比例-XX:+UseCMSCompactAtFullCollection:碎片整理-XX:CMSFullGCsBeforeCompaction:多少次Full GC之后执行碎片整理-XX:+PrintGCDetails:打印详情的gc日志-XX:+PrintGCTimeStamps:这个参数可以打印出来每次GC发生的时间-Xloggc:gc.log:这个参数可以设置将gc日志写入一个磁盘文件
Tomcat为每个部署在里面的Web应用都有一个对应的WebApp类加载器,负责加载部署的这个Web应用的类
运行时数据区域
好处就在于,每个层级的类加载器各司其职,而且不会重复加载一个类。比如代码里用两个不同层级的类加载器,都去尝试加载了某个类,如果有双亲委派机制,那么都会先找父类加载器去加载,如果加载到了,那么以后就只会是他去加载这个类。否则如果没有双亲委派机制,那么岂不是两个不同层级的类加载器可以加载同一个类,造成类的重复加载!
Eden区满了
还是有必要,比如启动类加载器,可以通过一些方式指定加载其他目录的类,那么你必须得走双亲委派,如果对那些特殊区域的类加载,走双亲委派,才能上推到启动类加载器去执行,不会重复加载
元空间(永久代)常量池,类信息,static变量
触发Full GC的条件
方法区
Jsp类加载器
程序计数器
系统可以创建各种新对象,可能会创建新的存活对象,也可以会让部分存活对象失去引用,会尽可能的对已有对象进行GC Roots追踪
双亲委派模型:先找父亲去加载,不行的话再由儿子来加载
为什么必须要一级一级类加载器的往上找,直接从顶层类加载器开始找不就行了吗?
虚拟机首先需要把编译完成的字节码文件通过类加载器来加载到运行时数据区域
将字节码文件加载到内存中
Shared类加载器
JVM运行时数据区
类加载机制
CMS(标记清除算法)
自定义类加载器
使用
每个线程都有Java虚拟机栈,里面也有方法的局部变量等数据,这个Java虚拟机栈需要进行垃圾回收吗?为什么?JVM里垃圾回收针对的是新生代,老年代,还有方法区(永久代),不会针对方法的栈帧。方法一旦执行完毕,栈帧出栈,里面的局部变量直接就从内存里清理掉了。
JVM内存区域
Survivor1
并发标记
如果初始化一个类的时候,发现他的父类还没初始化,那么必须先初始化他的父类
伊甸园区
根据自己的需求加载类
新生代
本地方法栈
加载Java目录“lib\\ext”下的核心类
类从加载到使用经历的过程
大对象直接进入老年代,通过JVM参数“-XX:PretenureSizeThreshold”来设置
根据Java虚拟机规范,来校验你加载进来的“.class”文件中的内容,是否符合指定的规范
放从“.class”文件里加载进来的类,还会有一些类似常量池的东西放在这个区域里。但是在JDK 1.8以后,这块区域的名字改为“Metaspace(元数据空间)”
老年代空间分配担保规则:1.Young GC之前,检查老年代最大可用的连续空间是否大于新生代所有对象的总空间2.如果大于,则此次Minor GC是安全的,即使Young GC之后所有对象都存活,Survivor区放不下,也可以转移到老年代中3.如果小于,那么会继续检查老年代最大可用连续空间是否大于历次晋升到老年代的对象的平均大小: 3.1 如果大于,则会尝试进行一次Young GC,但这次Young GC依然是有 风险的 (1)Young GC过后,剩余的存活对象的大小,小于Survivor区的大小,那么此时存活对象进入Survivor区域即可 (2)Young GC过后,剩余的存活对象的大小,大于Survivor区的大小,但是小于老年代可用内存大小,就直接进入老年代即可 (3)Young GC过后,剩余的存活对象的大小,大于Survivor区的大小,也大于老年代可用内存大小,此时老年代都放不下这些存活对象,就会发生“Handle Promotion Failure”的情况,这个时候会触发一次Full GC 3.2 如果小于,则进行一次Full GC
解析
Java栈
Jsp类加载器,是给每个JSP都准备了一个Jsp类加载器
Survivor0
启动类、扩展类和自定义加载器都已经指定了加载路径,所以不应该会有重复加载类的问题吧?所以双亲委派是不是没有必要?
加载器需要加载一个类,他首先会委派给自己的父类加载器去加载,最终传导到顶层的类加载器去加载,如果父类加载器在自己负责加载的范围内,没找到这个类,那么就会下推加载权利给自己的子类加载器
年轻代/新生代
Tenured
class文件
主要负责加载机器上安装的Java目录下的核心类“lib”目录:Java最核心的一些类库,支撑Java系统的运行
Full GC
1、保存每个方法内的局部变量等数据的2、每个线程都有自己的Java虚拟机栈3、线程执行了一个方法,就会对这个方法调用创建对应的一个栈帧,并压入线程的Java虚拟机栈4、栈帧里就有这个方法的局部变量表 、操作数栈、动态链接、方法出口等东西
Catalian类加载器
新生代对象经历垃圾回收15次,会进行老年代;通过JVM参数“-XX:MaxTenuringThreshold”来设置,默认是15
为虚拟机执行Native方法服务的也是存放各种native方法的局部变量表之类的信息
初始标记
Common类加载器
会\"STW\",影响不大,因为他的速度很快,仅仅标记GC Roots直接引用的对象
垃圾回收机制
0 条评论
回复 删除
下一页