JVM(二) 栈内存结构
栈内存是描述java方法执行的内存模型,每个方法在执行的同时都会创建一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态链接、返回出口等信息。每一个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。栈帧(Frame)是用来存储数据和部分过程结果的数据结构,同时也被用来处理动态链接(Dynamic Linking)、方法返回值和异常分派(Dispatch Exception)。栈帧随着方法调用而创建,随着方法结束而销毁——无论方法是正常完成还是异常完成(抛出了在方法内未被捕获的异常)都算作方法结束。

1. JVM栈内存结构
1.1 局部变量表
局部变量表(Local Variables Table)也可以称之为本地变量表,它包含在一个独立的栈帧中。顾名思义,局部变量表主要用于存储方法参数和定义在方法体内的局部变量,这些数据类型包括各类原始数据类型、对象引用(reference),以及returnAddress类型。局部变量表所需的容量大小在编译期就可以被完全确定下来,并保存在方法的Code属性中。大家思考一下,既然方法体内定义的局部变量是存储在栈帧中的局部变量表里的,那么原始数据类型的成员变量的值是否也存储在局部变量表中呢?其实如果是定义在方法体外的成员变量,不止是作用域发生了变化,更重要的是,其值也并非还是存储在局部变量表里,而是存储在对象内存空间的实例数据中,整体来看即存储在Java堆区内。简单来说,与线程上下文相关的数据存储在Java栈中,反之则存储在Java堆区内。
1.2. 操作数栈
每一个独立的栈帧中除了包含局部变量表以外,还包含一个后进先出(Last-In-First-Out)的操作数栈,也可以称之为表达式栈(Expression Stack)。操作数栈和局部变量表在访问方式上存在着较大差异,操作数栈并非采用访问索引的方式来进行数据访问的,而是通过标准的入栈和出栈操作来完成一次数据访问。每一个操作数栈都会拥有一个明确的栈深度用于存储数值,一个32bit的数值可以用一个单位的栈深度来存储,而2个单位的栈深度则可以保存一个64bit的数值,当然操作数栈所需的容量大小在编译期就可以被完全确定下来,并保存在方法的Code属性中。
1.3. 动态链接
每一个栈帧内部除了包含局部变量表和操作数栈之外,还包含一个指向运行时常量池中该栈帧所属方法的引用,包含这个引用的目的就是为了支持当前方法的代码能够实现动态链接(Dynamic Linking)。在运行时常量池,一个有效的字节码文件中除了包含类的版本信息、字段、方法以及接口等描述信息外,还包含一项信息,那就是常量池表(Constant Pool Table),那么运行时常量池就是字节码文件中常量池表的运行时表示形式。在一个字节码文件中,描述一个方法调用了另外的其他方法时,就是通过常量池中指向方法的符号引用(Symbolic Reference)来表示的,那么动态链接的作用就是为了将这些符号引用转换为调用方法的直接引用。
1.4. 方法返回值
一个方法在执行的过程中将会产生两种调用结果:一种是方法正常调用完成,而另外一种则是方法异常调用完成。如果是方法正常调用完成,那么这就意味着,被调用的当前方法在执行的过程中将不会有任何的异常被抛出,并且方法在执行的过程中一旦遇见字节码返回指令时,将会把方法的返回值返回给它的调用者,不过一个方法在正常调用完成之后究竟需要使用哪一个返回指令还需要根据方法返回值的实际数据类型而定。在字节码指令中,返回指令包含ireturn(当返回值是boolean、byte、char、short和int类型时使用)、lreturn、freturn、dreturn以及areturn,另外还有一个return指令供声明为void的方法、实例初始化方法、类和接口的初始化方法使用。
2. 栈上分配
jvm里面new Object对象除了在堆内存创建外,也可以在栈上创建,我们类里面的方法对应一个个的栈帧,方法里面new出来的对象,是局部不共享的。当然我们栈帧里面创建的对象如果太大,也会直接在堆空间分配。
3. 内存逃逸
当我们栈帧里面new出来的对象,如果被外部引用后,此时该对现象不会被分配在栈帧内而是直接分配在堆区间
JVM(二) 栈内存结构的更多相关文章
- JVM学习之 内存结构
目录 一.引言 1.什么是JVM? 2.学习JVM有什么用 3.常见的JVM 4.学习路线 二.内存结构 1. 程序计数器 1.1 定义 1.2作用 2. 虚拟机栈 2.1定义 2.2栈内存溢出 2. ...
- JVM原理及内存结构
JVM是按照运行时数据的存储结构来划分内存结构的,JVM在运行java程序时,将它们划分成几种不同格式的数据,分别存储在不同的区域,这些数据统一称为运行时数据.运行时数据包括java程序本身的数据信息 ...
- jvm(1):内存结构
JVM内存结构 JVM内存的运行时数据区: 线程私有(在线程启动时创建) 程序计数器Program Counter Register 一块较小的内存空间,可以看作是当前线程所执行的字节码的行号指示器, ...
- JVM之--Java内存结构(第一篇)
最近在和同事朋友聊天的时候,发现一个很让人思考的问题,很多人总觉得JVM将java和操作系统隔离开来,导致很多人不用熟悉操作系统,甚至不用了解JVM本身即可完全掌握Java这一门技术,其实个人的观点是 ...
- JVM宏观认知&&内存结构
JVM宏观认知 1.什么是虚拟机? 虚拟机是一种软件. 可分为系统虚拟机(仿真物理机)和程序虚拟机(执行单个计算机程序,比如JVM). 2.什么是Java虚拟机(JVM)? JVM是一种将字节码转化为 ...
- JVM运行时内存结构学习
学习JVM运行模型比较重要,先看一幅图片: 运行时数据区(内存结构) : 1.方法区(Method Area)类的所有字段和方法字节码,以及一些特殊方法如构造函数,接口代码也在这里定义.简单来说,所 ...
- 【JVM】JVM 概述、内存结构、溢出、调优(基础结构+StringTable+Unsafe+ByteBuffer)
什么是 JVM ? 定义 Java Virtual Machine - java 程序的运行环境(java 二进制字节码的运行环境) 好处 一次编写,到处运行 自动内存管理,垃圾回收功能 数组下标越界 ...
- JVM 运行时内存结构
1.JVM内存模型 JVM运行时内存=共享内存区+线程内存区 1).共享内存区 共享内存区=持久带+堆 持久带=方法区+其他 堆=Old Space ...
- JVM运行时内存结构
原文转载自:http://my.oschina.net/sunchp/blog/369707 1.JVM内存模型 JVM运行时内存=共享内存区+线程内存区 1).共享内存区 共享内存区=持久带+堆 持 ...
随机推荐
- Flask一种通用视图,增删改查RESTful API的设计
模型设计是后端开发的第一步.数据模型反映了各种对象之间的相互关系. from app import db class Role(db.Model): """角色" ...
- [NOI.AC]NOI2019省选模拟赛 第二场
传送门 Solution A. 一共有\(T\)组数据 每次询问你\([l,r]\)中有多少个数能被他的所有数位整除(如果数位中含有\(0\)忽略掉) 数位dp,咕咕咕 B. 题面略 考虑一个个只有两 ...
- 第十七周助教工作总结——NWNU李泓毅
助教博客链接:https://www.cnblogs.com/NWNU-LHY/ 本次作业的要求:软件测试与ALPHA冲刺:https://www.cnblogs.com/nwnu-daizh/p/1 ...
- SQL学习笔记(二)
连接查询 数据准备 例1:查询学生信息及学生的成绩 等值连接 此方法会产生笛卡尔积,生成的记录总数=表1的总数*表2的总数,会产生临时表 内连接 select * from 表1 inner join ...
- html5中output元素详解
html5中output元素详解 一.总结 一句话总结: output元素是HTML5新增的元素,用来设置不同数据的输出,没什么大用,了解即可 <form action="L3_01. ...
- spring线程池的同步和异步(1)
spring线程池(同步.异步) 一.spring异步线程池类图 二.简单介绍 2.1. TaskExecutor---Spring异步线程池的接口类,其实质是java.util.concurrent ...
- SSH项目中使用struts-tags报错According to TLD or attribute directive in tag file, attribute test does not accept any expressions
在运行struts2标签页面时报错,代码如下:<%@ page language="java" pageEncoding="gbk"%><%@ ...
- Status Code: 431 Request Header Fields Too Large
Status Code: 431 Request Header Fields Too Large
- Vue实现图片预加载
<script>export default { data () { return { count: 0, } }, mounted: function() { this.preload( ...
- 深入学习c++--智能指针(四)--使用建议
1. 不要自己手动管理资源 2. 一个裸指针不要用两个shared_ptr管理,unique_ptr 3. 使用shared_ptr作为函数的接口,如果有可能用 const shared_ptr&am ...