JVM运行时数据区内容简述
JVM运行时数据区分为五个部分:程序计数器、虚拟机栈、本地方法栈、堆、方法区。如下图所示,五部分其中又分为线程共享区域和线程私有区域,下面将分别介绍每一部分。

1. PC程序计数器
程序计数器是一块较小的空间,他的作用可看作是当前线程所执行的字节码的行号指示器。一个线程的挂起和恢复依赖于本区域,比如当一个线程因为发生某种情况需要挂起时,为了下一次恢复程序能从本次暂停区域继续执行,此时需要记录本线程挂起时运行到的位置。每条线程都需要一个独立的程序计数器,每条线程之间的计数器互不影响,独立存储,我们称这部分内存区域为线程私有的内存。由于本区域只需要存储线程执行到的地址,所以本区域是唯一一个不会发生OutOfMemoryError。
2. 虚拟机栈
与程序计数器一样,本区域也是线程私有的,他的生命周期与线程的生命周期相同。JVM Stack 描述的是Java方法执行的内存模型,每个方法被执行时都会创建一个栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法被调用直至执行完成的过程,就对应着一个栈帧在虚拟机中从入栈到出栈的过程。
当线程申请的栈深度大于JVM Stack所允许的最大深度时,JVM会抛出OverStackFlowError错误。JVM Stack的大小也是动态变化的,当内存不够时,系统会自动扩展,无法扩展时JVM会抛出OutOfMemoryError错误。
3. 本地方法栈
本区域也是线程私有的,其作用与上述虚拟机栈作用类似,不过不同的是其所服务的是本地方法。本地方法栈也会抛出OverStackFlowError和OutOfMemoryError错误。
4.Java 堆
Java堆是虚拟机所管理的内存中最大的一部分,正如上图所示,Java堆是所有线程共享的区域,本区域唯一的目的就是存储Java的实例对象,几乎所有的对象实例都在这里分配空间。堆也是JVM进行垃圾回收的主要区域,因此很多时候也被称为GC堆(Garbage Heap)。如果在堆中没有内存再完成实例分配,并且堆无法继续扩展时,本区域也会抛出OutOfMemoryError。另外原先处与方法区的运行时常量池在JDK 1.7之后也被移到了Java 堆中。
5. 方法区
与Java一样,本区域也是所有线程的共享区域,它用于存储已经被虚拟机加载的类信息、常量、静态变量、编译器编译后的代码等数据。根据JVM规范,当方法区无法满足内存分配时也会抛出OutOfMemoryError异常。
6. 运行时常量池
运行时常量池是方法区的一部分(jdk1.7之前)。Class文件中除了有关类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池,用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后进入方法区的运行时常量池中存放。
运行时常量池相对于Class文件常量池的另一个重要特征是具备动态性,Java语言并非不要求常量一定只有编译期才能产生,也就是并非预置入Class文件中常量池的内容才能进入方法区运行时常量池,运行期间也可以将新的常量池放入池中。
在实验验证周志明老师的深入理解JVM中的相关代码时,关于Java内存区域与内存溢出异常,运行下面这段代码(为了保证很快出现溢出错误,我们使用设置JVM运行参数-Xmx5m -XX:MaxPermSize=1M):
public static void main(String[] args) throws Throwable {
List<String> list = new ArrayList<String>();
int i=0;
while(true){
list.add(String.valueOf(i++).intern());
System.out.println(i);
}
}
在我的环境(jdk 1.8)下发生的错误为:
Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
at java.lang.Integer.toString(Unknown Source)
at java.lang.String.valueOf(Unknown Source)
at Test.main(Test.java:13)
并不是书中所描述的PermGen space溢出。所以又回头看出现的错误是GC overhead limit exceeded所以猜测运行时常量池是改变了位置?发现网上有很多这种验证运行时常量池被挪到了Java 堆中,这个也很容易验证,首先,源代码不变,增加运行时JVM的参数: -Xmx20m -Xms20m -XX:-UseGCOverheadLimit,这里的-XX:-UseGCOverheadLimit是关闭GC占用时间过长时会报的异常,然后限制堆的大小,运行程序,果然,一会后报异常:
Exception in thread “main” java.lang.OutOfMemoryError: Java heap space
从上面的异常可以知道我们测试增加的常量都放到了堆中。另外找到了关于官网对这点的说明:https://www.oracle.com/technetwork/java/javase/jdk7-relnotes-418459.html
参考资料:
深入理解Java虚拟机,周志明
https://www.jianshu.com/p/460aeab77b7f
https://www.jianshu.com/p/6173a467165e
JVM运行时数据区内容简述的更多相关文章
- Jvm运行时数据区
一:运行时数据区 Java虚拟机在执行Java程序的过程中会把它管理的内存分为若干个不同的数据区域.这些区域有着各自的用途,一级创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有些区域则依赖用户 ...
- Java内存管理:Java内存区域 JVM运行时数据区
转自:https://blog.csdn.net/tjiyu/article/details/53915869 下面我们详细了解Java内存区域:先说明JVM规范定义的JVM运行时分配的数据区有哪些, ...
- JVM总结(一):概述--JVM运行时数据区
大三下,趁着寒假重温一遍JVM,准备在一个系列来总价一下学习JVM的整个过程.争取在接下来的一个星期内更新完这一个系列,然后回家过年. JVM运行时数据区 线程私有的数据区 程序计数器 虚拟机栈 本地 ...
- Jvm运行时数据区 —— Java虚拟机结构小记
关于jvm虚拟机的文章网上都讲烂了.尤其是jvm运行时数据区的内容. 抱着眼见为实的想法,自己翻了翻JVM规范,花了点时间稍微梳理了一下. 以下是阅读Java虚拟机规范(Java SE 8版)的第二章 ...
- Java中的字符串常量池和JVM运行时数据区的相关概念
什么是字符串常量池 JVM为了减少字符串对象的重复创建,其维护了一个特殊的内存,这段内存被成为字符串常量池或者字符串字面量池 工作原理 当代码中出现字面量形式创建字符串对象时,JVM首先会对这个字面量 ...
- JVM运行时数据区及对象在内存中初始化的过程
JVM运行时数据区 Java虚拟机所管理的内存区域,也称为运行时数据区,分为以下几个运行时数据区,如图所示 程序计数器:当前程序所执行字节码的行号指示器 程序计数器(Program Counter R ...
- JVM 运行时数据区 (三)
JVM运行时数据区 运行时数据区由 程序计数器.java虚拟机栈.本地方法栈.堆.方法区 组成: 1.程序计数器 每一个Java线程都有一个程序计数器,用于保存程序执行到当前方法的哪一个指令,它是线程 ...
- JVM运行时数据区与JVM堆内存模型小结
前提 JVM运行时数据区和JVM内存模型是两回事,JVM内存模型指的是JVM堆内存模型. 那JVM运行时数据区又是什么? 它包括:程序计数器.虚拟机栈.本地方法栈.方法区.堆. 来看看它们都是干嘛的 ...
- JVM运行时数据区和垃圾回收机制
最近参考各种资料,尤其是<深入理解Java虚拟机 JVM高级特性和最佳实践>,大牛之作.把最近学习的Java虚拟机组成和垃圾回收机制总结一下. 你不会的都是新知识,学无止境,每天进步一点点 ...
随机推荐
- PHP中 PCRE正则表达式模式修饰符“u” 的使用。
u (PCRE_UTF8) 此修正符打开一个与 perl 不兼容的附加功能. 模式字符串被认为是utf-8的. 这个修饰符 从 unix 版php 4.1.0 或更高,win32版 php 4.2.3 ...
- Ubuntu16.04设置静态ip
给Ubuntu系统配置一个静态IP ,方法如下 : 1. sudo vi /etc/network/interfaces (本人更推荐使用 sudo gedit /etc/network/inter ...
- 第四节:详细讲解Java中的类和面向对象思想
前言 大家好,给大家带来详细讲解Java中的类和面向对象思想的概述,希望你们喜欢 类和面向对象 在Java中怎样理解对象,创建对象和引用:什么是引用,对于基础学习的同学,要深入了解引用.示例:Stri ...
- [Objective-C语言教程]关系运算符(8)
运算符是一个符号,告诉编译器执行特定的数学或逻辑操作. Objective-C语言内置很多运算符,提供如下类型的运算符 - 算术运算符 关系运算符 逻辑运算符 按位运算符 分配运算符 其它运算符 本教 ...
- 【design patterns】设计模式
1.单例设计模式(singleton) 用途举例:对于多个程序使用同一个配置信息对象时比如在连接数据库时使用单例模式,每次只取出一个连接 步骤:①私有化该类的构造函数 ②私有化一个静态的对象 ③公有化 ...
- python基础-字符串(6)
一.引言 当打来浏览器登录某些网站的时候,需要输入密码,浏览器把密码传送到服务器后,服务器会对密码进行验证,其验证过程是把之前保存的密码与本次传递过去的密码进行对比,如果相等,那么就认为密码正确,否则 ...
- Python文件操作与函数目录
文件操作 python文件操作 函数 Python函数学习——初步认识 Python函数学习——作用域与嵌套函数 Python函数学习——匿名函数 python内置函数 Python函数学习——递归 ...
- 国内使用google搜索引擎
百度搜索 "谷歌访问助手",点击第一个搜索结果,如下: 或者直接点击链接:http://www.ggfwzs.com/ ,然后点击相应的浏览器下载谷歌访问助手,解压,将解压好的谷 ...
- 最优路径算法合集(附python源码)(原创)
主要的最优(最短)路径算法: 一.深度优先算法:二.广度优先算法:三.Dijstra最短路径:四.floyd最短路径(待): 一.深度优先算法 图的深度优先搜索(Depth First Search) ...
- 设置build.gradle打包时自动加时间
在build.gradle中添加以下函数: def releaseTime() { return new Date().format("yyyyMMddHHmm", TimeZon ...