jvm内存模型

jvm内存模型

参考 https://www.cnblogs.com/newAndHui/p/11168791.html

img

JVM内存模型其实就是JVM在启动的时候从操作系统内存中要了一块大内存,然后将这个大内存分成五个区域:方法区、堆区、虚拟机栈、本地方法栈、程序计数器。 

​ 其中方法区、堆区是线程共享的

​ 虚拟机栈、本地方法栈、程序计数器是线程私有的

程序计数器

维护的只是下一条待执行命令的地址,所以不会OOM

虚拟机栈

​ 虚拟机栈描述的方法执行的内存模型。在每个方法执行的同时会创建一个栈帧,用于存储局部变量表、操作数栈、动态连接、方法出口等信息。每一个方法调用执行完成,都对应着一个栈帧在虚拟机中入栈到出栈的过程。

​ 局部变量表:存放的是方法参数和方法内定义的变量。局部变量表在编译时就确定了局部变量表的大小, 一个局部变量可以保存一个类型为boolean、byte、char、short、int、float、long、double、reference和returnAddress类型的数据。 long和double占用2个局部变量空间,其余类型占用1个局部变量空间。

​ 操作数栈:和局部变量表一样,操作数栈在编译时也确定了栈深度。操作数栈可以理解为java虚拟机栈中的一个用于计算临时数据的存储区(寄存器)。

​ 动态连接: 一个方法调用另一个方法,在栈帧中只会存储另一个方法的符号引用,需要将其转换成内存地址。

​ 方法出口:保存现场和恢复现场。

虚拟机栈的大小默认是1M。

本地方法栈

java调用c/c++的动态链接库,运行里面函数所需要的栈。JNI

​ Hot-Spot虚拟机直接就把本地方法栈和虚拟机栈合二为一。与虚拟机栈一样,本地方法栈也会在栈深度溢出或者栈扩展失败时分别抛出StackOverflowError和OutOfMemoryError异常。

方法区

​ 方法区只是一个java虚拟机的规范,在jdk8以前方法区的具体实现是***永久代***,jdk8方法区的具体实现***元空间***

​ 主要存储类的元信息(IntanceKlass)

​ Java7及以前版本的Hotspot中方法区位于永久代中。同时,永久代和堆是相互隔离的,但它们使用的物理内存是连续的。 永久代的垃圾收集是和老年代捆绑在一起的,因此无论谁满了,都会触发永久代和老年代的垃圾收集。 但在Java7中永久代中存储的部分数据已经开始转移到Java Heap或Native Memory中了。比如,符号引用(Symbols)转移到了Native Memory;字符串常量池(interned strings)转移到了Java Heap;类的静态变量(class statics)转移到了Java Heap

​ 永久代( PermGen space ):堆内存的一块逻辑区域。主要存储类的结构信息,所以对动态生成类的情况比较容易出现永久代的内存溢出,比如在jsp页面比较多的情况下,就会出现内存溢出。测试:设置PermGen Space大小为8M,死循环通过不同的类加载器加载class文件。会出现异常 img

​ 元空间(Metaspace):元空间和永久代的最大区别就是, 元空间不再与堆连续, 不在虚拟机中,而是直接使用的本地内存( 直接内存是调用native方法分配的内存,不属于JVM管理的内存 )。可以通过以下参数来指定元空间的大小:

  1. -XX:MetaspaceSize,初始空间大小,达到该值就会触发垃圾收集进行类型卸载,同时GC会对该值进行调整:如果释放了大量的空间,就适当降低该值;如果释放了很少的空间,那么在不超过MaxMetaspaceSize时,适当提高该值。元空间最小是21807104字节 20.75M。
  2. -XX:MaxMetaspaceSize,最大空间,最大默认是4G。
  3. -XX:MinMetaspaceFreeRatio,在GC之后,最小的Metaspace剩余空间容量的百分比,减少为class metadata分配空间导致的垃圾收集。
  4. -XX:MaxMetaspaceFreeRatio,在GC之后,最大的Metaspace剩余空间容量的百分比,减少为class metadata释放空间导致的垃圾收集。

java -XX:+PrintFlagsFinal -version | grep Metaspace

在这里插入图片描述

如何调优:

  1. 设置最大值和最小值相等(防止内存抖动)
  2. 设置成物理内存的1/32(阿里的规范)
  3. 使用工具查看元空间大小:visualVM,arthas

为什么元空间要替代永久代:

  1. 避免oom 。因为通常使用PermSize和MaxPermSize设置永久代的大小就决定了永久代的上限,但是不是总能知道应该设置为多大合适, 如果使用默认值很容易遇到OOM错误。
  2. gc算法。

堆区

堆区先线程共享的区域,存放的是java中的对象。

在这里插入图片描述

-Xms 堆内存初始大小,默认内存大小:系统64/1

-Xmx 堆内存最大值,默认内存大小:系统4/1

新生代(年轻代):新对象和没达到一定年龄的对象都在年轻代 。占堆内存的1/3

老年代:被长时间使用的对象,老年代的内存空间应该要比年轻代更大 。占堆内存的2/3

GC流程:

​ 新创建的对象,需要先进行内存空间申请。这时候判断Eden区是否能足够的空间存放对象,如果有,则直接防区Eden区。如果Eden区的内存空间不足,会进行一次Minor GC(Young GC),将Eden区的无用的内存空间进行清理,清理后的对象放入from survivor区(此时存活的对象的分代年龄+1),释放Eden区的空间。然后等到下次Eden区内存不足时,会再次触发一次Minor GC,这次Minor GC会将Eden区和 from survivor区存活的对象复制到to survivor区(此时存活的对象的分代年龄+1),然后释放新生代剩余90%的空间,周而复始,始终会有一个survivor空闲,作为下一次minor gc存放对象的空间。当存活的对象分代年龄达到一个阈值(默认是15),就会放入老年代。垃圾回收算法后续再总结。

​ 上面只提到了一种进入老年代的方式,那就是分代年龄达到阈值,除了这一种方式,还有其他的方式的对象会被放入老年代:

  1. 动态对象年龄判定。当其中一个survivor中同一年龄的对象大于这块survivor区域的50%,那么大于等于这个分代年龄的对象就会进入老年代。(比如分代年龄为7的一批对象超过了survivor的一半,那么>=7的分代年龄的对象会进入老年代,剩余的对象依然在新生代)
  2. 大对象直接进入老年代。可以设置一个jvm参数 -XX:PretenureSizeThreshold: 1048576 即1M(PretenureSizeThreshold 默认值是0,意味着任何对象都会现在新生代分配内存),当创建大于1M的对象直接进入老年代,避免在新生代出现大对象在survivor区域内来回复制才能进入老年代。
  3. Minor GC 之后的对象在survivor区域放不下,直接放入老年代。
  4. 空间担保。在进行Minor GC时,会先判断一下老年代的剩余内存是否大于新生代对象的总和,如果大于,那这次Minor GC是安全的,可以放心的gc。但是如果不大于的话,JVM就需要判断HandlePromotionFailure这个参数是否设置了(jdk1.6之后默认设置开启),如果设置了,那么会继续判断老年代的剩余大小是否是大于***历次晋升到老年代的对象的平均大小***,如果大于,则进行Minor GC,但是这一次的gc是有风险的(如果存活的对象大小 大于了老年代可用内存的大小,会进行Full GC),如果小于或者没有设置,则进行Full GC

Minor GC主要是对新生代的对象进行垃圾回收:当Eden区满时,触发Minor GC。

Full GC主要是对老年代的对象进行垃圾回收,Full GC触发的条件:

  1. System.gc()方法的调用 。此方法的调用是建议JVM进行Full GC,虽然只是建议而非一定,但很多情况下它会触发 Full GC,从而增加Full GC的频率,也即增加了间歇性停顿的次数。
  2. 老年代空间不足,当执行 Full GC后空间仍然不足,会抛出 java.lang.OutOfMemoryError: Java heap space
  3. 空间担保失败
  4. metaspace空间不足也会造成Full GC。

堆内存的最大值和最小值调成一样大,防止内存抖动。

MemoryError: Java heap space
3. 空间担保失败
4. metaspace空间不足也会造成Full GC。

堆内存的最大值和最小值调成一样大,防止内存抖动。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值