一、jvm内存模型图
JVM内存模型二、内存模型描述
堆:所有新建对象都会在堆中开辟内存
方法区(本地内存):存放类信息,方法信息,静态变量等数据(不设置默认21M,建议最好设置,且设置一样,很多程序因为该值设置问题,导致fullGC,fullGC后如果未设置,则会自动扩容
由于调整元空间的大小需要Full GC,这是非常昂贵的操作,如果应用在启动的时候发生大量Full GC,通常都是由于永久代或元空间发生了大小调整,基于这种情况,一般建议在JVM参数中将MetaspaceSize和MaxMetaspaceSize设置成一样的值,并设置得比初始值要大,对于8G物理内存的机器来说,一般我会将这两个值都设置为256M。)
堆和方法区属于线程共享
栈(java虚拟机栈):开启一个线程时建立,栈里面包含 局部变量表(用于存放方法执行时产生的变量)、操作数栈(执行程序操作,比如 加减乘除)、动态链接(存放方法的变量,类似于 执行方法的内存地址,运行时才能解析)、方法出口(方法返回)(默认1M)
程序计数器:当程序执行到那个步骤会记录在程序计数器(个人理解,应为CPU切换,导致线程被挂起,唤醒时需要从程序计数器中获取执行位置,继续执行)
本地方法栈:存放native方法执行时的变量等元素(目前基本上用不到,为了java最开始兼容其他程序准备的)
三、GC
对象初始化时先放入Eden区,当Eden区超过设置大小时,发生minor gc,回收不了的对象,转移到S区,后面再发生minor gc时,是回收Eden区和Survivor区一起,第一次转移到s0,第二次就会转移到s1区;每个对象经历一次GC,则会在对象头中记录GC年龄,默认且最大15,则会被迁入老年代,当老年代到达设置大小时,则会发生full gc,如果gc回收的内存不够,则会抛出OOM(内存溢出)异常;
每次GC都会发生stop the world(工作线程停止工作,防止产生新垃圾),每次JVM调优都是为了减少GC次数以及时间
GC时怎么判断该对象是否可以回收,根据GcRoot引用来查找,虚拟机栈和本地方法都可以算是GcRoot的一部分
虚拟机工作机制四、参数设置
-Xms2048M -Xmx2048M -Xmn1024M -Xss512K -XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=256M
-Xss:每个线程的栈大小
-Xms:初始堆大小,默认物理内存的1/64
-Xmx:最大堆大小,默认物理内存的1/4
-Xmn:新生代大小
-XX:NewSize:设置新生代初始大小
-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代表永久代的初始容量。
网友评论