代码准备:
模型图准备:
代码结合模型分析:
1、当我们执行main方法的时候,会为主线程在栈中开辟一小块空间,也可以称为(线程栈),也就是说jvm会为每一个线程在栈中开辟一块独立空间。
2、在main线程栈中为main()方法开辟一块栈帧。
3、执行代码new TestClass() ,在堆中开辟一块空间保存新建对象。这时候main方法栈帧中会有一块局部变量表,存储的是testClass,这里实际是对象的地址指针。
4、执行testClass.methodTest()代码,为methodTest()方法在main线程栈中开辟一块栈帧。
5、下面执行methodTest()方法代码逻辑:
- 把int 类型常量1 压入操作数栈——>将int类型值存入局部变量a。
- 把int 类型常量3 压入操作数栈——>将int类型值存入局部变量b。
- (从局部变量a中装载int类型值1,从局部变量b中装载int类型值3) ——>执行加法——>将和 值压入操作数栈——>将int类型和值存入局部变量c。
- 从局部变量c中装载int类型值。
- 返回最终结果到主线程中。
JVM内存参数设置:
-Xss:每个线程的栈大小
-Xms:设置堆的初始可用大小,默认物理内存的1/64
-Xmx:设置堆的最大可用大小,默认物理内存的1/4
-Xmn:新生代大小
-XX:NewRatio:默认2表示新生代占年老代的1/2,占整个堆内存的1/3。
-XX:SurvivorRatio:默认8表示一个survivor区占用1/8的Eden内存,即1/10的新生代内存。
关于元空间的JVM参数有两个:-XX:MetaspaceSize=N和 -XX:MaxMetaspaceSize=N
-XX:MaxMetaspaceSize: 设置元空间最大值, 默认是-1, 即不限制, 或者说只受限于本地内存大小。
-XX:MetaspaceSize: 指定元空间触发Fullgc的初始阈值(元空间无固定初始大小), 以字节为单位,默认是21M左右,达到该值就会触发full gc进行类型卸载, 同时收集器会对该值进行调整: 如果释放了大量的空间, 就适当降低该值; 如果释放了很少的空间, 那么在不超过-XX:MaxMetaspaceSize(如果设置了的话) 的情况下, 适当提高该值。这个跟早期jdk版本的-XX:PermSize参数意思不一样,-XX:PermSize代表永久代的初始容量。
由于调整元空间的大小需要Full GC,这是非常昂贵的操作,如果应用在启动的时候发生大量Full GC,通常都是由于永久代或元空间发生了大小调整,基于这种情况,一般建议在JVM参数中将MetaspaceSize和MaxMetaspaceSize设置成一样的值,并设置得比初始值要大,对于8G物理内存的机器来说,一般我会将这两个值都设置为256M。
补充堆中垃圾收集:
堆空间划分可以分为新生代和老年代,默认比例是1:2;新生代又分为eden和survivor0、survivor1默认比例是8:1:1;当一个新的对象产生,会先放在eden区,当第一次触发minorGC机制时会把eden区仍存活的对象复制到survivor0中并且存活对象分代年龄加1,然后清空eden,第二次触发minorGC机制时会把eden区和survivor0中仍存活的对象复制到survivor1中,然后把eden区和survivor0清空并且存活对象分代年龄加1。当分代年龄达到阈值(默认15),会把这些对象放到老年代中。