JVM 运行时内存结构

 

1.JVM内存模型

      JVM运行时内存=共享内存区+线程内存区

1).共享内存区

      共享内存区=持久带+堆

      持久带=方法区+其他

      堆=Old Space+Young Space

      Young Space=Eden+S0+S1

(1)持久带

      JVM用持久带(Permanent Space)实现方法区,主要存放所有已加载的类信息,方法信息,常量池等等。可通过-XX:PermSize和-XX:MaxPermSize来指定持久带初始化值和最大值。Permanent Space并不等同于方法区,只不过是Hotspot JVM用Permanent Space来实现方法区而已,有些虚拟机没有Permanent Space而用其他机制来实现方法区。

(2)堆

      堆,主要用来存放类的对象实例信息。

      堆分为Old Space(又名,Tenured Generation)和Young Space。

      Old Space主要存放应用程序中生命周期长的存活对象;

      Eden(伊甸园)主要存放新生的对象;

      S0和S1是两个大小相同的内存区域,主要存放每次垃圾回收后Eden存活的对象,作为对象从Eden过渡到Old Space的缓冲地带(S是指英文单词Survivor Space)。

堆之所以要划分区间,是为了方便对象创建和垃圾回收,后面垃圾回收部分会解释。

2).线程内存区

      线程内存区=单个线程内存+单个线程内存+.......

      单个线程内存=PC Regster+JVM栈+本地方法栈

       JVM栈=栈帧+栈帧+.....

      栈帧=局域变量区+操作数区+帧数据区

 

      在Java中,一个线程会对应一个JVM栈(JVM Stack),JVM栈里记录了线程的运行状态。JVM栈以栈帧为单位组成,一个栈帧代表一个方法调用。栈帧由三部分组成:局部变量区、操作数栈、帧数据区。

 

(1)局部变量区

      局部变量区,可以理解为一个以数组形式进行管理的内存区,从0开始计数,每个局部变量的空间是32位的,即4字节。基本类型byte、char、short、boolean、int、float及对象引用等占一个局部变量空间,类型为short、byte和char的值在存入数组前要被转换成int值;long、double占两个局部变量空间,在访问long和double类型的局部变量时,只需要取第一个变量空间的索引即可。

例如:

public static int runClassMethod(int i,long l,float f,double d,Object o,byte b) {
    return 0;
}   

public int runInstanceMethod(char c,double d,short s,boolean b) {
    return 0;
}

对应的局域变量区是:

 

      runInstanceMethod的局部变量区第一项是个reference(引用),它指定的就是对象本身的引用,也就是我们常用的this,但是在runClassMethod方法中,没这个引用,那是因为runClassMethod是个静态方法。

(2)操作数栈

      操作数栈和局部变量区一样,也被组织成一个以字长为单位的数组。但和前者不同的是,它不是通过索引来访问的,而是通过入栈和出栈来访问的。操作数栈是临时数据的存储区域。

例如:

int a= 100;
int b =5;
int c = a+b;

对应的操作数栈变化为:

      从图中可以得出:操作数栈其实就是个临时数据存储区域,它是通过入栈和出栈来进行操作的。

      PS:JVM实现里,有一种基于栈的指令集(Hotspot,oracle JVM),还有一种基于寄存器的指令集(DalvikVM,安卓 JVM),两者有什么区别的呢?

      基于栈的指令集有接入简单、硬件无关性、代码紧凑、栈上分配无需考虑物理的空间分配等优势,但是由于相同的操作需要更多的出入栈操作,因此消耗的内存更大。 而基于寄存器的指令集最大的好处就是指令少,速度快,但是操作相对繁琐。

示例:

package com.demo3;

public class Test {

    public static void foo() {
        int a = 1;
        int b = 2;
        int c = (a + b) * 5;
    }

    public static void main(String[] args) {
        foo();
    }
}

 

基于栈的Hotspot的执行过程如下:

 

基于寄存器的DalvikVM执行过程如下所示:

上述两种方式最终通过JVM执行引擎,CPU接收到的汇编指令是:

 

(3)帧数据区

      帧数据区存放了指向常量池的指针地址,当某些指令需要获得常量池的数据时,通过帧数据区中的指针地址来访问常量池的数据。此外,帧数据区还存放方法正常返回和异常终止需要的一些数据。

 

转自:http://my.oschina.net/sunchp/blog/369707

时间: 2024-11-09 15:29:48

JVM 运行时内存结构的相关文章

[转]JVM运行时内存结构

目录[-] 1.为什么会有年轻代 2.年轻代中的GC 3.一个对象的这一辈子 4.有关年轻代的JVM参数 1.为什么会有年轻代 我们先来屡屡,为什么需要把堆分代?不分代不能完成他所做的事情么?其实不分代完全可以,分代的唯一理由就是优化GC性能.你先想想,如果没有分代,那我们所有的对象都在一块,GC的时候我们要找到哪些对象没用,这样就会对堆的所有区域进行扫描.而我们的很多对象都是朝生夕死的,如果分代的话,我们把新创建的对象放到某一地方,当GC的时候先把这块存“朝生夕死”对象的区域进行回收,这样就会

JVM运行时内存结构

连接:http://my.oschina.net/sunchp/blog/369707 1.JVM内存模型 JVM运行时内存=共享内存区+线程内存区 1).共享内存区 共享内存区=持久带+堆 持久带=方法区+其他 堆=Old Space+Young Space Young Space=Eden+S0+S1 (1)持久带 JVM用持久带(Permanent Space)实现方法区,主要存放所有已加载的类信息,方法信息,常量池等等. 可通过-XX:PermSize和-XX:MaxPermSize来指

JVM运行时内存结构学习

学习JVM运行模型比较重要,先看一幅图片: 运行时数据区(内存结构) :  1.方法区(Method Area)类的所有字段和方法字节码,以及一些特殊方法如构造函数,接口代码也在这里定义.简单来说,所有定义的方法的信息都保存在该区域,静态变量+常量+类信息(构造方法/接口定义)+运行时常量池都存在方法区中, 虽然Java虚拟机规范把方法区描述为堆的一个逻辑部分,但是它却有一个别名叫做Non-Heap(非堆),目的应该是为了和Java的堆区分开 . 2.堆(Heap)虚拟机启动时自动分配创建,用于

Java 进阶(一) JVM运行时内存模型

1.JVM运行时数据区域的划分 a.程序计数器(Program Counter Register) 一块较小的内存空间,可以看作是当前线程所执行的字节码的行号指示器.每个线程拥有独立的一个计数器,如果当前执行的是Native方法,则计数器值为空. b.JVM栈(Java Virtual Machine Stack) 描述Java方法执行的内存模型,每个方法在执行的同时都会创建一个栈帧(Stacks Frame)用于存储局部变量表,操作数栈,动态链接,方法出口等信息. 每一个方法从调用直至执行完成

jvm运行时内存解析

一.jvm的概念 在了解jvm的概念之前,我们先来了解java平台的逻辑结构,图片来自<深入java虚拟机> 从图中我们可以看到jdk包含了jre,java语言和java开发工具和Api,jre包含了java运行的基础类库和java虚拟机,java虚拟机支撑着java程序的运行. jvm(java virtual machine)翻译为java虚拟机,从字面上来理解,jvm就是一个虚拟的机器,其实类似于一个操作系统,通过软件去虚拟出一个虚拟机,帮助我们管理计算机的内存和调用计算机的硬件等等.而

jvm运行时内存划分

(根据<深入理解java虚拟机>这本书总结) 本文主要解释jvm内存模型,以及各个部分的作用.都是自己总结的给自己看的通俗语言,未用专业术语的见谅. 一.为什么要了解jvm内存模型? 在了解一个类的编译-加载-内存分配-初始化所有过程前,要先了解jvm的内存模型.这样对整个java体系可能会更加便于理解.当然,如果不理解这些,也是没关系的,照样可以进行java开发. 二.jvm内存模型 1.根据自己的理解举个最简单的例子,一个main方法启动,进程运行,在这个过程中,会调用方法.开启多个线程.

JAVA-JVM 运行时内存结构(Run-Time Data Areas)

Java 虚拟机定义了在程序执行期间使用的各种运行时数据区域. 其中一些数据区域是在 Java 虚拟机启动时创建的,仅在Java虚拟机退出时销毁. 其他数据区域是每个线程.线程数据区域是在线程退出时创建和销毁线程时创建的. 一.运行时数据区划分(JDK8) 1.The pc Register(PC 寄存器.程序计数器) 2.Java Virtual Machine Stacks(Java 虚拟机栈.Java 栈) 3.Native Method Stacks(本地方法栈,C栈) 4.Heap(堆

JVM(一)—— 运行时内存结构

JVM 在执行 Java 程序的过程中会把它所管理的物理内存划分成不同的内存区域,每一个区域都存放着不同的数据.每个区域也都有不同的用途,以及创建和销毁的时机,根据虚拟机规定,可以获得这样的 JVM 内存结构. 1 程序计数器 程序计数器(Program Counter Register)是一块比较小的内存区域,可以看作是当前线程所执行的字节码的行号指示器.就是用于存放当前线程接下来将要执行的字节码指令.分支.循环.跳转.异常等信息.在任何时候,一个处理器只能执行一个线程中的指令,为了能让 CP

jvm运行是内存结构

转自:https://www.cnblogs.com/paddix/p/5309550.html 一.JVM 内存模型 根据 JVM 规范,JVM 内存共分为虚拟机栈.堆.方法区.程序计数器.本地方法栈五个部分. 1.虚拟机栈:每个线程有一个私有的栈,随着线程的创建而创建.栈里面存着的是一种叫“栈帧”的东西,每个方法会创建一个栈帧,栈帧中存放了局部变量表(基本数据类型和对象引用).操作数栈.方法出口等信息.栈的大小可以固定也可以动态扩展.当栈调用深度大于JVM所允许的范围,会抛出StackOve