hjr-JAVA JVM调优

理解

JVM结构

JVM 执行顺序 : class文件->类装载器 - >内存区->执行引擎

类装载器采用parent模型(每个加载请求会不断往父类传,最终到最顶层,最顶层实现不了,再一层层往下检测哪层能实现)避免父子加载器重复加载,主要包含,java内部库加载器->java扩展类库加载器->程序员代码类加载器->程序员自定义的类加载器

其中内存区主要包含 方法区 虚拟机栈 本地方法栈 堆 程序计数器

内存分为静态内存(方法区,栈)和动态内存(堆),静态内存回收方式是固定的,GC指的是动态内存,即堆中的内存

虚拟机栈和本地方法栈的区别是本地方法栈是为java native方法服务的,虚拟机栈是为程序员写的方法服务的

流程

当我们编写的class文件进入类装载器后,java栈总是和线程关联在一起,每当创建一个线程时,JVM就会为这个线程创建一个对应的java栈。在这个java栈中又会包含多个栈帧,每运行一个方法就创建一个栈帧,用于存储局部变量表、操作栈、方法返回值等。每一个方法从调用直至执行完成的过程,就对应一个栈帧在java栈中入栈到出栈的过程。所以java栈是线程私有的。

方法调用=》创建栈帧-》压入虚拟机栈=》方法执行完毕,栈帧出栈并被销毁,栈帧保存了局部变量表、操作数栈、动态链接、方法出口等数据,栈线程隔离

对JVM内存进行设置和分析可以定位异常代码,防止内存溢出,强引用(内存溢出也不回收,报错)、软引用(内存溢出回收)、弱引用(GC时回收)和虚引用(随时可以回收),不同的类型对应不同的GC机制,代码执行过程就是一个压栈入栈的过程,栈保存基本类型和引用类型,堆保存对象,引用变量就是对象的首地址

内存模型

堆中有主内存
每个线程维护一个自己的本地内存,维护堆内存中的共享变量的副本,各个线程从自己的本地内存中存取数据
普通代码不能保证可见性(线程操作本地内存后主存立刻更新,其他本地内存立刻同步)
使用volatile关键字,可以禁止代码指令优化重排序,和强制访问主存,保证可见性,但是不能保证原子性

GC

检测算法

  1. 引用计数法

给一个对象添加引用计数器,每当有个地方引用它,计数器就加1;引用失效就减1,没引用回收

问题:两个对象互相引用,永远无法回收,

  1. 可达性分析算法

从根集结点检测,没引用的回收,根集一般包括java栈中引用的对象、方法区常良池中引用的对象

收集算法

  1. 标记-清除
    先标记要回收的,然后把标记的回收,会造成内存碎片

  2. 复制

用2倍的内存,遍历区域1,把正在引用的复制到内存2,遍历结束后回收区域1的全部内存,无内存碎片,耗内存

  1. 标记-整理

先标记要回收的,然后边回收边整理内存

  1. 分代收集

堆内存分 年轻代(又分为8:1:1的三个子区域,用标记-清除) 年老代(满了用fullGC,不满用复制) 永生代(程序关闭才回收)

一个对象在年轻代出生,每经过n检测未被回收,即移动到下一代。不同代采取不同回收方式

n 是人为设置和由不同代内存大小决定的

调优

减少 fullGC 和 gc频率,使用JConsole(内存、CPU曲线等)、Java VisualVM、jsatck(通过线程PID查询,堆栈内存等),DUMP堆文件分析,等工具检测

  1. 修改各个内存区域的大小和比例
  2. 检测内存曲线防止死锁,死循环等异常代码
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

架构师小侯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值