深入理解JVM内存模型:Java内存管理的奥秘

1、 内存模型和运行时数据区

这一章学习java虚拟机内存模型(Java Virtual machine menory model),可以这样理解,jvm运行时数据库是一种规范,而JVM内存模型是对改规范的实现

30d9c9e99e8e78d162390295e956db57.jpeg

java虚拟机重点存储数据的是堆和方法区,所以本章节也重点从这两个方面进行比较详细描述。堆和方法区是内存共享的,而java虚拟机栈、Native方法栈、程序计数器是线程私有的

a523889edd0b783e67a9a6368cf3f6a6.jpeg

2、思维导图和图例

35fe3deb64f38c0aba73f78f1816fd61.jpeg


一个是非堆区(方法区),方法区也一般被称之为“永久代”。另外一个是堆区,分为young区和old区,young区又分为两个部分,一个是Eden区,一个是Survivor区(S0+S1),S0区也可以称之From区,S1也可以称之为To区

2a64b018d3fb93f7d6906804e8683310.jpeg

3、对象向JVM申请空间

b77844477fdfcf779936c4c97241ea2d.jpeg

4、为什么需要Survivor区?

为什么需要Survivor区?只有Eden不行吗?

假设不设计出Survivor区,Eden区进行一次MinorGC,对象就直接被送到Old区,这样一来Old区很快就被填满,Old区一满,就会进行FullGC(Old区会进行MajorGC,一般伴随着MinorGC),FullGC是很耗时的,所以设计出Survivor区的目的是减少对象被送到Old区,有一个过渡的Survivor区

补充:

  • Minor GC:新生代
  • Major GC:老年代
  • Full GC:新生代+老年代
  • Eden:S1:S2是8:1:1

5、为什么需要两个Survivor区?

需要两个Survivor区的目的是为了避免内存碎片化。为什么这么说?

假设只设计出一个Survivor区,一旦Eden区满了,就会进行Minor GC,Eden区存活的对象就会被移动到Survivor区,等下一次Eden区满时候,问题就来了,进行MinorGC就将Eden区对象硬放到Survivor区,这样就导致了对象所占的内存是不连续的

6、例子进行验证

  • 堆内存溢出

f6cb707b400b0dcaf1302c76d752e0c5.jpeg访问接口,出现内存溢出;

7653ffe7769b71090044ecaafad0928d.jpeg

可以设置参数:比如-Xms64M -Xmx512M

  • 方法区内存溢出

使用asm,maven配置:

8ccd766e92e251103a0b57fbfadd6a70.jpeg

编写代码,向方法区中添加Class的信息,注意,电脑性能不够好,不要执行此代码,很容易,造成电脑重启,太吃内存,也可以调小循环次数

d95ed7ac5811f3f4d0f38df775668d71.jpeg方法区测试接口:

edf7e47edcd4955e001981125244a169.jpeg6149f68b0e21644bbb67d3e5ae750494.jpeg处理方法,设置Metaspace的大小,比如-XX:MetaspaceSize=64M -XX:MaxMetaspaceSize=512M

  • Java虚拟机栈

在前面学习,java虚拟机栈是通过栈帧方式存储,一个方法对应一个栈帧,按照队列模式进栈,所以要测试程序导致java虚拟机栈出现问题,可以通过递归方法方式进行测试:

7ea424cd94bfdde3c1a768d4011fc97a.jpegStackOverflow,栈溢出异常:

ec207acd711c3e69200ba46fbf16090e.jpeg处理方法,设置-Xss256k:设置每个线程的堆栈大小。JDK 5以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值