JVM
2021-04-14 16:14:35 14 举报
AI智能生成
JVM
作者其他创作
大纲/内容
JVM
数据区
线程共享
堆
新生代
老年代
生命周期长的内存对象
永久代
存放Class和 Meta(元数据)的信息
GC 不会在主程序运行期对永久区域进行清理
随着类的加载增多,容易导致OOM
Java8中被移除
被元数据区取代
方法区
存储
JVM加载的类信息
常量、静态变量
即时编译器编译后的代码
回收
常量池的回收
类型的卸载
常量池
编译期生成的各种字面量和符号引用
线程私有
程序计数器
不会发生OOM
虚拟机栈
Java 方法执行的内存模型
方法执行入栈,堆内创建对象且栈内引用
方法结束出栈,堆内存对象引用失效
内容
局部变量表
存放方法参数和方法内定义的局部变量
操作数栈
一个后入先出栈(LIFO)
动态链接
方法返回地址
本地方法区
为本地方法服务
垃圾回收
MinorGC
触发条件
新分配对象内存不够
复制算法
步骤
1.eden、servicorFrom中活对象 复制到 ServicorTo,年龄+1
2.清空 eden、servicorFrom
3.ServicorTo 和 ServicorFrom 互换
MajorGC
1.MinorGC之后内存不够
2.新建大对象无法找到足够大的内存空间
3.年龄达到15岁
GC算法
标记清除算法
FullGC
1.调用System.gc时,系统建议执行Full GC,但是不必然执行
2.老年代空间不足
3.方法区空间不足
4.通过Minor GC后进入老年代的平均大小大于老年代的可用内存
标记算法
引用计数法
适用场景
内存不太充裕
实现
计数器的管理(自增/自减)
人工完成
Objective-C
C++里使用COM
自动管理
CPython
C++11的std::shared_ptr
引用计数存储
侵入式的存在对象内
CPython:把引用计数存在每个受自动内存管理的Python对象的对象头里
存在对象外面
C++11标准库里的std::shared_ptr
可达性分析
内存充裕
GC roots
虚拟机栈(栈帧中的本地变量表)中引用的对象
方法区中类静态属性引用的对象
方法区中常量引用的对象
本地方法栈中(Native)引用的对象
原理
GC Roots引用链
对象的生死状态只能批量的被识别出来,然后批量释放死对象
不可达不等于可回收
问题:内存碎片化
应用:MajorGC
老年代垃圾回收
问题:内存减半
应用:MinorGC
新生代垃圾回收
标记整理算法
将存活对象移向内存的一端
应用:
垃圾收集器
CMS
目的:获取最短回收停顿时间为目标的收集器
回收算法:基于“标记-清除”
原理:垃圾回收线程和系统工作线程尽量同时执行的模式
1.初始标记
STW
标记出所有GC Roots直接引用的变量
2.并发标记
对老年代所有对象进行GC Roots追踪(最耗时)
3.重新标记
重新标记第二阶段新创建的对象
4.并发清理
垃圾回收线程数
默认:(CPU核数+3)/4
存在的问题
1.消耗CPU资源
2.浮动垃圾:并发清理阶段进去老年代的对象
3.并发清理垃圾回收失败
4.内存碎片问题
导致
频繁的GC
参数设置开启
GC之后停止所有工作线程,进行碎片整理
执行多少次GC之后进行内存碎片整理
触发时机
老年代内存占用达到一定比例
1.6默认92%
参数可设置
并发垃圾回收失败
自动用Serial Old垃圾回收器替代CMS
生产实践中要避免
ParNew
多线程垃圾回收
默认线程数和CPU核数一致
G1
特点
将Java堆内存分为多个大小相等的Region
目标是不超过 2048个Region
Region的大小必须是2的倍数
一般保持默认即可
也可通过参数设置指定
新生代和老年代是逻辑概念
可以设置垃圾回收的预停顿时间
停顿可控
追踪每个Region中可以回收的对象大小和预估时间
尽量缩短垃圾回收对系统的影响时间
在有限的时间内回收尽可能多的垃圾对象
管理无限大内存
ZGC
并发
着色指针
读屏障
内存参数
参数含义
-Xms:Java堆内存大小
-Xmx:Java堆内存的最大大小
-Xmn:堆内存新生代大小
-XX:PermSize:永久代大小
-Xss:每个线程的栈内存大小
每个线程的栈空间是固定
进程内所有线程的栈空间不固定
系统应用设置JVM参数
java -Xms ... -jar App.jar
占机器内存比例
参考值
8G-5440M
实际并没有标准
实战
1.预估系统业务量,访问量
2.推算系统每秒并发,推算每秒内存占用
类加载
1.加载
2.链接
1.验证
2.准备
3.解析
3.初始化
机制
双亲委派
好处
加载器
启动类加载器
lib目录中的类库
拓展类加载器(ExtClassLoader)
lib\\ext目录中类库
系统类加载器(AppClassLoader)
ClassPath的类库
自定义类加载器
一些思考
自定义类会被编译和加载吗
会被编译
不会被加载,JVM类加载器会加载特定包下的类
自定义类加载器加载自定义类
JavaBridge
PhpJavaServlet
PhpCGIServlet
存在的意义
跨平台
1.Java 源文件—->编译器—->字节码文件
2.字节码文件—->JVM—->机器码
GC调优
工具
jstat
1.找到JAVA进程PID
2.jstat -gc PID
新生代对象增长的速率
年轻代触发频率
年轻代的耗时
.........
其他命令
jstat -gccapacity
jstat -gcnew PID
jstat -gcold PID
主要观察参数
年轻代
Eden区的对象增长速率
Young GC频率多高
一次Young GC 耗时
Young GC之后多少对象存活
老年代的对象增长速率
Full GC频率
一次Full GC耗时
jmap
jmap -head PID
jmap -histo PID
使用jmap生成堆内存转储快照
使用jhat在浏览器中分析堆转出快照
MAT
主要分析dump文件
阿里云ECS
线上系统监控
Zabbix
Open-Falcon
频繁Full GC的几种表现
机器CPU负载过高
频繁Full GC报警
系统无法处理请求或者处理很慢
排查OOM
让JVM在遇到OOM(OutOfMemoryError)时生成Dump文件-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/path/heap/dump
当你没有dump文件的时候,也没有明显日志的时候,GC也无异常的时候挂掉,可以在操作系统中开启参数 ulimit -c如果不等于0会在java进程挂掉的时候阻塞一段时间,留给操作系统保留现场,生成一个core dump,然后通过工具转换成jvm dump文件进行分析
好文
生产事故排查
案例1
事故现场
堆内存正常,栈内存正常
机器内存一直上升,容器杀掉进程
没有OOM
排查过程
确定原因:响应式编程代码,线程资源不受JVM管控,程序没有主动释放
解决方案
代码主动释放内存占用
案例2
机器内存足够,应用没有任何日志异常,上线就oom
而且重启运行后就正常,可以维持运行一个月左右
面试
16G内存的机器,长连接的应用如果用CMS参数怎么配置
G1平时怎么用?说说原理
JVM内存模型、栈帧的局部变量表有哪些内容
0 条评论
下一页