JVM
2022-12-12 10:54:39 0 举报
JVM
作者其他创作
大纲/内容
OOM
栈帧1
JVM线程栈
堆内存存储几乎所有的实例对象堆内存由各个线程栈共享堆内存空间可以通过指定-Xms256M -Xmx1024M来设置最小和最大堆容量,但是堆内存在不断的扩容与回缩会带来一定的系统压力,所以生产环境直接将-Xms 和 -Xmx设置一样大小即可。
Serial回收器
幸存区
Old区(老年代)
YGC
栈帧2
栈是一种先进后出的数据结构。JVM线程栈是描述Java方法执行的内存区域,是线程私有的。每一个栈帧就代表正在调用的一个方法,调用方法的过程就是入栈出栈的过程。栈顶帧称为当前活动栈帧,代表当前正在执行的方法
操作栈
N
局部变量表是存放方法参数和局部变量的区域
serial回收器(串行收集器)是一个主要应用于YGC的垃圾回收器,在垃圾回收器的某个截断会暂停整个应用程序的执行。
结束
方法返回地址
为了能够并行的标记和整理,将空间分为两部分,一部分为已激活,一部分为未激活,垃圾回收时只需要将存活对象复制到另一块未激活的空间,然后将未激活的空前标记为已激活,将已激活的空间标记为未激活,最后清除元空间的原对象。而堆内存则是划分为一个E区和两个S区,S区分为S0和S1,YGC的时候将存活的对象复制到S1,然后清除E区和S0的对象,最后将S0标记为S1,S1标记为S0。
静态属性
程序计数器
JVM中的程序计数器是对CPU寄存器的一种抽象。它是一块很小的内存空间。每个线程都有自己的程序计数器。程序计数器的生命周期和线程的生命周期一致。字节码中的每条指令都有相对的指令地址,程序计数器的主要作用是用来存储下一条指令地址,当再次获得CPU时间片的时候就可以知道应该从哪条指令开始执行。
老年代
堆内存
字段
标记-清除算法
老年代放得下?
动态链接
Mark-Copy算法
幸存区放得下?
从每一个GC Roots出发,依次标记有引用关系的对象,最后将没有被标记的对象清除,负面效果就是会带来大量的内存空间碎片,导致需要分配一大片连续空间的时候会出现FGC。
方法
先从GC Roots出发标记存活的对象,然后将存活的对象整理到内存的一端,形成连续的已使用空间,最后将该空间之前的部分清理掉,这样的话就不会出现空间碎片问题了。
String的引用
类元信息
放置在S0/S1区域
新对象申请内存
方法区在JDK1.8之前被称为永久代,存在于JVM中,他主要存储类的信息,如果动态加载的类过多,容易产生OOM。在Java8的hotspot中移除了永久代,使用本地内存来存储类元信息,这块内存被称为元空间
标记-整理算法
垃圾回收主要是清除不再使用的对象,自动释放内存空间,JVM引入GC Roots来判断对象是否存活,如果一个对象与GC Roots之间没有直接或者间接的引用关系,则这个对象就是需要被回收的垃圾对象。一般使用静态属性中引用的对象、常引用的对象、线程栈引用的对象、本地方法栈引用的对象。
Y
CMS回收器
伊甸园放得下?
伊甸园区
垃圾回收
对象存活超过阈值?
对象的创建流程当JVM接收到NEW指令的时候,首先在元空间检查需要创建类元信息是否存在,不存在的话则在双亲委派机制下使用类的全限定名查找对应的class文件,找不到的话会抛出classnotfind异常,找到的话进行类加载,生成对应的class对象。计算对象所需要的内存空间,如果实例成员变量是引用类型的话,则只分配引用变量空间4个字节。然后在堆中划分一块内存给新的对象。对成员变量设置默认值。初始化成员变量,执行实例代码块,调用类的构造方法最后把堆内对象的首地址赋值给引用变量
对象在产生之初在新生代,步入暮年的时候进入老年代,但是老年代也接纳在新生代无法容纳的超大对象。
FGC
Young区(新生代)
分配内存
当前活动栈帧
垃圾回收器
栈顶帧
新生代=1个E区+2个S区。绝大多数对象在E区生成。E区装满时会触发YGC。YGC触发后将对E区和S区进行清除策略,没有被引用的对象直接回收,存活的对象将被复制到另一个空闲的S区中,然后交换S区的使用状态。每个对象都有一个计数器,每次YGC都会+1,通过指定-XX:MaxTenuringThreshold指定移动次数阈值,当对象移动次数到达阈值的时候就会移交给老年代。如果YGC要移动的对象大于S容量上限,则将大的对象放到老年代。
局部变量表
常量
开始
元数据区(元空间/永久代/方法区)
0 条评论
下一页