青海餐饮网站建设,公司信息网站建设目标,青海建设银行的官方网站,湖南seo优化按天付费欢迎大家关注我的微信公众号#xff1a;
目录
JVM整体结构及内存模型
JVM内存参数设置 JVM整体结构及内存模型
首先附一段简单代码#xff0c;我们从代码层面来讲解内存模型
public class Math {public static final int initData 666;public static User user new …欢迎大家关注我的微信公众号
目录
JVM整体结构及内存模型
JVM内存参数设置 JVM整体结构及内存模型
首先附一段简单代码我们从代码层面来讲解内存模型
public class Math {public static final int initData 666;public static User user new User();public int compute() { //一个方法对应一块栈帧内存区域int a 1;int b 2;int c (a b) * 10;return c;}public static void main(String[] args) {Math math new Math();math.compute();System.out.println(test);}}
JVM内存模型图 以JDK8为例JVM虚拟机内存分为堆内存、栈内存、方法区(元空间)、本地方法栈及程序计数器
栈内存线程 每开启一个线程栈内存都会为每个线程分配一块区域线程中每个方法对应一块栈帧内存区域。main方法是一个栈帧main方法中调用了computer()方法因此computer()也是一个栈帧。根据先进后出原则每一个栈帧都按顺序从下至上排列。每个栈帧内存区域都包括局部变量表、操作数栈、动态链接及方法出口。 栈和局部变量通过JVM指令会进行一些操作。执行int a 1首先将常量压入栈。jvm指令iconst_1将int类型常量1压入操作数栈。然后将栈中的值存入局部变量。指令istore_1 将int类型值存入局部变量1。此时局部变量表中a1。执行int b 2iconst_2将int类型常量2压入操作数栈istore_2 将int类型值存入局部变量2。此时局部变量表中b2。执行int c (a b) * 10iload_1 从局部变量1中装载int类型值1iload_2 从局部变量2中装载int类型值2放入操作数栈iadd 执行int类型的加法123。然后bipush 将一个8位带符号整数压入栈也就是将10压入操作数栈。之后imul 执行int类型的乘法即3*1030将结果30重新压入操作数栈。istore_3 将int类型值存入局部变量3局表变量表中为int c 30。iload_3从局部变量3中装载int类型值3放入操作数栈将30重新压回操作数栈最后ireturn 从方法中返回int类型的数据即执行return c。 动态链接math.compute()方法调用其实就在常量池中的一个个常量。当代码执行到该方法时需要解析符号在方法区里去找寻对应的符号的直接内存地址。 方法出口当执行完compute()方法之后需要回到主线程里继续执行下面的代码。那回到什么位置执行哪行代码这些信息都存在方法出口里来找到继续执行的位置。
注意main()方法里创建了一个math对象我们知道对象一般是放在堆内存里的那么此时main栈帧里的局部变量表对应的math内存区域存放的就是堆内存中Math对象的内存地址。因此栈内存跟堆内存的关系也表示栈内存里会存放很多堆内存里的内存地址。
程序计数器 程序计数器用于计算jvm的操作步骤每操作一次计数器1相当于索引来找到对应的操作内容执行对应的指令。
方法区元空间 元空间存放的是常量、静态变量、类元信息等。 当代码load到内存中时会解析为运行时常量池之后会详细解释文本不在这里展开叙述。
本地方法栈 java很多方法都是执行本地方法比如new Thread().start()这里的start()就是调用本地方法他的底层是由C或C来实现的。本地方法栈就是为这些本地方法来分配内存空间。
堆内存 堆内存主要分为年轻代和老年代分配比例一般为1:2。年轻代又分为伊甸园区和幸存区S0与S1分配比例一般为8:1:1。我们新创建的对象一般存放在伊甸园区。当伊甸园区内存放满时触发Young GCMinor GC将不再被其他对象所引用的对象进行销毁而仍然有用的对象会放入S0区并随着young gc不断回收幸存的对象会不断在S0与S1之间来回存放并且每幸存一次生存年龄1。当幸存对象生存年龄达到15时会存入老年代。若老年代也满了那么这个时候将产生FullGCMajorGC进行老年代的内存清理。若老年代执行了Full GC之后发现依然无法进行对象的保存就会产生OOM异常“OutOfMemoryError”。
JVM内存参数设置 Spring Boot程序的JVM参数设置格式(Tomcat启动直接加在bin目录下catalina.sh文件里)
java -Xms2048M -Xmx2048M -Xmn1024M -Xss512K -XX:MetaspaceSize256M -XX:MaxMetaspaceSize256M -jar microservice-eureka-server.jar -Xss每个线程的栈大小
-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:MetaspaceSizeN和 -XX:MaxMetaspaceSizeN
-XXMaxMetaspaceSize 设置元空间最大值 默认是-1 即不限制 或者说只受限于本地内存大小。
-XXMetaspaceSize 指定元空间触发Fullgc的初始阈值(元空间无固定初始大小) 以字节为单位默认是21M左右达到该值就会触发full gc进行类型卸载 同时收集器会对该值进行调整 如果释放了大量的空间 就适当降低该值 如果释放了很少的空间 那么在不超过-XXMaxMetaspaceSize如果设置了的话 的情况下 适当提高该值。这个跟早期jdk版本的-XX:PermSize参数意思不一样-XX:PermSize代表永久代的初始容量。
由于调整元空间的大小需要Full GC这是非常昂贵的操作如果应用在启动的时候发生大量Full GC通常都是由于永久代或元空间发生了大小调整基于这种情况一般建议在JVM参数中将MetaspaceSize和MaxMetaspaceSize设置成一样的值并设置得比初始值要大对于8G物理内存的机器来说一般我会将这两个值都设置为256M。