JVM原理及调优

JVM运行原理:

java文件用过javac预编译处理变成字节码文件(字节码文件用二进制保存,可以通过javap - c 命令反汇编成容易看懂的汇编语言),字节码文件通过类装载系统进入到JVM运行内存里,JVM运行内存分为5个部分,堆,栈,方法区,本地方法栈和程序计数器。

main方法执行,栈内存分配一块栈帧,栈帧分为四块区域,局部变量表,操作数栈,动态链接,方法出口。局部变量的赋值在操作数栈里进行,赋值完,出栈,然后压入局部变量,完成变量的赋值。动态链接指向的是内部方法的地址值,执行完方法,栈帧消失。

当方法执行到底层代码,用native修饰的方法时,产生的内存放到本地方法栈,

程序计数器用来标记汇编java文件的运行的行数,读完一行汇编语言,字节码执行引擎会修改程序计数器标记的行数。因为系统是多线程,当你cpu执行代码时,会被其他线程调用,当cpu再次回来执行代码时,会继续根据程序计数器标记的行数继续执行。方法区用来存放常量,静态变量和字节码文件。

堆内存分为两个区:年轻代和老年代。年轻代又分为eden,s0,s1三个区,内存分配比例为8:1:1。

首先创建的对象放在Eden区,当Eden区存储数据满了后,字节码执行引擎进行minor gc 来收集垃圾。(这是可达性分析算法)每一个对象都可以是 GC root,这个对象作为根节点如果被依赖着,就被定为“非垃圾对象”,不会被minor gc 清理,minor gc清理完Eden去垃圾时,把非垃圾对象存到s0区,第二次minor gc 清理内存时,会把eden和s0区的垃圾对象都清理掉,把非垃圾对象存到s1区,经过默认的15c次清理后,s2区的对象会被存到老年代。当老年代存放的数据变多时,会进行full gc进行清理整个堆区的垃圾对象。

STW:stop the world:当执行垃圾清理时(minor gc 和 full gc),其他线程会被停止,因为多线程同时运行的话,会造成gc 刚判断完一个对象是非垃圾时,下一刻cpu就被其他线程抢过去执行这个对象并释放掉,那这个非垃圾对象就变成了垃圾对象,降低了gc的效率。

JVM调优:

比如订单系统高并发时,频繁进行full gc ,这个原因是什么,要如何优化?

答:原因:比如8个G的运行内存,堆内存分到了3个G,给老年代2个G,给年轻代1个G(eden区800M,s0区100M,s1区100M),高并发时,假如每秒产生60M的垃圾,eden区过了14,15秒就会内存满了,这是minor gc 进行垃圾清理,这时最后1,2秒时所产生的的对象还在使用,不能被清理,所以会存到s0区,但数据大于100M时,会直接把数据存到老年代,这样会造成老年代内存增多,所以会频繁进行full gc。

解决:优化堆内存的分配:给老年代1个G,给年轻代2个G,这样so区就有200M,就能直接存完,不会存到老年代。

加大系统的运行内存:比如说运行内存64个G:给堆内存分配40个G,年轻代里的Eden区分配到了32个G。但当进行minor gc 时,要一次性清理32个G中的垃圾对象,要耗时好几秒,这时其他线程会停止好几秒等待minor gc ,会造成其他线程超时错误。

解决:使用G1垃圾收集器,配置每次minor gc清理垃圾的时间为200毫秒,把eden进行分区清理,gc进行判断,清理时间不能超过200毫秒,每次清理eden区中的2~3个G。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值