JVM学习笔记

JVM虚拟机

一、为什么学习JVM

面试、找工作、OOM、调优

二、什么是JVM,它做了什么

java虚拟机,执行java代码的平台,屏蔽了底层硬件指令的细节,一次编写到处执行

代码执行过程:源代码->字节码文件class->-->jvm->

jvm&jdk&jre 关系  jdk包括jre和jvm

JVM学习笔记

jvm做了什么?

1,空间分配回收,而c++需要考虑内存分配和回收。java能让开发者100%精力投入业务开发

2,内存管理

3,屏蔽底层硬件区别

 

三、jvm运行时运行区

JVM学习笔记

1,程序计数器:指向当前线程执行的字节码指令的地址,行号,如0x3d48

java最小的执行单位是线程,但线程只负责做,做什么需要指令告知;

程序计数器为什么要记录地址呢?因为cpu是有调度策略的,当cpu被其他线程抢到了,此时该线程被挂起,此时需要记录上一次执行到的地址方便线程恢复执行。

 

2,虚拟机栈(FILO先进后出):存储当前线程运行方法时所需要的数据,指令和返回地址。

如一个helloword()方法,一个方法一个栈帧,局部变量表存储局部变量,一个程序运行时就能确定的空间,一个栈层存储32位的数,即一个int,多个字节要拆开存储如64位拆为高位和地位。

操作数栈:比如算sum=i+j  从局部变量表加载i,j,然后做加法得到sum,再将sum存到局部变量表,即对应4条指令。

注意:成员变量不管是不是引用类型都存储在堆内存中的。

但对于引用类型obj。局部变量表只记录obj的地址应用,所以结论栈指向堆。

学会看反编译字节码文件,javap -v HelloWord.class > aa.txt 参考javap指令集查看https://www.cnblogs.com/JsonShare/p/8798735.html

如methodOne(int i){int j=0; } ,仅一个int j=0 对应两条指令;  j存在局部变量第二位置里,地址0:存this 地址一1:存 i  地址2:存j。

 

动态链接:java动态特性,如运行时多态,如@Autowired private Service service;

代码调用serevice.do()。需动态解析,到底是哪个实现类的do方法。为什么动态链接要存在栈帧里呢?

方法出口:即return,正常出口和异常出口如throw。

一个方法调用另一个方法,怎么入栈?先入栈methodOne,再入栈methodTwo

 

JVM学习笔记

3,本地方法栈:native方法栈,

4,方法区:存储类信息即class文件,常量,静态变量,JIT,methodOne存储在方法区。

5,堆内存:分代模型 就分新生代和老年代,跟后面的永久代和元空间没关系。

注意:jdk1.8后 永久代变成了元空间meta space主要解决永久代溢出的问题,因为元空间会自扩容,跟arraylist差不多。

JVM学习笔记

方法区就存在永久区。老年代默认是新生代的2倍。创建对象首先在eden区询问空间,有则放下,没有则触发yonggc ,把之前的对象移动到surivor区域的from区域,如果from也放不下,就会触发担保机制,直接放到老年代,每新生代gc一次,就触发from和to的交换一次,对象向下移动年龄是加1的。

Xms  s:starting堆初始的总大小

Xmn  n:new  堆初始时new空间的大小

Xmx   x:max堆最多的空间

 

垃圾回收算法:gc算法:复制回收算法(新生代用的),标记清除算法和标记内存整理算法(后面俩是老年代用的)。

垃圾回收器:不同的垃圾回收器是实现了不同的垃圾回收算法的,如parllen new等实现了

复制回收算法,eden区一定是空的。

 

 

内存溢出后排查是否是内存泄露。

对象的生命周期,什么对象能被回收,即是否可达,gc root概念,当一个对象被应用时计数器就加1,当为0时即无引用代表可回收。堆里有很多gc root只要有gcroot指向的都是可达的,都不能回收。

gc root有哪些:有4种;强应用,弱引用。。。

 

FullGc 5分钟一次怎么调优? 衡量的标准和维度?5分钟一次怎么啦?是要追求吞吐率还是最小执行时间?业务出现性能问题,90%以上是业务调优,并不是有问题就调jvm。

内存泄露,要找出gcroot,即泄露源,因为它指向了很多对象,或者死循环对象,被回收不了。

性能调优:发挥机器本来的性能。

1,如果追求吞吐率就要算吞吐率,看下回收器用的什么,如可用cms就是追求吞吐率的。

2,

 

 

总结:程序计数器,虚拟机栈,本地方法栈是线程独有的,每个线程都有,但堆和方法区是共有的。