1. JVM虚拟机内存模型图解
- JAVA虚拟机主要由这三部分组成类装载子系统,字节码执行引擎,运行时数据区
- 上一节我们不是学了类的加载吗,那些类加载器许多都是C++帮我们做的,那么我们这个类装载子系统就是帮我们把类放入运行时数据区的(这里也就是上一节的一些程序代码)
- 放入到内存中之后,也就是运行时数据区
- 最后再通过字节码执行引擎来执行内存区里面的代码,也就是解析.class文件
2. 运行时数据区解释
2.1 栈
- 栈:(可以称为线程栈),当我们开启线程之后,就会在虚拟机栈中分配一小块的空间,用来存放局部变量等等,
- 在一个Jvm里面我们写的一个方法对应一块栈帧内存区域,
- 这里我的个人理解栈和栈帧是有区别的,当开启一个main线程的时候会在栈里面分配一块区域,这个区域就是mian这个线程用的,如果说启动了别的线程那么同样也会在栈里面分批一个其他的内存区域
- 然后在这个区域里面每调用一个方法,那么就在这个区域里面开辟一个栈帧,相当于对着区域做了分割,这个方法的局部变量等等就放在这里面,
- 因为我们的方法里面定义的变量等等之类的,应该放在一个栈帧里面,而不是随意的放在mian线程开辟的内存空间的任意区域
而且这是个栈由于他的特性,先进后出,这个也符合我们的代码运行逻辑 - 栈帧除了放局部变量还放了操作数栈,动态链接方法出口等等
这个是上一张图main方法里面的栈帧存放数据模型
这里有一个查看指令
javap -c .\PartOrderController.class > partOrder.txt
操作数栈就是需要进行临时的一块空间,也就是计算,然后把计算出来的数据放入到局部变量表中
动态链接就是把符号引用替换为直接引用
如果我们在栈里面new了一个对象,那么我们的栈帧里面的局部变量表是不是会存放一个new出来对象的局部变量,但是我们的对象一般是放在堆里面的,那么栈帧的局部变量表存放的就是这个对象的堆里面的地址
2.2 方法区
- 运行时常量池主要放在方法区
- 说简单点就是常量+静态变量+类信息
- 如果在加载的时候new了一个对象,并且是静态变量,那么同样方法区里面存储的也是堆的指针地址
2.3 本地方法栈
- 主要是为了调用一些C++代码
2.4 堆
- 堆的组成
堆分为年轻代和老年代
年轻代默认站堆得三分之一
老年代默认站堆得三分之二
当然这个配比是可以调的
年轻代又分为Eden区和seurivior区域,然后这个的比例是 8:1:1
3. Java自带的工具Jvisualvm
minor gc 回收年轻代
full gc 回收年轻代,老年代,元空间
在发生垃圾回收机制的时候会发生stop the world也就STW 停止掉用户线程
JVM调优主要就是就是减少full jc次数
4 jvm内存参数模型
-Xss是每一个线程栈的内存空间
-Xss设置的越小,每个线程栈里面能分配的栈帧就越少,但是对JVM整体来说能开启的线程就越多