首页
学习
活动
专区
工具
TVP
发布

Java内存模型、JVM内存模型及Java对象模型-JAVA成长之路

1. 什么是Java内存模型(JMM)

Java内存模型(Java Memory Model ,JMM)就是一种符合内存模型规范的,屏蔽了各种硬件和操作系统的访问差异的,保证了Java程序在各种平台下对内存的访问都能保证效果一致的机制及规范。

Java内存模型规定了所有的变量都存储在主内存中,每条线程还有自己的工作内存,线程的工作内存中保存了该线程中是用到的变量的主内存副本拷贝,线程对变量的所有操作都必须在工作内存中进行,而不能直接读写主内存。不同的线程之间也无法直接访问对方工作内存中的变量,线程间变量的传递均需要自己的工作内存和主存之间进行数据同步进行。

1.1 JMM就作用于工作内存和主存之间数据同步过程。他规定了如何做数据同步以及什么时候做数据同步。如图所示:

1.2 JMM的实现

在Java中提供了一系列和并发处理相关的关键字,比如 volatile、 synchronized、 final、 concurren包等。其实这些就是Java内存模型封装了底层的实现后提供给程序员使用的一些关键字。这里涉及到并发编程,我们需要了解并发编程的三个特性:原子性、可见性、有序性。这方面的知识我们留到并发编程那边再详细总结。

2. 什么是Java对象模型

      Java内存模型包含对象头、实例数据、对齐填充,如图所示:

3. JVM内存模型

运行时数据区是一种规范,而Java模型是对此规范的实现。     

模型图示:

注:前面我们总结过,非堆即方法区(JDK1.8后为元空间)

4. 从对象的创建过程了解JVM内存模型

step 1:JVM在创建对象时首先会试图在Eden区->Eden区内存不足则进行minor GC回收不活跃的对象->回收后的Eden区内存够不够->不够则执行下一步

step2:survivor区内存够?->够则将Eden区的部分复制到s区,申请空间成功。不够则查看old区,old区够则将S区的部分活跃对象复制到OLD区,Eden区部分活跃对象复制到S区,申请对象空间成功。->old区不够,则触发FullGC->fullGC后的OLD区还是不够则触发OM(OutOfMemoryError)

注:minorGC--新生代GC majorGC--老年代GC --fullGC=minorGC+majorGC

5. 拓展理解问题

4.1 为什么需要survivor区,只有Eden区不行吗?

      如果只有Eden区那么就会 有很多存活对象经过minorGC后被保存到Old区,这样Old区很快就会满,而Old区一旦内存不足就会触发FullGC(因为MajorGC一般都是伴随着minorGC的,所以可以当为fullGC),FullGC消耗的时间比较长,效率低,会大大影响程序的响应速度。

      如果Old区内存比较小则会频繁触发FullGC,如果增大Old区内存则一次FullGC的时间会更长。

注:FullGC消耗时间比较长主要是Old区采用标记清除和标记清理算法,且Old区一般对象数量庞大,一次GC的消耗时间自然要比minorGC长

5.2 为什么需要两个S区?

      为了解决内存碎片化问题。Eden区满了就会把存活对象复制到S区。下一次GC的时候Eden区和S区各有一部分存活对象,此时直接把Eden区的存活对象复制到S区,那么这两部分内存是很有可能不连续的,这就导致了碎片化问题。而分为两个S区可以保证永远有一个S区是空的,另一个S区的内存是连续的。相当于浪费了一半的S区来解决内存的碎片化问题。

5.3 为什么Eden区和S1、S0比例是8:1:1?

      因为大部分对象是“朝生夕死”的,所以Eden区应该足够大,大多数对象都在Eden区被回收。

5.4 堆内存中都是线程共享的吗?

      不是的。jvm默认会为每个线程在Eden区开辟一个buffer区域,用来加速对象的分配,称之为TLAB(ThreadLocal Allocation Buffer),TLAB内存区域较小,对象默认会在TLAB分配内存,但是如果对象比较大,则会在堆共享内存区域中分配

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20201019A0292N00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券