JVM学习(一)内存结构

你还记得吗?你还记得吗?你还记得吗?从来没有记住过,又何来忘记呢!

内存结构可以说是面试100%会出现的!为了应付面试,赶紧百度、看书,结果面试官问的深一点就嗝屁了!还不如说不会呢,可是这么基础的知识点都不会,所谓的会也可能是理论层面的,我在网上看多了很多相关的文章,互相印证,大部分的文章都是理论,理论还是理论。没错理论是实践的基础,可是知行合一才是完整的。废话不多说了,下面进入正题。

内存区域的划分:

共享区域:堆、方法区

私有区域:程序计数器、栈、本地方法栈

注:1.8开始没有单独的方法区,而是在堆中分配一块区域作为方法区,通过命令查看内存情况可知,真的没有单独方法区

1:程序计数器

      计数器到底记得是什么数呢?当前线程所执行的字节码的行号指示器。解释器就是通过计数器来控制分支、循环、跳转、异常处理、线程恢复等,为了保证每个线程正确执行,计数器是每个线程私有的。在形象一点就是查看class文件,code对应的每一行都是指令,计数器就是要记录当前栈正在执行的指令行,当线程切换后继续执行时,从上一次的指令行继续执行,

如果执行native方法,则计数器的值为空(undefined)

程序计数器特点:

    线程私有、生命周期和线程相同、无OutOfMemoryError异常

2:虚拟机栈

    线程私有的,和程序计数器的生命周期相同,虚拟机栈描述的是java方法执行的内存模型,每个方法执行时会创建一个栈帧。栈帧主要保存局部变量表、操作数栈、动态链接、方法出口,局部变量表存放了编译期可知的各种基本类型、对象引用(指针、句柄、对象的位置)、returnAddress类型(指向一条字节码指令)。线程请求的栈深度大于虚拟机允许的深度抛出StackOverFlowError(递归调用很容易抛出),如果虚拟机支持扩展空间,当无法申请到足够空间时抛出OutOfMemoryError(如果堆内存快用尽的时候,申请栈内存就会抛出)

虚拟机栈的特点:

  线程私有、生命周期和线程相同、抛出StackOverFlowError和OutOfMemoryError、存放内容(局部变量表、操作数、动态链接、方法出口)

3:本地方法栈

  和虚拟机栈的作用相同,只不过执行的是本地方法,而非java方法

4:堆

  所有对象的实例和数据都要在堆上分配,堆还可以细分为新生代、老年代、Eden空间、From Survivor空间、To Survivor空间,从内存分配角度可以划出多个线程私有的分配缓冲区TLAB,无论怎么划分和存在内容无关,仍然是实例,划分的目的就是为了更好的回收内存,或者更快的分配内存。物理空间可以不连续,但是逻辑空间要连续,如果无法扩展抛出OutOfMemoryError,可通过-Xmx -Xms 控制,无法扩展抛出OutOfMemoryError

源码:

        byte[] allocation1, allocation2, allocation3,allocation4;

        allocation1 = new byte[1 * _1MB];

        allocation2 = new byte[2 * _1MB];

        allocation3 = new byte[3 * _1MB];

        allocation4 = new byte[4 * _1MB];

打印内存情况

Heap Parameters:

Gen 0:  eden [0x04800000,0x04c28068,0x05000000) space capacity = 8388608, 51.95436477661133 used

  from [0x05100000,0x0517b108,0x05200000) space capacity = 1048576, 48.072052001953125 used

  to  [0x05000000,0x05000000,0x05100000) space capacity = 1048576, 0.0 usedInvocations: 1

Gen 1:  old  [0x05200000,0x05800030,0x05c00000) space capacity = 10485760, 60.000457763671875

可知内存的地址范围是0x04800000-0x05c00000

上图中的4个byte数组对应的内存地址为0x04800000、0x05500050、0x05300010、0x05200000,那么就足以说明这四个对象存储在堆里

堆的特点:共享内存、生命周期和虚拟机相同、抛出OutOfMemoryError,保存所有的new的实例

5:方法区

    线程共享的内存区域,用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码数据,虚拟机规范描述方法区为的一个逻辑部分,别名非堆,主要是和堆区分开。无法扩展抛OutOfMemoryError,关于类的具体细节会有专门章节

方法区特点:

共享内存、生命周期和虚拟机相同、抛出OutOfMemoryError,保存类信息、常量、静态变量、即时编译器编译后的代码数据

6:常量池

运行时常量池是方法区的一部分,class文件中除了有版本、字段、方法、接口信息外还有一项信息是常量池,用于存放编译后生成的字面量和引用,这部分内容将在类加载后进入方法区的运行时常量池中存放。运行过程中新的常量也可以放入常量池,允许扩展,无法扩展抛OutOfMemoryError

常量池特点:

共享内存、生命周期和虚拟机相同、抛出OutOfMemoryError,保存常量

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • JVM内存模型Java虚拟机(Java Virtual Machine=JVM)的内存空间分为五个部分,分别是: ...
    光剑书架上的书阅读 2,651评论 2 26
  • 一、内存模型 Java内存模型,往往是指Java程序在运行时内存的模型,而Java代码是运行在Java虚拟机之上的...
    keep_trying2017阅读 605评论 0 0
  • 文章转自 http://blog.csdn.net/u012152619/article/details/4696...
    云狗狗狗狗狗阅读 629评论 1 4
  • 我最亲爱的自己,每当困难,坎坷来临时,我不会像之前一样的愤怒你,嘲笑你,苛责你,因为你就是我小时候的样子,我要爱你...
    薛功灿阅读 236评论 0 0
  • 2018年的最后一天,我是在值班中度过的,早餐八点半来到这里,再也没出去过,说实话我不讨厌值班,但是很讨厌这个办公...
    sxwwxl阅读 162评论 0 0