Java虚拟机运行时数据区域

Java虚拟机将其所管理的内存划分为若干个不同的数据区域。这些区域都有着各自的用途,以及创建和销毁时间。其中有一些会随着虚拟机启动而启动,随着虚拟机退出而销毁;有些则是与线程一一对应,这些与线程对应的数据区域会随着线程开始和结束而创建和销毁。划分的几个运行时区域如下:

1.    PC寄存器

Java虚拟机支持多条线程同时执行,每条线程都有自己的PC寄存器(program counter register)。PC寄存器用来指示当前线程所执行字节码指令的地址,说白了就是记录各个线程执行的位置。如果正在执行的是Native方法,PC寄存器的值则为空(undefined)。

2.    Java方法栈

与PC寄存器一样,Java方法栈也是线程私有的。这个栈的生命周期与线程相同,与线程同时创建,线程结束也会随着销毁。Java方法栈用于存储栈帧(Frame,栈帧是方法运行时的基础数据结构,包括局部变量表、操作数栈、动态链接、方法出口等信息)。每一个方法从调用直至执行结束完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。(栈容量设置:-Xss设定)

Java虚拟机规范中,定义了两种异常情况:

(1)如果线程请求分配的栈深度超过Java方法栈允许的最大深度,Java虚拟机将会抛出一个StackOverflowError异常。

(2)如果Java方法栈可以动态扩展,并且在尝试扩展的时候无法申请到足够的内存,或者在创建新的线程时没有足够的内存去创建对应的虚拟机栈,那么Java虚拟机将会抛出OutOfMemoryError异常。

3. 本地方法栈

本地方法栈(Native Method Stack)与虚拟机栈的作用类似。虚拟机栈为虚拟机执行Java方法服务,而本地方法栈则为虚拟机执行Native方法服务。与虚拟机栈一样,本地方法栈也会抛出StackOverflowError异常和OutOfMemoryError异常。

4. Java堆

Java虚拟机中,Java堆(Java heap)是被所有线程共享的一块区域,在虚拟机启动时创建。此内存区域的唯一目的是存放类实例对象和数组对象。几乎所有的类实例对象和数组对象都在这里分配内存。是Java虚拟机所管理的内存中最大的一块。(存储对象实例数据)

Java堆可以是固定大小的,也可以是扩展的。当前主流的Java虚拟机都是按照可扩展来实现,通过参数-Xmx和-Xms设置堆的最小值和最大值。

Java堆可能抛出异常的情况:堆中没有足够的内存完成实例分配,并且堆也无法再扩展时,Java虚拟机将会抛出OutOfMemeroryError异常。

5. 方法区

与Java堆一样,方法区(method area)也是各个线程共享的区域,在虚拟机启动时创建。主要是用于存储每一个类的结构信息,例如,运行时常量池(runtime constant pool)、字段和方法数据、构造函数和普通方法的字节码内容。还包括一些在类、实例、接口初始化时用到的特殊方法。(存储对象类型数据)。配置方法区大小使用参数:-XX:PermSize和-XX:MaxPermSize。

方法区可能抛出异常的情况:方法区的内存空间不能满足内存分配需求时,Java虚拟机将会抛出一个OutOfMemoryError:PermGenspace的异常。

Java虚拟机加载class文件后,其中Java类会被存储到方法区(Method Area)。实际运行时,虚拟机会执行方法去内的代码。

6. 直接内存

NIO类是基于通道(Channel)与缓冲区(Buffer)方式,它可以使用Native函数库直接分配堆外内存,然后通过一个存储在Java堆中的DirectByteBuffer对象作为这块内存的引用进行操作。NIO操作需要使用到直接内存(Direct Memory)。

直接内存:可通过-XX:MaxDirectMemorySize调整大小。内存不足时抛出OutOfMemoryError或者OutOfMemoryError:Direct buff memory。

6. 运行时常量

运行时常量池(runtime constant pool)是方法区的一部分。在加载类和接口到虚拟机后,就在方法区创建对应的运行时常量池。它是class文件中每一个类或接口的常量池表的运行时表示,它包含了若干种不同的常量。用于存放在编译期间生成的各种字面量个符号引用。

可能抛出异常的情况:在创建类和接口的运行时常量池时,当常量池所需的内存空间超过方法区所能提供的最大值时,抛出OutOfMemoryError异常。

7. 栈帧结构

栈帧存储于Java虚拟机栈中。栈帧是一种数据结构,用于存储方法运行时的数据,包括局部变量表、操作数栈、动态链接、方法出口等信息。每一个栈帧都有自己的局部变量表、操作数栈、和指向当前方法所属的类的运行时常量池的引用。栈帧随着方法调用而创建,随方法结束而销毁。每一个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈、出栈的过程。

7.1 局部变量表

局部变量表是一组变量值存储空间,用于存放实例方法的”this指针”、方法参数以及方法内部定义的局部变量。在Java程序编译为Class文件时,就在方法的Code属性的max_locals数据项中确定了该方法所需要分配的局部变量表的最大容量。

一个局部变量可以保存一个类型为boolean、byte、char、short、int、float、reference、和retuanAddress的数据。两个局部变量可以保存一个类型为long或者double的数据。这么看来,局部变量表等价于一个数组,并且可以用正整数来索引。出了long、double值需要用两个数组单元来存储之外,其他基本类型以及引用类型的值均占用一个数组单元。(javap命令编译出来的class文件,方法里面的局部变量是用槽(slot)来表示的,double两个槽,int一个槽)。

因此,在32位的HotSpot中基本类型将占用4个字节;而在64位的HotSpot中,基本类型将占用8个字节。

参考资料:

【1】 周志明. 深入理解Java虚拟机:JVM高级特性与最佳实践(第二版)【M】.北京:机械工业出版社,2013

【2】爱飞翔,周志明(译).Java虚拟机规范(Java SE 8版)【M】.北京:机械工业出版社,2015.

Java虚拟机学习笔记(一)的更多相关文章

  1. 《深入Java虚拟机学习笔记》- 第19章 方法的调用与返回

    <深入Java虚拟机学习笔记>- 第19章 方法的调用与返回

  2. 《深入Java虚拟机学习笔记》- 第16章 控制流

    <深入Java虚拟机学习笔记>- 第16章 控制流

  3. 《深入Java虚拟机学习笔记》- 第17章 异常

    <深入Java虚拟机学习笔记>- 第17章 异常

  4. 《深入Java虚拟机学习笔记》- 第13章 逻辑运算

    <深入Java虚拟机学习笔记>- 第13章 浮点运算

  5. 《深入Java虚拟机学习笔记》- 第14章 浮点运算

    <深入Java虚拟机学习笔记>- 第13章 浮点运算

  6. 《深入Java虚拟机学习笔记》- 第8章 连接模型

    Java虚拟机学习笔记(八)连接模型

  7. 《深入Java虚拟机学习笔记》- 第4章 网络移动性

    Java虚拟机学习笔记(四)网络移动性

  8. 《深入Java虚拟机学习笔记》- 第2章 平台无关

    Java虚拟机学习笔记(二)平台无关

  9. Java虚拟机学习笔记——JVM垃圾回收机制

    Java虚拟机学习笔记——JVM垃圾回收机制 Java垃圾回收基于虚拟机的自动内存管理机制,我们不需要为每一个对象进行释放内存,不容易发生内存泄漏和内存溢出问题. 但是自动内存管理机制不是万能药,我们 ...

  10. 深入理解java虚拟机学习笔记(一)JVM内存模型

    上周末搬家后,家里的宽带一直没弄好,跟电信客服反映了N遍了终于约了个师傅明天早上来迁移宽带,可以结束一个多星期没网的痛苦日子了.这段时间也是各种忙,都一个星期没更新博客了,再不写之前那种状态和激情都要 ...

随机推荐

  1. .NET Core的依赖注入[1]: 控制反转

    写在前面:我之前写过一系列关于.NET Core依赖注入的文章,由于.NET Core依赖注入框架的实现原理发生了很大的改变,加上我对包括IoC和DI这些理论层面的东西又有了一些新的理解,所以我在此基 ...

  2. 深入理解Spring Redis的使用 (五)、常见问题汇总

    目前我所知道的Redistemplate里面,我没有使用到的就是管道.这个可以进行批量的读写.类似于jdbc的batch.还有就是Redis的集群部署.但是由于我业务里没有这种需求,所以没有使用无法给 ...

  3. 字符串匹配(二)----KMP算法

    什么是KMP算法: KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt同时发现,因此人们称它为克努特——莫里斯——普拉特操作(简称KMP算法).KMP ...

  4. SUSE12Sp3-Nginx安装

    1.安装pcre(nginx 依赖) 把安装包pcre-8.12.tar.gz复制到服务器指定目录 tar -zxvf pcre-8.12.tar.gz # 解压 cd pcre-8.12 #进入目录 ...

  5. numpy.random 常用函数详解之简单随机数篇(Simple random data)

    1.numpy.random.rand(d0,d1,d2,...,dn) 参数:d0,d1,d2,...,dn 须是正整数,用来描述生成随机数组的维度.如(3,2)代表生成3行2列的随机数组. 返回值 ...

  6. [Swift]LeetCode46. 全排列 | Permutations

    Given a collection of distinct integers, return all possible permutations. Example: Input: [1,2,3] O ...

  7. [Swift]LeetCode838. 推多米诺 | Push Dominoes

    There are N dominoes in a line, and we place each domino vertically upright. In the beginning, we si ...

  8. Python内置函数(34)——isinstance

    英文文档: isinstance(object, classinfo) Return true if the object argument is an instance of the classin ...

  9. 深入解析 H.265 编码模式,带你了解Apple全面推进H.265的原因

    今天我们聊聊视频编码.视频文件亘古以来存在一个矛盾:高清画质和视频体积的冲突,相同编码标准下,视频更高清,视频体积更大.因此,应用更先进的视频编码标准,降低视频体积,可以大幅降低网站的流量消耗. 目前 ...

  10. 搭建自己的hexo博客

    这是我最近用hexo搭建的个人博客,欢迎来参观留言,以下是我创建这个hexo的一步步步骤,欢迎指正! 我的博客 参考自 潘柏信的博客;CnFeat 主题参考这里 pacman; 主题选自这里 hexa ...