JVM
2020-11-20 17:42:57 53 举报
AI智能生成
JVM
作者其他创作
大纲/内容
内存模型
线程私有
虚拟机栈(线程栈)
局部变量表
操作数栈
动态链接
方法出口
-Xss设置越小count值越小,说明一个线程栈里能分配的栈帧就越少,但是对JVM整体来说能开启的线程数会更多
程序计数器
记录指令执行的行号
本地方法栈
native方法
线程共享
堆,-Xms,-Xmx
年轻代
eden
参数设置:-Xmn
survivor to
survivor from
年老代
old
方法区(元空间)1.8以后为直接内存
‐XX:MetaspaceSize=256M ‐XX:MaxMetaspaceSize=256M
直接内存
逃逸分析
解释模式(Interpreted Mode):只使用解释器(-Xint 强制JVM使用解释模式),执行一行JVM字节码就编译一行为机器码
编译模式(Compiled Mode):只使用编译器(-Xcomp JVM使用编译模式),先将所有JVM字节码一次编译为机器码,然
后一次性执行所有机器码
后一次性执行所有机器码
混合模式(Mixed Mode):依然使用解释模式执行代码,但是对于一些 "热点" 代码采用编译模式执行,JVM一般采用混合模
式执行代码
式执行代码
GC
GC做的哪些事
哪些对象需要回收
什么时候回收
怎么回收
怎样确定对象已经死亡
引用计数法
这个方法实现简单,效率高,但是目前主流的虚拟机中并没有选择这个算法来管
理内存,其最主要的原因是它很难解决对象之间相互循环引用的问题
理内存,其最主要的原因是它很难解决对象之间相互循环引用的问题
可达性分析
这个算法的基本思想就是通过一系列的称为 “GC Roots” 的对象作为起点,
从这些节点开始向下搜索,找到的对象都标记为非垃圾对象,其余未标记的对象
都是垃圾对象
从这些节点开始向下搜索,找到的对象都标记为非垃圾对象,其余未标记的对象
都是垃圾对象
minror GC、young GC
垃圾收集算法
标记清除
效率低,产生内存碎片,可能造成大对象无法存放
复制算法
效率高,不产生内存碎片,但是会导致内存使用空间减少一半
标记整理
标记后不是清理对象,
而是将存活对象移向内存的一端。然后清除端边界外的对象。
而是将存活对象移向内存的一端。然后清除端边界外的对象。
分代收集算法
其核心思想是根据对象存活的不同生命周期将内存
划分为不同的域,一般情况下将GC 堆划分为老生代(Tenured/Old Generation)和新生代(Young
Generation)
划分为不同的域,一般情况下将GC 堆划分为老生代(Tenured/Old Generation)和新生代(Young
Generation)
垃圾收集器
Serial
(-XX:+UseSerialGC -XX:+UseSerialOldGC 单线程
Par New
-XX:+UseParNewGC Serial的多线程版本,一般线程数与cpu核数一致,当然也可以用参数(-XX:ParallelGCThreads)指定收集线程数
Parallel Scavenge
(-XX:+UseParallelGC(年轻代),-
XX:+UseParallelOldGC(老年代))那么它有什么特别之处呢?
Parallel Scavenge收集器关注点是吞吐量(高效率的利用CPU)。CMS等垃圾收集器的关注点
更多的是用户线程的停顿时间(提高用户体验)。所谓吞吐量就是CPU中用于运行用户代码的时
间与CPU总消耗时间的比值
XX:+UseParallelOldGC(老年代))那么它有什么特别之处呢?
Parallel Scavenge收集器关注点是吞吐量(高效率的利用CPU)。CMS等垃圾收集器的关注点
更多的是用户线程的停顿时间(提高用户体验)。所谓吞吐量就是CPU中用于运行用户代码的时
间与CPU总消耗时间的比值
serial old
Par Old
CMS
过程:1.初始化标记2.并发标记3.重新标记4.并发清除;是一种以获取最短回收停顿时间为目标的收集器
一般情况下使用 Par new 年轻代,CMS年老代 -XX:+UseConcMarkSweepGC(old)
一般情况下使用 Par new 年轻代,CMS年老代 -XX:+UseConcMarkSweepGC(old)
G1
将内存分为多个segment,可以指定Full GC执行时间,一般用于大内存
进入老年代
1.大对象直接进入老年代
2.长期存活的对象进去老年代
3.对象
在 Survivor 中每熬过一次 MinorGC,年龄就增加1岁,当它的年龄增加到一定
程度(默认为15岁),就会被晋升到老年代中。对象晋升到老年代的年龄阈
值,可以通过参数 -XX:MaxTenuringThreshold 来设置。
在 Survivor 中每熬过一次 MinorGC,年龄就增加1岁,当它的年龄增加到一定
程度(默认为15岁),就会被晋升到老年代中。对象晋升到老年代的年龄阈
值,可以通过参数 -XX:MaxTenuringThreshold 来设置。
4.对象的动态年龄判断;),一批对象的总
大小大于这块Survivor区域内存大小的50%,那么此时大于等于这批对象年龄最
大值的对象,就可以直接进入老年代了
大小大于这块Survivor区域内存大小的50%,那么此时大于等于这批对象年龄最
大值的对象,就可以直接进入老年代了
5.minor GC存活下来的对象,survivor区放不下,直接进入老年代
6.老年代空间分配担保机制“-XX:-HandlePromotionFailure”(jdk1.8默认就设置了)的参数是
否设置了
否设置了
调优工具
1.打印操作日志‐XX:+PrintGCDetails ‐XX:+PrintGCTimeStamps ‐XX:+PrintGCDateStamps ‐Xloggc:./gc.log
2.jps -查看进程
3.jmap -histo 进程id >log.txt;打印对象情况num:序号
instances:实例数量
bytes:占用空间大小
class name:类名称,[C is a char[],[S is a short[],[I is a int[],[B is a byte[],[[I is a int[][]
instances:实例数量
bytes:占用空间大小
class name:类名称,[C is a char[],[S is a short[],[I is a int[],[B is a byte[],[[I is a int[][]
4.jmap -dump:format=b,file=xx.hpof 进程号;查看堆
也可以设置内存溢出自动导出dump文件(内存很大的时候,可能会导不出来)
1. -XX:+HeapDumpOnOutOfMemoryError
2. -XX:HeapDumpPath=./ (路径)
也可以设置内存溢出自动导出dump文件(内存很大的时候,可能会导不出来)
1. -XX:+HeapDumpOnOutOfMemoryError
2. -XX:HeapDumpPath=./ (路径)
5.jstack 查看线程,死锁
6.jinfo 查看正在运行的Java应用程序的扩展参数
7.stat命令可以查看堆内存各部分的使用量,以及加载类的数量
jstat -gc 进程id 2000 100 每隔两秒执行一次,执行100次(最常用的)
jstat -gc 进程id 2000 100 每隔两秒执行一次,执行100次(最常用的)
JVM类加载
类加载机制
分为五个部分
加载
在硬盘上查找并通过IO读入字节码文件,使用到类时才会加载,例如调用
类的main()方法,new对象等等,在内存中分配一块表这个class类的空间
类的main()方法,new对象等等,在内存中分配一块表这个class类的空间
验证
验证clas文件是否符合JVM规范
准备
给类的静态变量分配内存,并赋予默认值,如:int a=1;此阶段先为a赋值为0
解析
将符号引用替换为直接引用,所谓的静态连接,动态连接是在程序运行时完成的;虚拟机将常量池中的符号引用替换为直接引用的过程
初始化
对类的静态变量初始化为指定的值,执行静态方法;如int a=1;此时将0换为1
类加载器
启动类加载器
负责支撑JVM运行的,位于JRE/lib
目录下的核心类库
目录下的核心类库
扩展类加载器
负责加载JVM运行的位于JRE/lib/EXT的扩展目录
应用程序加载器
负责加载ClassPath路径下的类的包,主要加载自己写的类
自定义加载器
负责加载用户自定义的加载器
双亲委派机制
加载过程
1首先查看指定名称的类是否已经加载过,加载过以后直接返回,未加载过则继续
2.此类未加载过,判断是否存在父加载器;有则由父加载器加载;(即调用parent.loadClass(name, false);).或者是调用bootstrap类加
载器来加载。
载器来加载。
3.如果父加载器及bootstrap类加载器都没有找到指定的类,那么调用当前类加载器
的findClass方法来完成类加载。
的findClass方法来完成类加载。
设计原因:沙箱安全机制,自己写的java.lang.String.class类不会被加载,这样便可以防止
核心API库被随意篡改 2.避免类的重复加载:当父亲已经加载了该类时,就没有必要子ClassLoader再加
载一次,保证被加载类的唯一性
核心API库被随意篡改 2.避免类的重复加载:当父亲已经加载了该类时,就没有必要子ClassLoader再加
载一次,保证被加载类的唯一性
打破双亲委派机制
如tomcat,方法重写loadClass和findClass方法
tomcat打破双亲委派原因
1.一个web容器可能部署多个应用,而多个应用需要使用同一个第三方类的不通版本,,不能要求同一个类库在同一个服务器只有一份,因此要保证每个应用程序的类库都是独立的,保证相互隔离。
2.部署在同一个web容器中相同的类库相同的版本可以共享。否则,如果服务器有10个应
用程序,那么要有10份相同的类库加载进虚拟机。
用程序,那么要有10份相同的类库加载进虚拟机。
3.web容器有自己的类库,不能与应用程序的类库混淆,基于安全考虑,应该让容
器的类库和程序的类库隔离开来。
器的类库和程序的类库隔离开来。
4.web容器要支持jsp的修改,我们知道,jsp 文件最终也是要编译成class文件才能在虚拟
机中运行,但程序运行后修改jsp已经是司空见惯的事情, web容器需要支持 jsp 修改后不
用重启。
机中运行,但程序运行后修改jsp已经是司空见惯的事情, web容器需要支持 jsp 修改后不
用重启。
0 条评论
下一页