JVM-Java内存区域
JVM虚拟机运行时数据区结构分为:

其中方法区和堆是所有线程共享的内存区域,而Java栈、本地方法栈、程序计数器是线程私有的。
我们详细介绍运行时数据区的各个区域及其作用。
程序计数器:
一块较小的内存空间,字节码指示器工作时通过改变计数器的值来选取下一条需要执行的字节码指令。分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。
JVM的多线程通过线程轮流切换并分配处理器执行时间的方式来实现,在任何一个确定的时刻,一个处理器都只会执行一条线程中的指令,为了保证线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器,各条线程之间的计数器互不影响,独立存储,我们称这类内存区域为“线程私有”的内存。
存储内容:
当线程执行一个Java方法时,计数器记录的是正在执行的JVM字节码指令的地址。如果执行的是Native方法,计数器则为空(Undefined)。
该内存区域是唯一一个在jvm规范中没有规定任何OutOfMemoryError情况的区域。
Java虚拟机栈:
线程私有,生命周期与线程相同。虚拟机栈描述的是Java方法执行的内存模型:每个方法被执行的时候都会同时创建一个栈帧(Stack Frame)用于存储局部变量表、操作栈、动态链接、方法出口等信息。每一个方法被调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。
存储内容:
栈的存储可以说是局部变量表部分,存放了编译期可知的基本数据类型(boolean、byte、char、short、int、float、long、double),对象引用(reference类型,它不等同于对象本身,根据不同的虚拟机实现,它可能是一个指向对象起始地址的引用指针,也可能指向一个代表对象的句柄或者其他与此对象相关的位置)和returnAddress类型(指向了一条字节码指令的地址)。局部变量表所需的内存空间在编译期间完成分配,当进入一个方法时,这个方法需要在帧中分配多大的局部变量空间是完全确定的,在方法运行期间不会改变局部变量表的大小。
异常状况:
1、线程请求的栈深度大于JVM所允许的深度,抛出StackOverflowError异常。
2、虚拟机栈可以动态扩展时,当无法申请到足够的内存,就会抛出OutOfMemoryError异常。
本地方法栈:
作用与虚拟机栈非常相似,区别在于虚拟机栈服务于执行Java方法,而本地方法栈服务于执行Native方法。它也会抛出StackOverflowError和OutOfMemoryError异常
Java堆:
Java虚拟机管理的内存中最大的一块,被所有线程共享的内存区域。虚拟机启动时创建,该区域的目的就是存放对象实例,几乎所有对象实例都在这里分配内存。Java堆也是垃圾收集器管理的主要区域,又被称为GC堆。
从收集器的分代收集法来看,Java堆还可以分为:新生代和老年代。Java堆可以处于物理上不连续的内存空间,只要逻辑上是连续的即可。
存储内容:
几乎所有对象实例
异常情况:
如果在堆中没有内存完成实例分配,并且堆无法再扩展时,将抛出OutOfMemoryError异常。
方法区:
与Java堆一样,是各个线程共享的内存区域。别名非堆(Non-Heap),目的是与Java对区分开
存储内存:
存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据
Java虚拟机规范对这块区域限制非常宽松,除了和Java堆一样不需要连续的内存和可以选择固定大小或者可扩展外,还可以选择不实现垃圾收集。因此又有很多人将其趁为永久代。这个区域内存回收目标主要是针对常量池的回收和对类型的卸载,一般来说这个区域的回收“成绩”比较难以令人满意,尤其是类型的卸载,条件相当苛刻,但是这部分区域的回收确实是有必要的。
异常情况:
当方法区无法满足内存分配需求时,将抛出OutOfMemoryError异常。
方法区有时候也被称为持久代(PermGen),所有对象在实例化后的整个运行周期内,都被存放在堆内存中。堆内存又被划分成不同的部分:伊甸区(Eden),幸存者区域(Survivor Sapce),老年代(Old Generation Space)。
方法的执行都是伴随着线程的。原始类型的本地变量以及引用都存放在线程栈中。而引用关联的对象比如String,都存在在堆中。
运行时常量池(Runtime Constant Pool):
方法区的一部分,存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后进入方法区的运行时常量池中释放。
当常量池无法再申请到内存时会抛出OutOfMemoryError异常。
直接内存:
该区域并不是虚拟机运行时数据区的一部分,也不是Java虚拟机规范中定义的内存区域,但这部分内存被频繁使用也可能导致OutOfMemoryError异常。
本机直接内存分配不会受到Java堆大小的限制,但会受到本机总内存及处理器寻址空间的限制。配置虚拟机参数时,忽略直接内存,会使得各个内存区域总和大于物理内存限制,导致动态扩展时出现OutOfMemoryError异常。
OutOfMemoryErrors:
Exception in thread “main”: java.lang.OutOfMemoryError: Java heap space 原因:对象不能被分配到堆内存中 Exception in thread “main”: java.lang.OutOfMemoryError: PermGen space 原因:类或者方法不能被加载到持久代。它可能出现在一个程序加载很多类的时候,比如引用了很多第三方的库; Exception in thread “main”: java.lang.OutOfMemoryError: Requested array size exceeds VM limit 原因:创建的数组大于堆内存的空间 Exception in thread “main”: java.lang.OutOfMemoryError: request <size> bytes for <reason>. Out of swap space? 原因:分配本地分配失败。JNI、本地库或者Java虚拟机都会从本地堆中分配内存空间。 Exception in thread “main”: java.lang.OutOfMemoryError: <reason> <stack trace>(Native method) 原因:同样是本地方法内存分配失败,只不过是JNI或者本地方法或者Java虚拟机发现
参考资料:
《深入理解Java虚拟机——JVM高级特性与最佳实践(第2版)》
《纯洁的微信-JVM系列文章》:http://www.ityouknow.com/jvm.html
由衷的感谢提供学习资料的前辈们!!!
JVM-Java内存区域的更多相关文章
- JVM Java 内存区域透彻分析(转)
出处: Java 内存区域透彻分析 Java8内存模型—永久代(PermGen)和元空间(Metaspace) 这篇文章主要介绍Java内存区域,也是作为Java虚拟机的一些最基本的知识,理解了这 ...
- 一、JVM — Java内存区域
Java 内存区域详解 写在前面 (常见面试题) 基本问题 拓展问题 一 概述 二 运行时数据区域 2.1 程序计数器 2.2 Java 虚拟机栈 2.3 本地方法栈 2.4 堆 2.5 方法区 2. ...
- 深入理解JVM - Java内存区域与内存溢出异常 - 第二章
一 运行时数据区域 JVM在执行Java程序的过程中会把它管理的内存划分为若干个不同的数据区域.这些区域都有各自的用途,以及创建和销毁的时间. 程序计数器 程序计数器(Program Counter ...
- JVM java内存区域的介绍
jvm虚拟机在运行时需要用到的内存区域.广泛一点就是堆和栈,其实不然,堆和栈只是相对比较笼统的说法,真正区分有如下几个 先上图一: 总的就是 java的内存模型 内存模型又分堆内存(heap)和方法区 ...
- JVM——Java内存区域
一,概述: Java跟C++不同,在内存管理区域C++程序员拥有着最高权力,但是正是因为如此,所以C++程序员要照顾这个对象的生老病死,从创建到消亡都是由程序员决定的. 但是Java程序员在虚拟机的自 ...
- java虚拟机学习-JVM内存管理:深入Java内存区域与OOM(3)
概述 Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想进去,墙里面的人却想出来. 对于从事C.C++程序开发的开发人员来说,在内存管理领域,他们即是拥有最高权力的皇帝又 ...
- JVM参数配置 java内存区域
java内存区域 一些基本概念 http://www.importnew.com/18694.html https://www.cnblogs.com/wangyayun/p/6557851.html ...
- Java内存管理:Java内存区域 JVM运行时数据区
转自:https://blog.csdn.net/tjiyu/article/details/53915869 下面我们详细了解Java内存区域:先说明JVM规范定义的JVM运行时分配的数据区有哪些, ...
- JVM系列1:Java内存区域
JVM系列主要分享自己都虚拟机的理解,我自学时的知识框架多来源于<深入理解Java虚拟机_JVM高级特性与最佳实践>这本书,感兴趣的朋友可直接去阅读这本书. 本系列暂定有3部分,它们是学习 ...
- JVM自动内存管理机制——Java内存区域(下)
一.虚拟机参数配置 在上一篇<Java自动内存管理机制——Java内存区域(上)>中介绍了有关的基础知识,这一篇主要是通过一些示例来了解有关虚拟机参数的配置. 1.Java堆参数设置 a) ...
随机推荐
- Android为TV端助力 清除本应用里的各种数据的方法
public class DataCleanManager { /** * * 清除本应用内部缓存(/data/data/com.xxx.xxx/cache) * * * * @param conte ...
- java后台打开浏览器代码
import java.awt.Desktop; import java.io.IOException; import java.net.URI; import java.net.URISyntaxE ...
- 智能POS相关FAQ
1.安卓智能POS(一体机)的口碑点餐已知问题: 1.由于口碑的组合套餐接口不稳定,强烈建议商户不要使用组合套餐商品.已开通口碑后付的门店,如果有组合套餐商品,暂时不要使用组合套餐商品:有组合套餐需求 ...
- mssql sqlserver for xml EXPLICIT 用法详解说明
摘要:下文通过举例的方式,详细说明"for xml EXPLICIT"关键字的用法,如下所示:实验环境:sql server 2008 R2 EXPLICIT的功能:将数据表采用特 ...
- 洗礼灵魂,修炼python(87)-- 知识拾遗篇 —— 线程(1)
线程(上) 1.线程含义:一段指令集,也就是一个执行某个程序的代码.不管你执行的是什么,代码量少与多,都会重新翻译为一段指令集.可以理解为轻量级进程 比如,ipconfig,或者, python ...
- 转:敏捷开发之Scrum扫盲篇
现在敏捷开发是越来越火了,人人都在谈敏捷,人人都在学习Scrum和XP... 为了不落后他人,于是我也开始学习Scrum,今天主要是对我最近阅读的相关资料,根据自己的理解,用自己的话来讲述Scrum中 ...
- adb连接手机模拟器
首先,要保证模拟器和电脑在同一网段(手机模拟器设置为桥接模式即可) 我使用的是夜神模拟器. 然后查看一下adb版本, adb version 需要1.0.31往上的版本才能连接. 然后输入 adb c ...
- 安装window 7系统----计算机经验
上期我们已经成功制作了U盘启动并且也成功进入了PE系统了,在PE微型系统中,除了简单的装系统来恢复C盘,还有什么功能你们可以使用的呢?如果这一期我没有把其他内容讲解的话,千万别乱搞,到时我可能会讲解几 ...
- Git&GitHub
Git是一个开源的分布式版本控制系统,可以有效.高速地处理从很小到非常大的项目版本管理. Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软 ...
- PHP的move_uploaded_file()出错解决
今天用的PHP的move_uploaded_file方法保存前端上传的中文名称文件时,方法返回假,调试时错误码为2,错误信息为: move_uploaded_file(D:\ git_prj \ xx ...