Java虚拟机运行时数据区分为以下几个部分:
方法区、虚拟机栈、本地方法栈、堆、程序计数器。如下图所示:

一、程序计数器

程序计数器可看作当前线程所执行的字节码行号指示器,字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令。Java虚拟机的多线程是通过线程轮流切换以分配处理执行时间的方式进行的,因而为了确保线程切换后能够恢复到正确的执行位置,每条线程都有一个独立的程序计数器,各个线程计数器独立存储,互不影响,这类内存区域称为“线程私有”内存。当线程执行Java方法时,计数器记录的时正在执行虚拟机字节码指令的地址;如果执行Native方法,则计数器值为空(Undefine)。
程序计数器时唯一一个在Java虚拟机规范中没有任何规定OutOfMemoryError情况的内存区域。

二、Java虚拟机栈

Java虚拟机栈也是线程私有的,生命周期与线程相同。Java虚拟机栈是描述Java方法执行的内存模型:每个方法执行时都会创建一个栈帧(方法运行期间的基础数据结构),方法的执行过程对应着相应的栈帧在虚拟机中从入栈到出栈的过程。我们平时提到的栈就是虚拟机栈,也称为局部变量表部分。
局部变量表存放了编译期间的各种基本数据类型、对象引用和returAdress类型。其中,double和long占两个局部变量空间(Slot),其余数据类型占据一个。局部变量表所需内存是在编译期间完成分配的,当进入一个方法时,方法在帧中分配的局部变量空间大小是完全确定的,在方法运行期间局部变量表的大小不变。
Java虚拟机栈规定了两种异常状况:

  1. 线程请求栈深度大于虚拟机所允许的深度,抛出StackOverflowError异常。
  2. 虚拟机栈可以动态扩展,当扩展时无法申请到足够的内存时抛出OutOfMemoryError异常。

三、本地方法栈

本地方法栈为虚拟机使用的Native方法服务,本地方法栈可根据虚拟机的具体要求自由实现。由的虚拟机(如Sun HotSpot虚拟机)直接将本地方法栈和虚拟机栈赫尔为一。
本地方法栈出现的异常为StackOverflowError和OutOfMemoryError异常。

四、Java堆

Java堆(Java Heap)是Java虚拟机内存中最大的一块。堆被所有线程共享,在虚拟机启动时创建。堆的唯一目的就是存放对象实例。一般来说,几乎所有的对象实例都在堆上分配内存。
Java堆是垃圾收集器管理的主要区域,因此又称为“GC堆”。(为什么莫名想到垃圾堆?)从内存回收角度由于收集器采用分代收集算法,故将Java堆细分为新生代,老生代;从内存分配角度将线程共享的堆划分为多个线程私有分配缓冲区。
Java堆处于物理不连接的内存空间中,只要逻辑上连续即可。如果堆中没有内存完成实例分配,且堆无法再扩展时抛出OutOfMemoryError异常。

五、方法区

方法区也是线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时候编译器编译后的代码等数据。Java虚拟机规范将方法区描述为堆的一个逻辑部分,但为与java堆进行区分,称它为Non-Heap(非堆)。由于HotSpot虚拟机用永久代来实现方法区,因而部分人习惯将方法区称为“永久代”。垃圾回收在方法区是较少出现的,这个区域内存回收主要目标是对常量池的回收和对类型的卸载。当方法区无法满足内存分配需求时,将抛出OutOfMemoryError异常。

六、运行时常量池

运行时常量池是方法区的一部分,常量池是包含在Class文件中的一项信息,用于存放编译期生成的各种自面量和符号引用,这部分信息将在类加载后存放到方法区的运行时常量池中。一般来说,除了保存Class文件中的符号引用外,还会把翻译出来的直接引用也存储在运行时常量池中。
运行时常量池与Class文件常量池相比具有动态性,并非时只有预置在Class文件中的常量池内容才能进入运行时常量池,运行期间也可以将新的常量放入池中,如String的intern()方法。当常量池无法再申请到内存时抛出OutOfMemoryError异常。

七、直接内存

直接内存并不是虚拟机运行时数据区的一部分,但这部分内存被频繁的使用,也会OutOfMemoryError异常的出现。
JDK1.4加入Input/Output类,引入基于通道(Channel)与缓冲区(Buffer)的I/O方式,它可以使用Native函数库直接分配堆外内存,再通过Java堆中的DirectByteBuffer对象引用这块内存,以提高性能。它一般受到本机总内存与处理器寻址空间的限制,从而导致OutOfMemoryError异常。

本文主要参考《深入理解Java虚拟机——JVM高级特性与最佳实践》一书
另参考文章:
https://blog.csdn.net/u011116672/article/details/50994109

理解JVM之Java内存区域的更多相关文章

  1. 深入理解JVM - 1 - Java内存区域划分

    作者:梦工厂链接:https://www.jianshu.com/p/7ebbe102c1ae来源:简书简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处. Java与C++之间有一堵 ...

  2. 深入理解JVM(一)--Java 内存区域

    一.  运行时数据区域 Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域. Java虚拟机所管理的内存将会包括以下几个运行时数据区域:               ...

  3. 深入理解JVM(二)Java内存区域

    2.1 C.C++内存管理是由开发人员管理,而Java则交给了JVM进行自动管理 2.2 JVM运行时数据区:方法区.堆(运行时线程共享),虚拟机栈.本地方法栈.程序计数器(运行时线程隔离,私有) 1 ...

  4. JVM之Java内存区域

    JVM之Java内存区域 世界上并没有完美的程序,但我们并不因此而沮丧,因为写程序本来就是一个不断追求完美的过程. 一.JAVA内存区域 谈及JAVA虚拟机运行时数据区域就不得不祭出这张经典的图了: ...

  5. 学习jvm(一)--java内存区域

    前言 通过学习深入理解java虚拟机的教程,以及自己在网上的查询的资料,做一个对jvm学习过程中的小总结. 本文章内容首先讲解java的内存分布区域,之后讲内存的分配原则以及内存的监控工具.再下来会着 ...

  6. 深入理解JVM(6)——Java内存模型和线程

    Java虚拟机规范中定义了Java内存模型(Java Memory Model,JMM)用来屏蔽掉各种硬件和操作系统的内存访问差异,以实现让Java程序在各种平台下都能达到一致的内存访问效果(“即Ja ...

  7. 史上最详细JVM,Java内存区域讲解

    本人免费整理了Java高级资料,一共30G,需要自己领取:传送门:https://mp.weixin.qq.com/s/JzddfH-7yNudmkjT0IRL8Q 运行时数据区域 JVM载执行Jav ...

  8. JVM:Java内存区域与内存溢出异常

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

  9. 深入理解虚拟机之Java内存区域

    1 概述 对于Java程序员来说,在虚拟机自动内存管理机制下,不再需要像C/C++程序开发程序员这样为内一个new 操作去写对应的delete/free操作,不容易出现内存泄漏和内存溢出问题.正是因为 ...

随机推荐

  1. Git安装学习记录

    1.下载: https://gitforwindows.org/ 2.安装:https://blog.csdn.net/chengyuqiang/article/details/54178683 3. ...

  2. es6 学习小记 扩展运算符 三个点(...)

    参考: es6 扩展运算符 三个点(...) 经常回顾,方能真正掌握. 一.含义 扩展运算符( spread )是三个点(...).它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列. ...

  3. Doxygen的使用,配置及实例

    Doxygen是一种开源跨平台的,以类似JavaDoc风格描述的文档系统,可以从一套归档源文件开始,生成文档 下载Doxygen + Graphviz Doxygen可以生成动态文档 Graphviz ...

  4. Liferay开发实战(2):Service Builder生成持久化层,及开发服务层

    本文Liferay适用版本:v6.2.ce-ga6版 Liferay的插件体系是:模型-视图-控制器的portlet MVC框架.MVC是一个伟大的用于Web应用程序的设计模式,在实际应用中还应处理持 ...

  5. psutil 跨平台根据程序名杀进程

    笔者在项目中遇到过需要根据进程名杀进程的需求,利用python库psutil实现了此功能. 模块地址: https://pypi.python.org/pypi/psutil/   psutil功能 ...

  6. [LeetCode]无重复字符的最长子串

    给定一个字符串,找出不含有重复字符的最长子串的长度. 示例 1: 输入: "abcabcbb" 输出: 3 解释: 无重复字符的最长子串是 "abc",其长度为 ...

  7. 兼容IE9以下和非IE浏览器的原生js事件绑定函数

    事件绑定函数的demo如下: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "htt ...

  8. C#基础篇五值类型和引用类型

    using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace P01M ...

  9. 在Idea2017.1中编译时发生如下的错误

    错误 在Idea2017.1中编译时发生如下的错误 Information:java: javacTask: 源发行版 1.8 需要目标发行版 1.8 Information:java: Errors ...

  10. 交换排序:冒泡排序vs快速排序

    在开发的过程中, 经常会遇到集合排序, 那么一般情况下, 我们都是使用list.OrderBy()的方式来排序, 也无需关注到里面算法的实现是个什么样子. 正好这几天准备回顾一下数据结构与算法. 首先 ...