概述:
内存是硬盘和cpu的中间桥梁,jvm内存布局规定了java在过程中内存申请、分配、管理的策略
内存布局如下图
Heep(堆)
Heep是OOM故障最主要的发源地,他存储的几乎多有的实例对象。
Heep内是由垃圾收集器自动回收的。
启动时设置堆内存的初始值参数: -Xms... (最小堆内存) -Xmx...(最大堆内存)
在运行期间,堆空间不断的扩容和收缩,所以设置初始值时,Xms和Xmx设置成一样大小,避免GC
后调整堆大小带来的不必要的系统压力
堆内存分为两大块,新生代有分为Eden s0 s1
对象新创建时在新生代,步入暮年进入老年代,
如果新创建的对象新生代无法容纳, 会将其直接放到老生代
当Eden区装满的时候会触发 YGC(Yong Garbage Collection)策略
执行策略的时候,没有被引用的直接被回收。依然存活的的对象移送到survivor,
每次移送的的时候都是将存活的对象复制到s0或s1中未使用的那块空间,然后把另一块空间完全清除。
如果移送的对象大于survivor的容量,则直接交给老年代。
一个对象如果在Survivor交换的次数达到 --XX:MaxTenuringThreshold配置的值,则直接移至老年代, 默认为15
请结合下图进行查看
Metaspace(元空间)
在JDK7之前Hotspot存在perm区(永代区), 作为元空间的前身。
但是Perm区有很大的问题,他在启动时固定大小,很难调优, 并且在FGC的时候会移动类元信息。
如果动态类加载过多,容易引发Perm区的OOM, 解决此问题,需要设置启动参数 -XX:MaxPermSize=1280m.
但是部署到新机器上,可能会因为没有修改JVM参数导致故障在现
基于以上jdk8将Perm用元空间取代
jdk8中Perm中所有内容字符串常量移至堆内存,其他内容包括类元信息、字段、静态属性、方法、常量等都移动至元空间
JVM Stack(虚拟机栈)
栈是一个先进后出的数据结构 。
JVM中的虚拟机栈是描述java方法执行的内存区域,是线程私有的;
如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常;
如果虚拟机栈可以动态扩展,如果扩展时无法申请到足够的内存,就会抛出OutOfMemoryError异常
Native Method Stacks(本地方法栈)
在JVM中是线程私用的;
服务于Native方法;
线程调用本地方法时,则不在受JVM约束;
本地方法可以通过JNI(Java Native Interface) 来访问虚拟机运行时的数据去,甚至可以调用寄存器。
Program Counter Register程序计数寄存器
请看这篇文档了解Program Counter Register