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虚拟机组成和垃圾回收机制总结一下. 你不会的都是新知识,学无止境,每天进步一点点 ...
随机推荐
- entity.Database.SqlQuery() 和entity.Database.SqlCommand()
原文地址: http://msdn.microsoft.com/en-us/library/gg715124(v=vs.103) 使用 EF 4.1 或者更新版本, 你可以直接执行任何数据库命令. 在 ...
- 一套高可用、易伸缩、高并发的IM群聊架构方案设计实践
本文原题为“一套高可用群聊消息系统实现”,由作者“于雨氏”授权整理和发布,内容有些许改动,作者博客地址:alexstocks.github.io.应作者要求,如需转载,请联系作者获得授权. 一.引言 ...
- itext实现pdf自动定位合同签订
需求 需要实现如下效果(最终效果) 思考 需求方的要求就是实现签订合同,实现方法不限,但过程中又提出需要在签章的过程中把签订日期的文字也打上去,这就有点坑了~ 一开始的想法是想办法定位需要签名的位置, ...
- SpringBoot集成Thymeleaf模板引擎
简单介绍 目前在JavaEE领域有几中比较常用的模板引擎,分别是Jsp.Velocity.Freemarker.Thymeleaf,对Freemark语法不是特别熟悉,不过对于前端页面渲染效率来说,j ...
- Robot Framework - 1 - 测试用例与测试库
01- 关于测试库(Test libraries) Test libraries provide the actual testing capabilities to Robot Framework ...
- vue搭建多页面开发环境
自从习惯开发了单页面应用,对多页面的页面间的相互跳转间没有过渡效果.难维护极度反感.但是最近公司技术老大说,当一个应用越来越大的时候单页面模式应付不来,但是没讲怎么应付不来,所以还得自己去复习一遍这两 ...
- RabbitMQ配置
RabbitMQ Configuration RabbitMQ提供多种配置方式:配置文件.环境变量.运行时参数等等. 默认配置文件的位置在/etc/rabbitmq/ Config File Loca ...
- ASP.NET Core 2.1 使用Docker运行
重要提示,本文为 ASP.NET Core 2.1 如果你是 2.2 那么请将文中的镜像换为 microsoft/dotnet:2.2.0-aspnetcore-runtime 即可,其他操作一样 1 ...
- springboot与ActiveMQ整合
前言 很多项目, 都不是一个系统就做完了. 而是好多个系统, 相互协作来完成功能. 那, 系统与系统之间, 不可能完全独立吧? 如: 在学校所用的管理系统中, 有学生系统, 资产系统, 宿舍系统等等. ...
- Dubbo架构学习整理
一. Dubbo诞生背景 随着互联网的发展和网站规模的扩大,系统架构也从单点的垂直结构往分布式服务架构演进,如下图所示: 单一应用架构:一个应用部署所有功能,此时简化CRUD的ORM框架是关键 垂直应 ...