前言

java作为一款能够自动管理内存的语言,与传统的c/c++语言相比有着自己独特的优势。虽然我们无需去管理内存,但为了防范可能发生的异常,我们需要对java内部数据如何存储有一定了解,已应对突发问题,写出更好的程序

JVM对运行时程序内存的划分

java程序在被编译成字节码后,由JVM执行,执行期间产生的所有数据,会被分门别类的存储在JVM预设好的区域里,具体情况如下所示

java6时方法区还属于JVM管理的内存,那时俗称为“永久代”,负责存储:被虚拟机加载的类型信息、方法信息、常量(包括字符串常量)、静态变量等等

java7时把永久代里的字符串常量池、静态变量移动到了堆中

java8废除永久代,改用元空间来实现方法区,原来java7中永久代的剩余内容移动到元空间中

以下为java8的内存分布图

Tips:红色是线程共享的,黄色是线程私有的

接下来我们着重讨论Java8中的内存分布情况

JVM管理的内存

这部分内存在JVM中,由JVM直接分配,初始大小、最大大小都可以由JVM进行配置

程序计数器

是一段较小的内存空间,用于告诉字节码解释器下一条执行哪一个字节码指令。是唯一一个在《java虚拟机规范》没有规定任何OutOfMemoryError的区域

每条线程必须有独立的程序计数器,以确保切换线程时,线程可以在正确的位置继续执行字节码

Tips:当执行Native方法时,计数器值为空(undefined)


虚拟机栈

我们平常俗称的栈指的就是虚拟机栈,用来描述和存储Java方法的内存模型。里面的数据生命周期在编译时就已经确定了,比如局部变量方法调用结束就该释放,内存很容易管理,所以并不是很依赖GC

具体行为:

每当执行一个方法时,JVM就会创建一个栈帧放进虚拟机栈中

栈帧的内容包括但不限于:

  1. 局部变量表(也包括形参)

    • 八大基本数据类型
    • 引用类型(直接指针或者句柄,由具体的JVM实现决定)
    • returnAddress类型 (用于方法结束回到原来的字节码位置继续执行)
  2. 操作数栈
    • 开始时是空的,运行后逐渐入栈出栈,比如算数运算就是操作数栈进行的
  3. 动态连接
  4. 方法出口

直到方法执行结束,JVM就会将此方法的栈帧出栈

显然,如果多个线程共用同一虚拟机栈,会出现某个线程的方法还没执行完毕,又被另一线程的栈帧入栈,破坏了方法数据结构。所以虚拟机栈是线程私有的

returnAddress作用

用于执行完方法后回到调用方法的位置继续往下执行

当一个栈帧入栈时,returnAddress保存当前程序计数器的值,即当前字节码位置,然后开始执行方法,方法执行结束后,用returnAddress的值恢复程序计数器,即回到调用方法时的字节码位置


本地方法栈

几乎与虚拟机栈一样的作用,其区别是,本地方法栈为本地Native方法服务,通常是本地的C/C++库的方法,而虚拟机栈是为java方法服务的


堆区

通常是JVM中最大的内存区域,也是垃圾收集器GC最经常光顾的区域,里面的数据生命周期无法在编译时确定,需要GC来帮助判断是否是“死亡变量”,以回收没必要的内存。

存储的内容:

  1. 对象的实例
  2. 数组
  3. 字符串常量池
    • 物理上在堆区,逻辑上是方法区的内容
  4. 静态变量
    • 物理上在堆区,逻辑上是方法区的内容

本地内存

默认情况使用大小只受限于本地内存的实际大小

但我们任可以通过JVM配置限制使用大小

这里面的数据一般不经常变动,存放在这里被JVM间接管理较为合适(间接管理速度肯定比JVM内部的慢些)

方法区(元空间)

java8使用元空间来实现的方法区,《Java虚拟机规范》中方法区为堆区的逻辑部分,堆中的对象依靠方法区存储的类信息来生成实例

存储的内容:

  1. 运行时常量池

    • 字面量
    • 符号引用
  2. 类信息
    • 类型

      • 完整名
      • 修饰符
      • 父类、接口信息
      • 名称
      • 类型
    • 方法
      • 名称
      • 参数
      • 返回值
      • 字节码

以上包含了一些有代表性的内容,并不代表方法区存储的全部内容


直接内存

此部分并不常用,至少对我目前来说。

在jdk1.4中加入了NIO(New Input/Putput)类,引入了一种基于通道(channel)与缓冲区(buffer)的新IO方式,它可以使用native函数直接分配堆外内存,然后通过存储在java堆中的DirectByteBuffer对象作为这块内存的引用进行操作,这样可以在一些场景下大大提高IO性能,避免了在java堆和native堆来回复制数据。--《深入理解java虚拟机》


Java8-JVM内存区域划分白话解读的更多相关文章

  1. JVM内存区域划分及垃圾回收

    第一部分.闲扯+概述 近来在研读<深入理解java虚拟机>一书,读完之后做个小结,算是记录一下自己的学习所得,在成长的路上,只能死磕. 要理解JVM,就要先从其内存区域划分开始,知道其由几 ...

  2. JVM内存区域划分

    前言 Java程序的运行是通过Java虚拟机来实现的.通过类加载器将class字节码文件加载进JVM,然后根据预定的规则执行.Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同 ...

  3. JVM内存区域划分(JDK6/7/8中的变化)

    前言 Java程序的运行是通过Java虚拟机来实现的.通过类加载器将class字节码文件加载进JVM,然后根据预定的规则执行.Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同 ...

  4. JVM内存区域划分Eden Space、Survivor Space、Tenured Gen,Perm Gen解释

    以下内容转自:http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=29632145&id=4616836 jvm区域总体分两 ...

  5. JVM内存区域划分Eden Space、Survivor Space、Tenured Gen,Perm Gen解释(转)

    jvm区域总体分两类,heap区和非heap区.heap区又分:Eden Space(伊甸园).Survivor Space(幸存者区).Tenured Gen(老年代-养老区). 非heap区又分: ...

  6. JVM内存区域划分Eden Space,Survivor Space,Tenured Gen,Perm Gen

    jvm区域总体分两类,heap区和非heap区.heap区又分:Eden Space(伊甸园).Survivor Space(幸存者区).Tenured Gen(老年代-养老区). 非heap区又分: ...

  7. JVM内存区域划分总结

    发现网上有两个版本的JVM内存划分,一个是按照<深入理解JVM虚拟机>上的版本,包含程序计数器等,按照是否线程共享划分. 另一个我觉得更好记一些,也更适合我自己,在这里记录一下. 首先上思 ...

  8. [转]JVM内存区域划分Eden Space、Survivor Space、Tenured Gen,Perm Gen解释

    jvm区域总体分两类,heap区和非heap区.heap区又分:Eden Space(伊甸园).Survivor Space(幸存者区).Tenured Gen(老年代-养老区). 非heap区又分: ...

  9. JVM 内存区域划分

    一.运行时数据区包括哪几部分? 根据<Java虚拟机规范>的规定,运行时数据区通常包括这几个部分:程序计数器(Program Counter Register).Java栈(VM Stac ...

随机推荐

  1. 易华录 X ShardingSphere|葫芦 App 后台数据处理的逻辑捷径

    "ShardingSphere 大大简化了分库分表的开发和维护工作,对于业务的快速上线起到了非常大的支撑作用,保守估计 ShardingSphere 至少为我们节省了 4 个月的研发成本.& ...

  2. Java初步学习——2021.10.05每日总结,第五周周二

    (1)今天做了什么: (2)明天准备做什么? (3)遇到的问题,如何解决? 今天学习了二维数组,包括二维数组的声明,和二维数组的创建.以及获取二维数组的长度,其中要注意的是二维数组是每个元素都是一维数 ...

  3. 题解 [SDOI2009]E&D/染色游戏/Moving Pebbles

    E&D 染色游戏 Moving Pebbles E&D 题目大意 给出 \(2n\) 堆石子,\(2i-1\) 和 \(2i\) 为一组.每次可以选择一组删掉其中一堆,然后从同一组另外 ...

  4. c++中的数学函数

    math.h 数学函数库,一些数学计算的公式的具体实现是放在math.h里,具体有:1 三角函数double sin (double);double cos (double);double tan ( ...

  5. 消息队列那么多,为什么建议深入了解下RabbitMQ?

    你为啥要在项目中选择xxx消息中间件? 提起消息队列,也许你的脑海里会不自觉地蹦出好多概念:JMS.Kafka.RocketMQ.AMQP.RabbitMQ.ActiveMQ.Pulsar.Redis ...

  6. 深入理解java中main方法

    理解main方法语法 深入理解main方法: 解释main方法的形式:public static void main(String[] args){} main方法调用者:虚拟机 java虚拟机需要调 ...

  7. kivy浮点布局

    from kivy.app import App from kivy.uix.floatlayout import FloatLayout class FloatLayoutWidget(FloatL ...

  8. [no code][scrum meeting] Beta 1

    $( "#cnblogs_post_body" ).catalog() 会议纪要 会议在微信群进行:集体反思alpha阶段博客分数尤其是scrum博客分数低的问题,讨论beta阶段 ...

  9. Spring DeferredResult 异步请求

    Spring DeferredResult 异步请求 一.背景 二.分析 三.实现要求 四.后端代码实现 五.运行结果 1.超时操作 2.正常操作 六.DeferredResult运行原理 六.注意事 ...

  10. 示波器分析I2C时序波形图

    对于嵌入式开发的朋友来说,I2C协议实在是再熟悉不过了,有太多的器件,采用的都是通过I2C来进行相应的设置.今天,我们就随便聊聊这个I2C协议. I2C协议中最重要的一点是I2C地址.这个地址有7位和 ...