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运行时数据区内容简述的更多相关文章

  1. Jvm运行时数据区

    一:运行时数据区 Java虚拟机在执行Java程序的过程中会把它管理的内存分为若干个不同的数据区域.这些区域有着各自的用途,一级创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有些区域则依赖用户 ...

  2. Java内存管理:Java内存区域 JVM运行时数据区

    转自:https://blog.csdn.net/tjiyu/article/details/53915869 下面我们详细了解Java内存区域:先说明JVM规范定义的JVM运行时分配的数据区有哪些, ...

  3. JVM总结(一):概述--JVM运行时数据区

    大三下,趁着寒假重温一遍JVM,准备在一个系列来总价一下学习JVM的整个过程.争取在接下来的一个星期内更新完这一个系列,然后回家过年. JVM运行时数据区 线程私有的数据区 程序计数器 虚拟机栈 本地 ...

  4. Jvm运行时数据区 —— Java虚拟机结构小记

    关于jvm虚拟机的文章网上都讲烂了.尤其是jvm运行时数据区的内容. 抱着眼见为实的想法,自己翻了翻JVM规范,花了点时间稍微梳理了一下. 以下是阅读Java虚拟机规范(Java SE 8版)的第二章 ...

  5. Java中的字符串常量池和JVM运行时数据区的相关概念

    什么是字符串常量池 JVM为了减少字符串对象的重复创建,其维护了一个特殊的内存,这段内存被成为字符串常量池或者字符串字面量池 工作原理 当代码中出现字面量形式创建字符串对象时,JVM首先会对这个字面量 ...

  6. JVM运行时数据区及对象在内存中初始化的过程

    JVM运行时数据区 Java虚拟机所管理的内存区域,也称为运行时数据区,分为以下几个运行时数据区,如图所示 程序计数器:当前程序所执行字节码的行号指示器 程序计数器(Program Counter R ...

  7. JVM 运行时数据区 (三)

    JVM运行时数据区 运行时数据区由 程序计数器.java虚拟机栈.本地方法栈.堆.方法区 组成: 1.程序计数器 每一个Java线程都有一个程序计数器,用于保存程序执行到当前方法的哪一个指令,它是线程 ...

  8. JVM运行时数据区与JVM堆内存模型小结

    前提 JVM运行时数据区和JVM内存模型是两回事,JVM内存模型指的是JVM堆内存模型. 那JVM运行时数据区又是什么? 它包括:程序计数器.虚拟机栈.本地方法栈.方法区.堆. 来看看它们都是干嘛的 ...

  9. JVM运行时数据区和垃圾回收机制

    最近参考各种资料,尤其是<深入理解Java虚拟机 JVM高级特性和最佳实践>,大牛之作.把最近学习的Java虚拟机组成和垃圾回收机制总结一下. 你不会的都是新知识,学无止境,每天进步一点点 ...

随机推荐

  1. 一篇入门 — Scala 宏

    前情回顾 上一节, 我简单的说了一下反射的基本概念以及运行时反射的用法, 同时简单的介绍了一下编译原理知识, 其中我感觉最为绕的地方, 就属泛型的几种使用方式了. 而最抽象的概念, 就是对于符号和抽象 ...

  2. 脑残式网络编程入门(五):每天都在用的Ping命令,它到底是什么?

    本文引用了公众号纯洁的微笑作者奎哥的技术文章,感谢原作者的分享. 1.前言   老于网络编程熟手来说,在测试和部署网络通信应用(比如IM聊天.实时音视频等)时,如果发现网络连接超时,第一时间想到的就是 ...

  3. 最火移动端跨平台方案盘点:React Native、weex、Flutter

    1.前言 跨平台一直是老生常谈的话题,cordova.ionic.react-native.weex.kotlin-native.flutter等跨平台框架的百花齐放,颇有一股推倒原生开发者的势头. ...

  4. Nginx+tomcat集群使用redis共享session

    一 :nginx负载均衡 当Tomcat当做独立的Servlet容器来运行时,可看做是能运行Java Servlet的独立Web服务器. 此外 Tomcat还可以作为其他Web服务器进程内或者进程外的 ...

  5. 第86节:Java中的JQuery基础

    第86节:Java中的JQuery 前言复习 定时器: setInterval clearInterval setTimeout clearTimeout 显示: img.style.display ...

  6. oracle select in超过1000条报错解决方法

    本博客介绍oracle select in超过1000条数据的解决方法,java框架是采用mybatis的,这可以说是一种比较常见的错误:select * from A where id in(... ...

  7. java后端服务器读取excel将数据导入数据库

    使用的是easypoi,官网文档:http://easypoi.mydoc.io/ /** * 导入Excel文件 */ @PostMapping("/importTeacher" ...

  8. 机器学习入门12 - 分类 (Classification)

    原文链接:https://developers.google.com/machine-learning/crash-course/classification/ 1- 指定阈值 为了将逻辑回归值映射到 ...

  9. Python - 使用objgraph生成对象引用关系图

    1- objgraph简介 HomePage:https://mg.pov.lt/objgraph/ PyPI:https://pypi.org/project/objgraph/ 一般用于分析pyt ...

  10. 10 种保护 Spring Boot 应用的绝佳方法

    原文:developer.okta.com/blog/2018/07/30/10-ways-to-secure-spring-boot 译文:www.jdon.com/49653 Spring Boo ...