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. SQL Server 用户'NT AUTHORITY\IUSR' 登录失败

    今天打开网站时,突然报这个错误,平时都好好的 Cannot open database "JMECC" requested by the login. The login fail ...

  2. Java - Tips

    001 - Java中print.printf与println的区别? printf:格式化输出,用来控制输出的格式. print:标准输出,不换行. println:标准输出,换行.例如,print ...

  3. java分模块项目在idea中使用maven打包失败(ps:maven常用到的命令)

    一.分模块项目打包失败 情况:项目是分模块创建的,一些公共的方法是单独的一个模块common,其他模块依赖于此模块,poom依赖已经添加了,项目可以正常运行,但使用maven打包时出现了问题:找不到依 ...

  4. Django-cookie的保存以及删除操作

    Django里的保存cookie和flask是有区别的 今天我就说以下Django里的cookie操作 #先导包 #导入Django模块 from django.http import HttpRes ...

  5. [0day]微软VS全版本DLL却持漏洞(VS2015 VS2013 VS2012 VS2010 VS2008)

    <无敌破坏王>大师兄说的 "我不是针对谁,而是在座的各位,都是垃圾"前几天在国外论坛看到一个VS2010 DLL却持漏洞 测试发现是全版本 实际上2014年在某越南黑客 ...

  6. MVC3学习:利用mvc3+ajax检测用户是否被注册

    假设用户名是保存在表Users中.关系模式为Users(Uid,UserName,PassWord) 可先利用mvc自带的模板生成Create页面. 将填写用户名的地方,由原来的 <div cl ...

  7. ElasticSearch入门3: Spring Boot集成ElasticSearch

    第一步:创建项目elasticsearch 编写pom文件 <?xml version="1.0" encoding="UTF-8"?> <p ...

  8. 全网最详细的Cloudera Hue执行./build/env/bin/supervisor 时出现KeyError: "Couldn't get user id for user hue"的解决办法(图文详解)

    不多说,直接上干货! 问题详情 如下: [root@bigdata-pro01 hue--cdh5.12.1]# ./build/env/bin/supervisor Traceback (most ...

  9. Spring Boot + Spring Cloud 实现权限管理系统 后端篇(二):数据库设计

    数据库设计 系统主要包含用户(sys_user).组织(sys_dept).角色(sys_role).菜单(sys_menu).角色组织(sys_role_dept).角色菜单(sys_role_me ...

  10. 使用Codis-Admin命令配置环境

    前提条件:由于22.35.60服务器各自配置了Codis-Service主机,所以22.35.60对应的ip和端口要求能通信和互信访问,为下面通过60的dashboard配置22.35.60实现分组. ...