JVM性能调优实战
.Java文件—javac—》.class—java—》JVM(分为Linux机器码/Windows机器码)
Java math.class进入虚拟机,主要进方法区。字节码执行引擎---操作方法区代码(math.class)
栈--对应每个方法------先进后出:分区{局部变量、操作数栈、动态链接、方法出口}
首先,方法:int a=1,b=2 ,c=(a+b)*10;
局部变量0下标,是this。。。表示用这个局部变量块的数据,,调用this
操作数栈1,局部变量a,然后机器语言,a=1;。。。。。b=2
取出a的值进操作数栈,取b的值进操作数栈,然后取2+1,(先进后出)然后压进操作数栈,然后10压进操作数栈,然后计算30,在操作数栈。然后局部变量c=30;
程序计数器 ----每个线程都有自己的程序计数器,0开始,表示代码运行到的位置,以防丢失执行。
字节码执行引擎,可以操作程序计数器的执行位置。
操作数栈,操作数在程序运行期间,临时的一块内存空间,然后进行数据的操作。
动态链接的作用就是为了将这些符号引用转换为调用方法的直接调用
根据动态链接就能找到方法,然后给方法里面的属性分配内存,也可以根据链接执行方法。
方法出口:可以继续执行当时结束的方法后续应该执行的方法。。。相当于有个程序计数器,记录应该执行的代码。可以继续执行
栈和堆的关系:局部变量---》引用堆里面的对象
方法区:常量+静态变量+类信息 User user=new User(),,这个静态变量user(对象类型)存在方法区,(对象类型的值)new 出来的user在堆,也是引用关系
本地方法栈:native修饰本地方法接口 c/c++语言实现
每个线程都需要分配内存空间---栈,本地方法栈,程序计数器--------》线程私有的,
堆,方法区---------》线程共享
堆:年轻代(Eden,survivor),老年代----》存放new 出来的对象
先放Eden区,当满了之后,会gc---minor gc(young gc)---字节码执行引擎在后台开启的垃圾收集
线程的GC root:根节点-线程栈的本地变量、静态变量、本地方法栈的变量等。。。。。
从(栈,方法区--本地变量,静态变量)根节点找,直接引用对象,找到就标记为非垃圾对象
复制到空的survivor区,然后其他的直接清理,然后继续,下次GC 的区域变为Eden和这块已经应用的survivor区,
然后继续根据节点找,可以用的,放进另外的survivor区,之前的继续清空。会用分代年龄来区分一下
对象Object是由对象头(mark word标记字段--GC的分代年龄/锁状态/线程持有锁/时间戳、类型指针、数组长度)和实例数据组成
当一个对象的分代年龄为15,就是15次GC都没有清理,就进入老年代
当老年代满了之后,字节码执行引擎会进行full GC,所有区里的东西----会OOM报错
JVM调优:避免YGC和full GC,或者使时间尽量短。
STW Java里面字节执行引擎只要开始执行GC,Java虚拟机就会停止用户线程。。为了保证当前的对象状态不会变化
线程执行完,会释放局部变量空间。
方法区(元空间),1.8之前,叫做永久代。1.8之后叫元空间----》直接内存(常量+静态变量+类信息)。
案例:
频繁full GC要怎么办 full GC比较影响性能。JVM调优就是为了减少full GC
对象的大小====就是成员变量之和+对象包+队形
当前线程结束,方法对象里面的就变成垃圾对象。当Eden满了之后,就minor GC
当有一批对象的大小对于survivor区域的大小的50%,就直接进入老年代。所以,会有优化设置,以免老年代储存一堆无意义的垃圾,
运行时数据区---
程序计数器PCR(线程私有,当前线程执行字节码的行号指示器)、虚拟机栈VM stack、本地方法栈、堆、方法区