JVM 笔记

JVM 笔记

类装载子系统,运行时数据区,执行引擎

运行时数据区

方法区 (虚拟机规范)

方法区具体实现:

1.永久代  1.8以前,由jvm管理。

2. 元空间 1.8以后,操作系统管理(OS)

为什么1.8以后要用元空间取代永久代?

答:1.硬件发展  1.8以前大部分运行32位机,OS最大内存4G(2^32),内核2G,应用2G。如果不放JVM管理,很可能会影响操作系统其他程序执行。64位机,最大内存256G。64位只有48位在用。2^48-》256G。由于方法区主要存储类的相关信息,所以对于动态生成类的情况比较容易出现永久代的内存溢出。

2.业务发展-》系统复杂度提升。并发。spring吃内存,等等。

内存调优:jvm元空间(20.75m-无限)-XX:+PrintFlagsFinal 查看jvm运行参数命令。

    最大最小内存不一致,导致内存抖动(这块程序内存忽大忽小,影响程序运行)

    一般方法区大小设成物理内存的1/32(论坛和大牛的建议)

 

虚拟机栈(java栈)

栈帧

1. 局部变量表  局部变量占2个slot(槽)。赋值完的变量放进来

2.操作数栈  存变量的值

3.动态链接

4.返回地址  做的事情-》 1.局部变量表指针重置,2.操作数栈指针重置,3.返回值压栈,4.add方法占用的栈帧内存回收,5.程序计数器的数值重置

 

本地方法栈

运行native方法的栈

 

程序计数器

记录程序要执行的行号

 

新生代与老年代1:2的问题

新生代  分代+复制算法

伊甸园,from,to区。8:1:1,经大公司测试,90-95%的对象在第一次被gc。所以第一次gc后有10%(取最大值)的对象存活,所以设置成1。一开始是9:1,后来变8:1:1。因为程序产生的对象被回收,会产生很多内存碎片。

内存碎片导致程序(需要分配连续内存空间)要分配内存分不到。标记整理算法,存在问题:非常复杂,空间回收-》合并-》打标记的指针进行移动-》对数据进行移动。很多地方要做stw(stop the world)。

分代复制算法效率相对高很多。

 

老年代

1.新生代15次gc没释放就进入老年代

2.大对象(大于伊甸园区的对象) 占满伊甸园区,要复制移动到老年代消耗性能多,空间分配担保(老年代作为担保)

 

栈对堆得引用,栈变量指向堆得对象

堆对方法区的引用,对象的类型指针指向方法区的class对象

方法区对堆得引用,静态变量

 

 

多线程

1.6以前syncronize 没获得cpu的线程会阻塞进队列等待

原子操作类AtomicInteger优化

CAS:无锁,自旋锁,乐观锁,轻量级锁  compareandset

hotspot源码

https://www.bilibili.com/video/BV1o54y167pa?p=2

1原子性问题:lock  cmpxchgq(汇编指令)缓存行锁(硬件级别加锁是针对一个缓存行(64位))/总线锁(超过缓存行大小在总线加锁)

2 ABA问题:加版本号version  AtomicStampedReference

volatile 

增加一个#Lock在汇编指令,相当于内存屏蔽。

可以实现可见性(共享变量修改后强制写入主存,通过总线嗅探(也可以说是监听),其他cpu当监听到总线的共享变量修改后,就让自己的共享变量失效,会重新从主存中读取),有序性(确保重排序时不会把其后面的指令排到内存屏蔽之前的位置,也不会把之前的指令排到内存屏蔽之后的位置),不能保证原子性。

有序性例子:对象初始化

可以看到下面对象初始化的执行命令,cpu会重排序。下图21是调构造方法,24是把对象赋值给变量instance。如果21,24重排序换位置,就可能出现版构造

内存屏障

storeload ->fence 

最后调了汇编命令lock

 

锁优化 jdk1.6开始

锁升级

1.偏向锁 

在对象头记录线程id

2.CAS 轻量级锁。如果大量线程争抢cpu,会导致cpu空转。

3.重量级锁。线程很多,不如用重量级锁

优化轻量级锁到重量级锁 LongAdder.java  分段CAS

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值