##jvm内存模型
public class Math{
public static final int initData = 333;
public static User user = new User();
public int compute(){
int a = 1;
int b = 2;
int c = (a+b)*10;
return c;
}
public static void main(String[] args) throws IOException{
Math math = new Math();
math.compute();
System.out.println("end");
}
}
每一个线程在内存中拥有独立的程序计数器,栈,本地方法栈。
程序计数器:记录下一行代码的位置;
栈:其中每一个方法分配一块栈帧
局部变量表:存放方法中的局部变量
操作数栈:进行数据操作的临时空间
动态链接:该方法中引用的其他方法的地址
方法出口:方法执行完后父方法的执行位置
本地方法栈:native方法的执行空间
堆和方法区是多个线程共享的
堆:
gc:可达性分析算法
将“GC Roots”对象(线程的局部变量、静态变量、本地方法栈的变量)作为起点,从这些节点开始向下搜索其引用的对象,找到的对象都标记为非垃圾对象,其余未标记的对象都是垃圾对象
STW:stop the world ,gc的时候会挂起用户请求线程
minor gc:伊甸园区满了会做minor gc,会回收整个年轻代,每次gc会将伊甸园区和一个s区的非垃圾对象挪到另一个空的s区,同时分代年龄+1,年龄到15后会放到老年代,垃圾对象直接清除
full gc:老年代满了进行full gc,对整个堆进行gc
Jstat
jstat命令可以查看内存各部分的使用量以及加载类的数量。命令的格式如下:
jstat [-命令选项] [vmid] [间隔时间(ms)] [查询次数]
jstat -gc pid最常用,可以评估程序内存使用及gc压力整体情况
Arthas jvm调优工具
使用场景
1.是否有一个全局视角来查看系统的运行状况?
2.为什么CPU又升高了,到底哪里占用了CPU?
3.运行的多线程有死锁吗?,有阻塞吗?
4.程序运行耗时很长,是哪里耗时比较长,如何检测
5.这个类从哪个jar包加载的,为什么回报各种类相关的exception?
6.我改的代码为什么没有执行到?难道是我没有commit?分支搞错了?
7.召问题无法在线上debug,难道只能通过加日志再重新发布吗?
8.有什么办法可以监控到jvm的实时运行状态
使用
# githtb下载arthas
wget https://alibaba.github.io/arthas/arthas-boot.jar
# Gitee下载
wget https://arthas.gitee.io/arthas-boot.jar
用java -jar运行即可,可以识别计器上所有的java进程
dashboard 大盘情况
thread pid 定位线程问题
thread -b 线程锁的情况
jad com.xxx.Test反编译线上代码
ognl修改线上内存变量的值