Java 运行期数据区
对于 Java 开发者来说,由虚拟机进行内存管理是把双刃剑,一方面免去了繁杂的内存管理工作,另一方面,一旦出现内存泄漏和溢出方面的问题,如果不了解虚拟机是怎样使用内存的,排查问题将成为一项艰难的工作。本文主要介绍 Java 运行时的内存区域。
JVM 在执行 Java 程序的过程中,会把它所管理的内存划分为若干个不同的数据区域。如图:

程序计数器
程序计数器是一块较小的内存空间,可以看作是当前线程所执行的字节码的行号指示器。
由于 JVM 的多线程是通过线程轮流切换病分配处理器执行时间的方式来执行的,在任何一个确定的时刻,一个处理器(一个核心)只会执行一个线程中的指令。因此,为了县城切换后能恢复到正确的执行位置,每个线程都需要有一个独立的程序计数器,各个线程之间计数器互不影响,独立存储。即,“线程私有”。
如果线程正在执行的是一个 Java 方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址;如果正在执行的 Native 方法,这个计数器值则为空(Undefined)。此内存区域是唯一一个在 JVM 规范中没有规定任何 OutOfMemoryError 情况的区域。
注意:在虚拟机的概念模型中,字节码解释器工作时通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要以来这个计数器来完成。
Java 虚拟机栈
Java 虚拟机栈也是线程私有的,生命周期跟线程的相同。虚拟机栈描述的是 Java 方法执行的内存模型:每个方法在执行的同时都会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每个方法从调用到执行完成的过程,对应着一个栈帧在虚拟机中入栈道出栈的过程。
局部变量表存放了编译期可知的各种基本类型、对象引用、指向一个代表对象的句柄、一个指向对象起始地址的引用指针或其他与此对象相关的位置、或者是 returnAddress 类型(指向一条字节码指令的地址)。
局部变量表所需的内存空间在编译期间完成分配,当进入一个方法时,这个方法需要在栈中分配多大的局部变量空间是完全确定的,在方法运行期间不会改变局部变量表的大小。
在 JVM 规范中,对该区域规定了两种情况的异常:
- 如果线程请求的栈深度大于虚拟机所允许的深度,将抛出
StackOverflowError异常; - 如果虚拟机可以动态扩展,在扩展时如果无法申请到足够的内存,就会跑出
OutOfMemoryError异常。
本地方法栈
与 Java 虚拟机栈类似,虚拟机栈为虚拟机执行 Java 方法(字节码)服务,本地方法栈则为虚拟机使用到的 Native 方法服务。
本地方法栈区域也会抛出 StackOverflowError 和 OutOfMemoryError异常。
Java 堆
对于大多数迎来说,Java 堆是 Java 虚拟机所管理的内存中最大的一块,该区域被所有线程共享,在虚拟机启用时创建。几乎所有(JIT 技术的发展,让这里多了“几乎”)的对象实例和数组都在堆上分配内存。
从内存回收的角度来看,由于现在垃圾收集器基本都采用分带算法,所有Java堆中还可以细分为:新生代和老圣代;在细一点有 Eden 空间、From Survivor 空间, To Survivor 空间。(在之后垃圾回收的文章中会有介绍)。
根据 JVM 规范的规定,Java 堆可以处于物理上不连续的区域,只要逻辑上是连续的即可。
如果在堆中没有完成实例分配,并且堆也无法再扩展时,将会跑出 OutOfMemoryError 异常。
方法区(永久代)
方法区也是各线程共享的内存区域,用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
根据 JVM 规范的规定,当方法区无法满足内存分配需求时,将抛出 OutOfMemoryError 异常。
运行时常量池
运行时常量池时方法区的一部分。Class 文件中出了有类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池,用于存放编译器生成的各种字面量和符号引用,这部分内容将在类加载后渐入方法区的运行时常量池存放。
运行时常量池相对于 Class 文件常量池的另外一个重要特征是具备动态性,Java 语言并不要求常量一定已有编译器期才能产生,也就是并非预置入 Class 文件中常量池的内容才能进入方法区运行时常量池,运行期间也能将新的常量放入池中。
参考:
- 图片来源:http://chenzhou123520.iteye.com/blog/1585224
- 《深入理解Java虚拟机》第2版
Java 运行期数据区的更多相关文章
- Jvm基础(1)-Java运行时数据区
最近在看<深入理解Java虚拟机>,里面讲到了Java运行时数据区,这是Jvm基本知识,把读书笔记记录在此.这些知识属于常识,都能查到的,如果我有理解不对的地方,还请指出. 首先把图贴上来 ...
- 读书笔记-浅析Java运行时数据区
作为一个 Java 为主语言的程序员,我偶尔也需要 用 C/C++ 写程序,在使用时让我很烦恼的一件事情就是需要对 new 出来的对象进行 delete/free 操作,我老是担心忘了这件事情,从而导 ...
- Java 运行时数据区
写在前面 本文描述的有关于 JVM 的运行时数据区是基于 HotSpot 虚拟机. 概述 JVM 在执行 Java 程序的过程中会把它所管理的内存划分为若干个不同的数据区域.这些区域都有各自的用途,以 ...
- Java运行时数据区
目录 1. 概述 2. Java内存结构 3. 程序计数器 4. Java虚拟机栈 5. 本地方法栈 6. 堆 7. 方法区 8. 运行时常量池 9. 直接内存 10. 总结 1. 概述 作为日常的J ...
- 【转】Java运行时数据区简介及堆与栈的区别
理解JVM运行时的数据区是Java编程中的进阶部分.我们在开发中都遇到过一个很头疼的问题就是OutOfMemoryError(内存溢出错误),但是如果我们了解JVM的内部实现和其运行时的数据区的工作机 ...
- Java 运行时数据区和内存模型
运行时数据区是指对 JVM 运行过程中涉及到的内存根据功能.目的进行的划分,而内存模型可以理解为对内存进行存取操作的过程定义.总是有人望文生义的将前者描述为 "Java 内存模型" ...
- JVM之Java运行时数据区(线程隔离区)
来源 JVM会在会在执行Java程序过程中把所管理的内存划分为若干区域,主要包括程序计数器(Program Counter Register),虚拟机栈(VM Stack),本地方法栈(Native ...
- Java运行时数据区概述
Java 虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域,这些区域都有各自的用途,如图所示: 程序计数器 程序计数器是一块比较小的内存空间,可以看作是当前线程所执行的字节 ...
- JVM内存布局(又叫Java运行时数据区)
JVM 堆中的数据是共享的,是占用内存最大的一块区域. 可以执行字节码的模块叫作执行引擎. 执行引擎在线程切换时怎么恢复?依靠的就是程序计数器. JVM 的内存划分与多线程是息息相关的.像我们程序中运 ...
随机推荐
- 12.引入依赖项目的时候,如果找不到jar
原因是bin没有生成,先clean依赖包,再clean原工程包,就可以了
- js或者jq的tab切换
<!DOCTYPE html><html><head><meta http-equiv="Content-Type" content=&q ...
- 微软虐我千百遍——记一次比较漫长的TFS数据库迁移
起因 七月三日早晨刚到公司,同事就跟我讲TFS开始返回 TF30042错误,报告数据库已满.按照处理问题的第一直觉,我上bing的英文网站搜了一下,发现是部署TFS的时候使用的SQL Express限 ...
- 如何使用slice,substr代替substring(原创)
//写这个是为了加深对substring和slice的理解 substring: 任何一个参数小于0,都会被替换成0.两个参数,最小值会被当做start,最大值当做end. 参数 描述 start 必 ...
- Vijos 1004 伊甸园日历游戏 博弈
描述 Adam和Eve玩一个游戏,他们先从1900.1.1到2001.11.4这个日期之间随意抽取一个日期出来.然后他们轮流对这个日期进行操作: 1 : 把日期的天数加1,例如1900.1.1变到19 ...
- ABP入门系列(19)——使用领域事件
ABP入门系列目录--学习Abp框架之实操演练 源码路径:Github-LearningMpaAbp 1.引言 最近刚学习了下DDD中领域事件的理论知识,总的来说领域事件主要有两个作用,一是解耦,二是 ...
- (转载)Jython 简单入门
转载链接:http://willzh.iteye.com/blog/307222 1. 用Jython调用Java类库 第一步.创建Java类 写一个简单的Java类,用Point来示例: impor ...
- JDBC注册驱动
一.Sql server2008 使用sqljdbc4.jar private static String driver = "com.microsoft.sqlserver.jdbc.SQ ...
- [POJ2104/HDU2665]Kth Number-主席树-可持久化线段树
Problem Kth Number Solution 裸的主席树,模板题.但是求k大的时候需要非常注意,很多容易写错的地方.卡了好久.写到最后还给我来个卡空间. 具体做法参见主席树论文<可持久 ...
- MySql单表最大8000W+ 之数据库遇瓶颈记
前言 昨晚救火到两三点,早上七点多醒来,朦胧中醒来发现电脑还开着,赶紧爬起来看昨晚执行的SQL命令结果.由于昨晚升级了阿里云的RDS,等了将近两个小时 还在 升降级中,早上阿里云那边回复升级过程中出现 ...