前言

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. WIN10下的VMware与Docker冲突的解决方案

    VMARE版本升级到15.5以上 WIN10升级到2004版本以上 Hyper-V为开启状态

  2. 双系统升win11(grub启动问题修复与讲解)?!?

    起 最近win11不是出来了吗.(着急修复的可以直接跳到最后一步) 于是我就突发奇想给我半年没进去的windows升个级........ 于是我找到了我win11的升级包(从我一个同学哪儿) 工具都集 ...

  3. Perl 编程 基础用法

    Perl 编程 标准头部写法 #!/usr/bin/perl -w # 标准的头部写法,-w意为显示警告 变量 $a=$b+10 # $a和$b都不需要定义,拿过来就用 Note: $flag=0 如 ...

  4. [JUC-5]ConcurrentHashMap源码分析JDK8

    在学习之前,最好先了解下如下知识: 1.ReentrantLock的实现和原理. 2.Synchronized的实现和原理. 3.硬件对并发支持的CAS操作及JVM中Unsafe对CAS的实现. 4. ...

  5. Golang通脉之包的管理

    在工程化的开发项目中,Go语言的源码复用是建立在包(package)基础之上的. 包(package)是多个Go源码的集合,是一种高级的代码复用方案,Go语言提供了很多内置包,如fmt.os.io等. ...

  6. BUAA_2020_软件工程_软件案例分析作业

    项目 内容 这个作业属于那个课程 班级博客 这个作业的要求在哪里 作业要求 我在这个课程的目标是 学习掌握软件工程的相关知识 这个作业在哪个具体方面帮我实现目标 通过对具体软件案例的分析学习软件工程 ...

  7. freemarker自定义指令

    最近项目中使用了spring boot搭建项目,使用spring security管理项目中的权限,使用freemarker作为视图层.为了将权限控制到按钮上,因此考虑直接使用spring secur ...

  8. spring cloud zuul的回退

    当我们使用 @EnableZuulProxy 注解来开启zuul的路由时,默认在@EnableZuulProxy注解上就包含了@EnableCircuitBreaker注解,即开启了断路器功能.那么在 ...

  9. 架构师之路-https底层原理

    引子 先说说我对架构师的理解.从业务能力上,需要的是发现问题和解决问题的能力:从团队建设上,需要的是能培养团队的业务能力:从项目管理上,把控好整个项目和软件产品的全生命周期. 我搜索了一下架构师的培训 ...

  10. 方阵里面的dp

    打了一场luogu的信心赛,惊讶地发现我不会T2,感觉像这样在矩阵里面的dp看起来很套路的样子,但是仔细想想还是有很多需要注意的细节. 又想到之前貌似也考过一些类似的题目 然而我并没有改 ,于是打算补 ...