JVM - 2. java堆栈里面到底有什么

标签: Java堆栈 元空间 程序计数器 栈帧
127人阅读 评论(0) 收藏 举报
分类:
  • 在虚拟机自动内存管理机制的帮助下, 不容易出现内存泄漏和内存溢出问题
  • 不过, 也正是因为把内存控制的权力交给了Java虚拟机
  • 如果不了解虚拟机是怎样使用内存的, 那么排查错误将会成为一项异常艰难的工作。

运行时数据区

Java虚拟机定义了若干种程序运行期间会使用到的运行时数据区,其中有一些会随着虚拟机启动而创建,随着虚拟机退出而销毁。还有一些则是与线程一一对应,他们的生命周期也随着线程而创建于销毁。

这里写图片描述

程序计数器

每条虚拟机线程都有自己的程序计数器。程序计数器记录着字节码行号。

由于Java虚拟机的多线程是通过线程切换并分配处理器执行时间的方式来实现的,在任何一个确定的时刻, 一个处理器( 对于多核处理器来说是一个内核) 都只会执行一条线程中的指令。 因此, 为了线程切换后能恢复到正确的执行位置, 每条线程都需要有一个独立的程序计数器, 各条线程之间计数器互不影响, 独立存储, 我们称这类内存区域为“线程私有”的内存。
@@>>>字节码指令

《深入理解java虚拟机中jdk1.7》中称作:程序计数器
《 虚拟机规范JAVA SE8》中称作:PC寄存器
 英文原名:Program Counter Register

  1. 如果正在执行的是一个Java方法, 这个程序计数器记录的是正在执行的虚拟机字节码指令的地址
  2. 如果正在执行的是Native方法, 这程序计数器则为空( Undefined)
  3. 程序计数器中的容量至少足够可以保存一条returnAddress类型数据或者一个与平台相关的本地指令地址。(retrunAddress 指向了一条字节码指令地址)
  4. 此内存区域是唯一一个在Java虚拟机规范中没有规定任何OutOfMemoryError情况的区域。

Java虚拟机栈

Stack与Java vm Stack是不同的。我们java程序员所说的栈,指的是虚拟机栈(Java vm Stack),然而虚拟机是由其他语言实现,其中java vm stack可能是分配在heap(堆)上

  • 虚拟机栈主要用于存储局部变量与尚未计算完毕的过程结果
  • 线程创建的同时得到了虚拟机栈,栈中保存着栈帧
  • 每个方法执行的同时会创建栈帧,栈帧的创建到销毁,就是其在虚拟机栈中出入栈的过程

虚拟机栈在线程请求的时候,如果超过虚拟机栈最大深度会抛出StackOverflowError
虚拟机栈支持动态扩展,在尝试扩展并无法申请到内存时会抛出OutOfMemoryError

@@>>>Error And Exception

说完程序计数器和虚拟机栈,我们总结成一张图
位于栈顶的栈帧为(当前栈)
这里写图片描述

Java堆

Java堆是被所有线程共享的一块内存区域, 在虚拟机启动时创建
此内存区域的唯一目的就是存放数组对象与类对象实例, 几乎所有的对象实例都在这里分配内存。

这一点在Java虚拟机规范中的描述是: 所有的对象实例以及数组都要在堆上分配

随着JIT编译器的发展与逃逸分析技术逐渐成熟, 栈上分配、 标量替换优化技术将会导致一些微妙的变化发生, 所有的对象都分配在堆上也渐渐变得不是那么“绝对”了。
@@>>>逃逸分析
垃圾回收期主要管理的就是堆区域
@@>>>GC

堆可以根据虚拟机参数动态扩展和调整堆大小,当堆超过了可以提供的最大容量时。则会抛出OutOfMemoryError

方法区

方法区是java堆的逻辑组成部分
存储了每一个类的结构信息,例:运行时常量池,字段和方法数据,构造函数,普通方法的字节码以及类,实例,接口初始化时的特殊方法。
@@>>>特殊方法
方法区根据不同虚拟机有不同实现,方法区只是一个逻辑存在,在Hotspot中方法区实现为“永久代”(PermGen)。

然而从JAVA8开始,永久代被移除,而增加了“元空间”(Metaspace),利用本地内存(native memory)来存储(MaxMetaspaceSize来设置其大小,默认是动态调节),极大的减少了永久代堆溢出。

运行时常量池

运行时常量池在方法区分配
保存符号引用与直接饮用,其动态性确保了不仅仅在编译期才产生保存,在运行期间也可以,最好的例子就是String.intern()

本地方法栈

当调用native本地方法时,会有一个额外的栈来服务,这就是本地方法栈
HotSpot已经把本地方法栈和虚拟机栈合并

这里写图片描述

堆外内存

JUC中DirectByteBuffer可以引用堆外内存,堆外内存不受虚拟机堆内存限制。

栈帧

在活动线程中, 只有位于栈顶的栈帧才是有效的, 称为当前栈帧 , 与这个栈帧相关联的方法称为当前方法。
执行引擎运行的所有字节码指令都只针对当前栈帧进行操作

在编译程序代码的时候, 栈帧中需要多大的局部变量表, 多深的操作数栈都已经完全确定了, 因此一个栈帧需要分配多少内存,不会受到程序运行期变量数据的影响, 而仅仅取决于具体的虚拟机实现。

局部变量表

局部变量表( Local Variable Table) 是一组变量值存储空间, 用于存放方法参数和方法内部定义的局部变量
局部变量表中数据存放在局部变量表槽中(称作变量槽,Slot),Slot在定义中可以满足boolean、 byte、 char、 short、 int、 float、 reference或returnAddress类型的数据,当然64位的虚拟机仍要补白和对齐。

  • Slot 0 在非static方法中 保存的永远是 this
  • Slot 1 ~ N 排列其他参数

操作数栈

操作数栈最大深度在编译器就已确定。
依赖后入先出的规则,执行字节码指令

动态连接

每个栈帧都包含一个指向运行时常量池中该栈帧所属方法的引用, 持有这个引用是为了支持方法调用过程中的动态连接

返回地址

方法正常退出下,会得到字节码指令来唤起调用者栈帧,并在有返回值的情况下返回结果。
当异常退出下,会将异常指令返回并唤起调用者,不会有返回值。

这里写图片描述

查看评论

Java中堆栈的理解

对象是放在堆里面的,基本类型数据是放在栈里面的。 堆:放new出来的对象 栈:放基本类型数据和对对象的引用(相当于指针,但是对象本身还是在堆里) 常量池:public static fi...
  • u013458516
  • u013458516
  • 2015-09-13 14:24:04
  • 518

JAVA中堆栈的定义及区别

已经有人发过java堆栈是什么,那么我就概括的来介绍下堆栈的广义吧. 堆栈是一种执行“后进先出”算法的数据结构。 设想有一个直径不大、一端开口一端封闭的竹筒。有若干个写有编号的小球,小球的直径比竹...
  • dreamthen
  • dreamthen
  • 2014-05-22 11:01:09
  • 1561

java 堆栈的区别

Java把内存分成两种,一种叫做栈内存,一种叫做堆内存 在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配。当在一段代码块中定义一个变量时,java就在栈中为这个变量分配内...
  • chengyingzhilian
  • chengyingzhilian
  • 2012-07-24 19:12:20
  • 28700

java中堆和堆栈的区别

1.栈(stack)与堆(heap)都是Java用来在Ram中存放数据的地方。与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆。   2. 栈的优势是,存取速度比堆要快,仅次于...
  • whaosy
  • whaosy
  • 2013-02-26 13:47:06
  • 7310

JVM - 2. java堆栈里面到底有什么

在虚拟机自动内存管理机制的帮助下, 不容易出现内存泄漏和内存溢出问题 不过, 也正是因为把内存控制的权力交给了Java虚拟机 如果不了解虚拟机是怎样使用内存的, 那么排查错误将会成为一项异常艰难的工作...
  • crazyzxljing0621
  • crazyzxljing0621
  • 2017-12-27 10:55:35
  • 127

java 堆 栈 方法区的简单分析

基础数据类型(Value type)直接在栈(stack)空间分配,方法的形式参数,直接在栈空间分配,当方法调用完成后从栈空间回收。 引用数据类型,需要用new来创建,既在栈空间分配一个地址空间(r...
  • u012176204
  • u012176204
  • 2017-01-04 20:41:12
  • 1397

(第18讲)java数据结构的堆栈与内存区的堆栈(总结各大神的见解)

大神1 Java 把内存划分成两种:一种是栈内存,另一种是堆内存。 在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配,当在一段代码块定义一个变量时,Java 就在栈中为这个变...
  • weiyastory
  • weiyastory
  • 2016-05-27 10:58:36
  • 2212

JAVA 堆栈 堆 方法区 静态区 final static 内存分配 详解

转自:http://blog.csdn.net/peterwin1987/article/details/7571808 Java栈与堆 堆:顺序随意 栈:后进先出(Last-in/Fi...
  • xiankechuanqi
  • xiankechuanqi
  • 2016-07-29 15:40:11
  • 4456

java堆栈 (转)

 Java栈与堆 ----对这两个概念的不明好久,终于找到一篇好文,拿来共享 1. 栈(stack)与堆(heap)都是Java用来在Ram中存放数据的地方。与C++不同,Java自动管理栈和堆,程序...
  • songjie521
  • songjie521
  • 2008-11-25 12:04:00
  • 35925
    个人资料
    专栏达人 持之以恒
    等级:
    访问量: 3万+
    积分: 770
    排名: 6万+
    博客专栏