
根据JVM规范,JVM 内存共分为虚拟机栈,堆,方法区,程序计数器,本地方法栈五个部分。
程序计数器(线程私有):
是当前线程锁执行字节码的行号治时期,每条线程都有一个独立的程序计数器,这类内存也称为“线程私有”的内存。正在执行java方法的话,计数器记录的是虚拟机字节码指令的地址(当前指令的地址)。如果是Natice方法,则为空。
java 虚拟机栈
也是线程私有的。
每个方法在执行的时候也会创建一个栈帧,存储了局部变量,操作数,动态链接,方法返回地址。
每个方法从调用到执行完毕,对应一个栈帧在虚拟机栈中的入栈和出栈。
通常所说的栈,一般是指在虚拟机栈中的局部变量部分。
局部变量所需内存在编译期间完成分配,
如果线程请求的栈深度大于虚拟机所允许的深度,则StackOverflowError。
如果虚拟机栈可以动态扩展,扩展到无法申请足够的内存,则OutOfMemoryError。
本地方法栈(线程私有)
和虚拟机栈类似,主要为虚拟机使用到的Native方法服务。也会抛出StackOverflowError 和OutOfMemoryError。
Java堆(线程共享)
被所有线程共享的一块内存区域,在虚拟机启动的时候创建,用于存放对象实例。
对可以按照可扩展来实现(通过-Xmx 和-Xms 来控制)
当队中没有内存可分配给实例,也无法再扩展时,则抛出OutOfMemoryError异常。
方法区(线程共享)
被所有方法线程共享的一块内存区域。
用于存储已经被虚拟机加载的类信息,常量,静态变量等。
这个区域的内存回收目标主要针对常量池的回收和堆类型的卸载。

概述:栈内存针对的是每一个线程,一个线程一个栈,栈中的局部变量表中的对象存放的是该对象在堆中的内存地址;方法区中主要存放:常量+静态变量+类元信息;方法区中的静态变量对象存放的是该静态变量对象在堆内存中的地址。




概述:堆内存分为2大块,年轻代,老年代,年轻代又分为:eden区,survivor区(from,to),默认的jvm虚拟机,将堆内存分配:年轻代占1/3,eden区占8/10,from与to区分别占1/10,老年代占2/3。
流程概述:一个web应用开始运行后,新创建的对象会不断的进入到堆内存中,放入到eden区,又叫伊甸园区, 当伊甸园区放满后,会触发minorGc清理伊甸园区中的垃圾对象(垃圾对象指在堆中没有指针指向的对象),将未被清理的对象放入Survivor区中的from区,之后再次来了新的对象就进伊甸园区,当伊甸园区满了,就再次进行minorGc,清除伊甸园区的垃圾对象,这个时候对from区也进行一次清除,并将from区中未被清除的对象放入到to区,将伊甸园区中未被清除的对象也放入to区中,之后那一块区域有对象就清除那一块区域,并将未被清除的放入没有对象的那一块。当一个对象经历了15次Gc未被清除会放入到老年代,当然,还有一些对象也会被之间放入到老年代,当老年代满了后,会进行Full Gc 。
使用jdk 自带的jvm监视工具 jvisualvm 进行调优
所谓的jvm的调优 调的是什么?
jvm在执行Full GC的时候 都会去 STW(STOPWORLD) 停止世界,用户会感觉到1到两秒的卡顿
所以我们调优的目的是为了让GC的次数减少,让GC的速度(STW)加快
java -Xms3072M -Xmn2048M -Xss1M -XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=256M -jar xxxxx.jar
上述优化命令 分配堆内存3G 分配年轻代 2G 此时 eden(伊甸园)区 占1.6G survior区占400M 其中 from去200M to区200M 栈内存 1M 老年代占1G 元空间又叫方法区 占256M 、
备注
java -Xms2048M -Xmn1024M -Xss1M -XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=256M -jar C:\Users\Administrator\Desktop\bmone-server-1.0-SNAPSHOT.jar
minor gc 时清理对象会根据gcroots根来清理垃圾对象。
GcRoots根节点:线程栈的本地变量,静态变量,本地方法栈的变量等等。
将GcRoots对象作为起点,从这些节点开始向下搜索索引引用的对象,找到的对象都标记为非垃圾对象,其余标记的对象都是垃圾对象。
老年代中放的对象:1.一个对象经历了15次Gc 2.如果一个对象在Survivor区中的From区或to区放不下,或被直接放入老年代 3.线程池 4.缓存对象(使用静态初始化的对象) 5.@service注解 6.@Bean注解