存放对象,也是发生线程安全的地方
new对象分配在Eden区间
老年代
STW(stop the world)
线程独立内存空间,局部变量存放位置。不同线程有自己独立的内存空间
栈帧: 一个方法对应一个独立的栈帧空间
局部变量表
存放局部变量,类似数组结构
局部变量如果new 对象。对象是存在堆空间。局部变量表存放内存的引用地址
操作数栈
是一个数据在操作时临时存放的内存空间。也是一个栈结构
动态链接
程序在加载的时候才能确认一些调用,所以有些接口的调用是动态的。
方法出口
记录方法进入时的位置,在方法调用结束返回。
-xss设置单个栈的空间大小(一个线程)
理论上:单个栈的空间分配越少,能开的线程就越多。其他影响的因素还有句柄数等信息
元空间的内存是外部内存。方法区就是在元空间。元空间的初始大小是21MB
-XX:MetaSpaceSize指定元空间的初始空间大小,默认是21M,达到该值就会触发full GC进行类型卸载
同时收集器会对该值进行调整;如果释放了大量的空间,该值就会调低;如果释放了很少的空间,那么在不超过
-XX:MaxMetaSpaceSize的情况下适当提高该值。由于调整元空间大小需要触发Full GC,这是非常昂贵的操作,如果应用
在启动的时候触发大量Full GC,通常是由于永久代或是元空间发生了调整,基于这种情况,一般建议在JVM参数中将MetaSpaceSize和MaxMetaSpaceSize设置成一样,并设置得比初始值要大。对于8G的物理内存我们一般设置256MB
记录程序执行的指针的位置,程序的内存地址
程序执行引擎会根据代码执行的进度修改计数器。程序计数器存在的意义在于多线程切换时能记录下来程序执行的位置。
1、对象动态年龄判断机制
当前放对象的Survivor区域里(其中一块区域,放对象的那块s区),一批对象的总大小大于这块Survivor区域内存大小的50%(-XX:TargetSurvivorRatio可以指定),那么此时大于等于这批对象年龄最大值的对象,就可以直接进入老年代了。例如Survivor区域里现在有一批对象,年龄1+年龄2+年龄n的多个年龄对象总和超过了Sruvivor区域的50%,此时就会把年龄n(含)以上的对象都放到老年代,这个规则其实是希望那些可能长期存活的对象,今早进入老年代。对象动态年龄判断机制一般是在minor gc之后触发的。
2、老年代空间分配担保机制
在做minor gc 之前会进行校验,老年代剩余的空间是否能放下所有
支持每秒1000的订单,一共3台机器 4核8G。均分到每台上需要承担300左右的并发
内存估算
订单对象每个差不多1KB,每秒差不多300KB订单对象。下单还涉及其他对象,如库存、优惠价卷、积分等,我们放大20倍。(300KB*20)/秒对象生成,每秒差不多300KB订单对象。可能同时还有其他操作,如订单查询等,我们再放大10倍。每秒产生60M的对象,差不多一秒以后都变为垃圾对象
初始jvm参数设置
老年代:年轻代 默认2:1
java -Xms3072M -Xmx3072M -Xss1M -XX:MetaspaceSize=512M -XX:MaxMetaspaceSize=512M -jar microservice-eureka-server.jar
初始内存模型
因为幸存区太小,触发动态年龄判断机制,会往老年代放。导致触发fullGC
调整jvm参数,提高年轻代内存
java -Xms3072M -Xmx3072M -XmN2048m -Xss1M -XX:MetaspaceSize=512M -XX:MaxMetaspaceSize=512M -jar microservice-eureka-server.jar
调整后的内存模型
避免引起空间担保机制
后续更新JVM实战常用命令的使用