理解JVM之Java内存区域
Java虚拟机运行时数据区分为以下几个部分:
方法区、虚拟机栈、本地方法栈、堆、程序计数器。如下图所示:
一、程序计数器
程序计数器可看作当前线程所执行的字节码行号指示器,字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令。Java虚拟机的多线程是通过线程轮流切换以分配处理执行时间的方式进行的,因而为了确保线程切换后能够恢复到正确的执行位置,每条线程都有一个独立的程序计数器,各个线程计数器独立存储,互不影响,这类内存区域称为“线程私有”内存。当线程执行Java方法时,计数器记录的时正在执行虚拟机字节码指令的地址;如果执行Native方法,则计数器值为空(Undefine)。
程序计数器时唯一一个在Java虚拟机规范中没有任何规定OutOfMemoryError情况的内存区域。
二、Java虚拟机栈
Java虚拟机栈也是线程私有的,生命周期与线程相同。Java虚拟机栈是描述Java方法执行的内存模型:每个方法执行时都会创建一个栈帧(方法运行期间的基础数据结构),方法的执行过程对应着相应的栈帧在虚拟机中从入栈到出栈的过程。我们平时提到的栈就是虚拟机栈,也称为局部变量表部分。
局部变量表存放了编译期间的各种基本数据类型、对象引用和returAdress类型。其中,double和long占两个局部变量空间(Slot),其余数据类型占据一个。局部变量表所需内存是在编译期间完成分配的,当进入一个方法时,方法在帧中分配的局部变量空间大小是完全确定的,在方法运行期间局部变量表的大小不变。
Java虚拟机栈规定了两种异常状况:
- 线程请求栈深度大于虚拟机所允许的深度,抛出StackOverflowError异常。
- 虚拟机栈可以动态扩展,当扩展时无法申请到足够的内存时抛出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内存区域的更多相关文章
- 深入理解JVM - 1 - Java内存区域划分
作者:梦工厂链接:https://www.jianshu.com/p/7ebbe102c1ae来源:简书简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处. Java与C++之间有一堵 ...
- 深入理解JVM(一)--Java 内存区域
一. 运行时数据区域 Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域. Java虚拟机所管理的内存将会包括以下几个运行时数据区域: ...
- 深入理解JVM(二)Java内存区域
2.1 C.C++内存管理是由开发人员管理,而Java则交给了JVM进行自动管理 2.2 JVM运行时数据区:方法区.堆(运行时线程共享),虚拟机栈.本地方法栈.程序计数器(运行时线程隔离,私有) 1 ...
- JVM之Java内存区域
JVM之Java内存区域 世界上并没有完美的程序,但我们并不因此而沮丧,因为写程序本来就是一个不断追求完美的过程. 一.JAVA内存区域 谈及JAVA虚拟机运行时数据区域就不得不祭出这张经典的图了: ...
- 学习jvm(一)--java内存区域
前言 通过学习深入理解java虚拟机的教程,以及自己在网上的查询的资料,做一个对jvm学习过程中的小总结. 本文章内容首先讲解java的内存分布区域,之后讲内存的分配原则以及内存的监控工具.再下来会着 ...
- 深入理解JVM(6)——Java内存模型和线程
Java虚拟机规范中定义了Java内存模型(Java Memory Model,JMM)用来屏蔽掉各种硬件和操作系统的内存访问差异,以实现让Java程序在各种平台下都能达到一致的内存访问效果(“即Ja ...
- 史上最详细JVM,Java内存区域讲解
本人免费整理了Java高级资料,一共30G,需要自己领取:传送门:https://mp.weixin.qq.com/s/JzddfH-7yNudmkjT0IRL8Q 运行时数据区域 JVM载执行Jav ...
- JVM:Java内存区域与内存溢出异常
Java 虚拟机在执行 Java 程序的过程中会把它所管理的内存划分为若干个不同的数据区域.这些区域都有各自的用途,以及创建和销毁时间,有些区域随着虚拟机进程的启动而存在,有些区域依赖用户线程的启动和 ...
- 深入理解虚拟机之Java内存区域
1 概述 对于Java程序员来说,在虚拟机自动内存管理机制下,不再需要像C/C++程序开发程序员这样为内一个new 操作去写对应的delete/free操作,不容易出现内存泄漏和内存溢出问题.正是因为 ...
随机推荐
- 【react】当react框架遇上百度地图
百度地图官方文档的使用指导是这样说的:在页面中引入<script type="text/javascript" src="http://api.map.baid ...
- cad2020卸载/安装失败/如何彻底卸载清除干净cad2020注册表和文件的方法
cad2020提示安装未完成,某些产品无法安装该怎样解决呢?一些朋友在win7或者win10系统下安装cad2020失败提示cad2020安装未完成,某些产品无法安装,也有时候想重新安装cad2020 ...
- javaweb项目中的过滤器的使用
翻阅博客园的的时候,看到两篇关于javaweb过滤器的帖子写的很好,这里备忘一下: 过滤器基础:http://www.cnblogs.com/xdp-gacl/p/3948353.html 获取器案例 ...
- servlet实现商品商场项目
1.1 1.创建四个包DButils reposiable service servletJPK DButils包中的类jdbcutils.java 用于获取工具类DButils工具类的DataSou ...
- 设计模式《JAVA与模式》之备忘录模式
在阎宏博士的<JAVA与模式>一书中开头是这样描述备忘录(Memento)模式的: 备忘录模式又叫做快照模式(Snapshot Pattern)或Token模式,是对象的行为模式. 备忘录 ...
- Golang 中哪些值是不可以寻址的
不可以寻址, 指的是不能通过&获得其地址. golang中不能寻址的可以总结为:不可变的,临时结果和不安全的.只要符合其中任何一个条件,它就是不可以寻址的. 具体为: 常量的值. 基本类型值的 ...
- Redhat/CentOS 制作本地yum源
一.制作本地yum源的场景有: (1) 操作系统ISO文件是通过光驱读取的 (2) 操作系统ISO文件是通过USB设备挂载的 (3) 操作系统ISO文件是被上传到本地文件夹的形式 二. 这3种配置方式 ...
- System.Threading.Tasks.Task 引起的 IIS 应用池崩溃
接口服务运行一段时间后,IIS应用池就会突然挂掉,事件查看日志,会有事件日志Event ID为5011的错误 为应用程序池“PokeIn”提供服务的进程在与 Windows Process Activ ...
- JavaScript初探一
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <m ...
- vue父组件传参给子组件
其实组件之间传参有很多种方法: 1.通过本地存储 2.使用vuex状态管理 今天记录一下第三种方法 1.首页我们先创建一个项目(创建项目自行百度) 2.打开项目,在components文件夹下新建一个 ...