关闭

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

标签: Java堆栈元空间程序计数器栈帧
84人阅读 评论(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 排列其他参数

操作数栈

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

动态连接

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

返回地址

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

这里写图片描述

0
0
查看评论
发表评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场

Java之美之JVM 中堆栈的区别

一。------------------------------------------------------------ 堆--用new建立,垃圾自动回收负责回收 1、堆是一个"运行时...
  • wangjia55
  • wangjia55
  • 2013-04-07 23:50
  • 2412

【JVM命令系列(2)】堆栈跟踪之Jstack命令

jstack是java虚拟机自带的一种堆栈跟踪工具。 功能 jstack用于生成java虚拟机当前时刻的线程快照。线程快照是当前java虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照...
  • liyanspace88888888
  • liyanspace88888888
  • 2016-03-10 09:40
  • 7152

初识JVM中堆栈的存储

Java语言的一个显著特点就是跨平台型
  • regan1994
  • regan1994
  • 2014-11-09 14:53
  • 857

JVM学习----查看堆栈信息

JPS 查看当前运行java进程JVM Process Status Tool,显示指定系统内所有的HotSpot虚拟机进程。jps -lvm 用于查看当前机器上运行的java进程。 命令格式 ...
  • eos2009
  • eos2009
  • 2017-11-13 17:50
  • 257

java堆栈信息打印

对于java堆栈信息的打印,对于我们调试代码解决问题是非常有帮助的。java的异常机制会让我们很快的找到错误的位置。例如我的问题如下所示。 启动tomcat出现如下问题: ...
  • lovesummerforever
  • lovesummerforever
  • 2014-05-10 10:05
  • 8899

JVM 线程堆栈分析过程详解

在这篇文章里我将教会你如何分析JVM的线程堆栈以及如何从堆栈信息中找出问题的根因。在我看来线程堆栈分析技术是Java EE产品支持工程师所必须掌握的一门技术。在线程堆栈中存储的信息,通常远超出你的想象...
  • u014082617
  • u014082617
  • 2015-03-21 12:19
  • 1542

JVM定位占用cpu过高堆栈信息(Linux)

第一步:使用top命令查看进程占用CPU的情况,获取PID top 从图中可以看出cpu占用高达46.5%的进程ID是16243 第二步:使用top -H -p命令获取进程中线程信息(其中H:...
  • keketrtr
  • keketrtr
  • 2017-01-09 15:22
  • 663

JVM之内存构成(二)--JAVA内存模型与并发

物理机中的并发硬件效率与一致性 Java线程执行的内存模型 工作内存 主内存 内存间交互 long和double的非源自性协定 Volatile类型变量的特殊规则和语义 保证可见性 禁止指令重排优化 ...
  • qq_33938256
  • qq_33938256
  • 2016-09-19 13:05
  • 778

分析JVM的线程堆栈以及如何从堆栈信息中

在这篇文章里我将教会你如何分析JVM的线程堆栈以及如何从堆栈信息中找出问题的根因。在我看来线程堆栈分析技术是Java EE产品支持工程师所必须掌握的一门技术。在线程堆栈中存储的信息,通常远超出你的想象...
  • nvnh7553
  • nvnh7553
  • 2015-12-01 08:44
  • 728

Java JVM 中 堆,栈,方法区 详解

一 jvm运行时数据区有哪些我们先来看一张图 JVM运行时数据区分类 1. JVM栈 (Java Virtual Machine Stacks) 2. 堆内存 (Heap Memory)...
  • zhangqiluGrubby
  • zhangqiluGrubby
  • 2017-03-01 16:45
  • 3206