JAVA内存管理(一)-内存区域基础概念(上)

来源:互联网 发布:电脑桌面视频录制软件 编辑:程序博客网 时间:2024/06/03 18:54

本文翻译自:www.jikexueyuan.com/course/1793.html

1.Java虚拟机

  • 定义:模拟某种计算机体系结构,执行特定指令集的软件
  • 分为 系统虚拟机:(Virtual Box、VMware)和 进程虚拟机

2.进程虚拟机

  JVM、Adobe Flash Player、FC模拟机

3.高级语言虚拟机

  JVM、.NET CLR、P-Code

4.java语言虚拟机

  可以执行java语言的高级语言虚拟机。Java语言虚拟机不一定可以称为JVM,譬如:Apache Harmony

5.Java™虚拟机

  •   必须通过JAVA TCK(Technology Compatibility Kit)的兼容性测试的java语言虚拟机才能称为“Java™虚拟机“
  •   Java™虚拟机并不一定要执行java程序
  •   业界三大商用JVM:Oracle HotSpot、Oracle JRockit、IBM J9 VM

6.OracleHotSpot虚拟机

  • 最初由名为“Longview Technologies”的小公司开发,后来被sun收购。最初并非面向java语言开发,而是面向Strongtalk语言
  • HotSpot命名来自它的“热点代码探测”技术
  • 从JDK1.2开始加入SUN(Oracle)JDK,在JDK1.3开始成为SUN(Oracle)JDK的默认实现,在1.4成为唯一的虚机
  • 在2006年底开始开源,由此建立的Open JDK项目
  • 本文所讲所有的虚拟机实现,所指的都是Oracle HotSpot虚拟机

7.Java虚拟机运行时数据区

  •   在《java虚拟机规范》中定义了若干种程序运行期间会使用到的存储不同类型的数据区域
  •   有一些区域是安全共享的,随着虚拟机启动而创建,随着虚拟机推出而销毁。有一些区域是线程私有的,随着线程开始和结束而创建和销毁
  •   是所有java虚拟机共同的内存区域概念模型

7.1运行时数据区划分

  • 程序计数器
  • java堆
  • java虚拟机栈
  • 本地方法栈
  • 方法区

如图:


7.2程序计数器

  • 一块较小的内存空间,它的作用可以看作是当前线程所执行的字节码的行号指示器
  • 如果线程正在执行的是一个java方法,这个计数器记录的是正在运行的虚拟机字节码指令的地址;如果正在执行的是Native方法,这个计数器值则为空
  • 此内存区域是唯一一个在java虚拟机规范中没有规定任何OutOfMemeryError情况的区域

7.3java虚拟机栈

  • 内存私有,声明周期与线程相同,描述的是java方法执行的时候的内存模型,每个方法在执行的时候都会创建一个栈帧,用来创建这个方法的操作出栈,局部变量表,方法出口,动态链接等信息。每一个方法在调用和结束的过程就对应了一个栈帧在虚拟机栈中入栈到出栈的过程
  • 后进先出栈,靠后执行的方法会优先完成,后面进入虚拟机栈的栈帧会优先被出栈
  • 存储栈帧,支持java方法的调用、执行和退出
  • 可能出现OutOfMemoryError异常和StackOverflowError异常

7.4java本地方法栈

  Java本地方法栈与java虚拟机栈是非常相似的,差别在于java虚拟机栈是为了虚拟机执行字节码所服务的,而本地方法栈则是为了java虚拟机执行native方法所服务的

  • 线程私有
  • 后进先出栈
  • 作用是支撑Native方法的调用、执行和推出
  • 可能出现OutOfMemoryError异常和StackOverflowError异常
  • 有一些虚拟机(如HotSpot)将java虚拟机栈和本地方法栈合并实现

 

  Java虚拟机规范并没有对本地方法栈所使用的语言 方法的数据结构和形式做任何详细的规定,因此,任何一款具体的java虚拟机都可以选择以自己的方式去实现本地方法栈

7.5栈帧

  • Java虚拟机栈中存储的内容,它被用于存储数据和部分过程结果的数据结构,同时也被用来处理动态链接、方法返回值和异常分派
  • 一个完整的栈帧包含:局部变量表、操作数栈、动态链接信息、方法正常完成和异常完成信息(在编译程序代码的时候,栈帧需要多大的局部变量表、需要多深的操作数栈这时候在编译期就已经完全确定了。Java虚拟机编译器会把这些信息写入到class文件的code表之中。因此,一个栈帧需要分配多大的内存是不会受程序运行期间变量数据的影响,而仅仅取决于具体的java虚拟机。在一个方法里面,方法调用的调用链可能会很长,很多方法都同时处于执行的状态,对于执行引擎而言,在活动线程之中,只有位于java虚拟机栈栈顶的那个栈帧才是有效的。这个栈帧被称为当前栈帧,于这个栈帧相关联的方法会被称为当前方法。虚拟机执行引擎中所有执行的字节码指令都针对当前栈帧和当前方法进行操作)
7.5.1栈帧之局部变量
  • 由若干个Slot组成,长度由编译器决定
  • 单个Slot可以存储一个类型为boolean、byte、char、short、float、reference和returnAddress的数据,两个slot可以存储一个类型为long或者double的数据
7.5.2栈帧之操作数栈
  • 也是后进先出栈,由若干个Entry组成,长度由编译器决定
  • 单个Entry即可以存储一个java虚拟机中定义的任意数据类型的值,包括long和double型,但是存储long和double类型的Entry深度为2,其他类型的深度为1
  • 在方法执行过程中,栈帧用于存储计算参数和计算结果;在方法调用时,操作数栈也用来准备调用方法的参数以及接受方法返回的结果

  下面通过一个简单的类来说明:

  首先创建一个java类文件

 

编译这个文件:





  我们把code表中的数据提取出来成下面这个样子:

 

  解释:

 


未完待续..