一文看懂JVM内存区域分布与作用
那么我们在开始介绍Java内存区域之前,我们先放一张内存区域的图,方便我们后面介绍的时候可以对照着看。
须知,本文是根据JDK8来介绍的。

程序计数器
首先它是线程私有的,它也称为代码的行号指示器,字节码解释器就是通过改变程序计数器的位置来确定下一行要执行的代码,它不存在OOM。
如果线程正在执行一个Java方法,那么它记录的是正在执行虚拟机字节码指令的地址,如果是一个本地方法那么它的值为空。
Java虚拟机栈
它也是线程私有的,它的声明周期和线程一致。每个线程创建时都会创建一个虚拟机栈,内部保存了一个个的栈帧,每个栈帧就对应着一次方法的调用。既然知道了虚拟机栈里面存放的是一个个的栈帧,那么也不难猜出虚拟机栈里面都存储了什么东西。
Java虚拟机栈是存在OOM的,当线程所请求的栈的深度大于虚拟机栈的深度或者虚拟机栈可以动态扩容,当栈扩展时无法申请到足够的内存时,就会抛出OOM。
- 虚拟机栈内部结构:

局部变量表:
主要存储方法的参数,所有的基本类型数据和对象地址,以及返回地址类型(return address)。它以变量槽为最小的存储单位,Java虚拟机并没有规定一个变量槽占用多少内存空间,但是规定了一个变量槽可以存放一个32位以内的数据类型。如果存储的数据类型超过32位,比如long、double,那么就使用两个变量槽进行存储。
操作数栈:
操作数栈是一个先进后出的操作数栈,当一个方法刚开始执行的时候,一个新的栈帧也会随之被创建出来,这个方法的操作数栈是空的,它主要用于保存计算过程的中间结果,同时作为计算过程中变量临时的存储空间。如果被调用的方法有返回值,那么返回值将会被压入当前栈帧的操作数栈中。操作数栈并非采用索引的方式进行数据访问,而是通过入栈(push)和出栈(pop)操作来完成数据的访问。
动态链接:
大白话就是,栈帧中保存了一个方法的引用,当执行方法的时候,可以拿着这个引用到运行时常量池中找到这个方法。
动态链接的作用就是将这些方法的符号引用转换为调用方法的直接引用。
方法返回地址:
就是在方法执行结束之后,要返回下一条要执行代码位置的值,也就是程序计数器的值。
那么除了方法正常执行结束退出外,还有另外一种情况就是异常导致的方法退出,那么这种情况下是不会返回任何值的。对于抛出的异常,栈帧中不会做任何记录,但是会记录在一个异常表中。
本地方法栈
Java虚拟机栈为虚拟机执行Java方法服务,本地方法栈则为虚拟机使用到的本地方法服务。像JVM就有好多C语言写的方法,这个就需要本地方法栈来执行。
Java堆
Java堆是虚拟机中最大的一块内存空间,它被所有的线程共享,在虚拟机启动时创建。它唯一的目的就是存放对象实例。
如果面试被问到,所有的对象实例都是在堆中分配内存吗?这个时候你一定要回答,不是。
随着即时编译技术的发展进步,尤其是逃逸分析技术的日渐强大,栈上分配、变量替换等优化手段,让实例在”只在堆“中分配不再成为绝对。
Java堆是垃圾收集的主要区域,Java堆中也经常出现新生代、老年代、永久代等等,这里需要注意,这些并不是Java堆物理上的内存布局,它是作为垃圾收集器而划分一种内存布局。
方法区
方法区也是线程共享的区域,它主要用于存储被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据。
方法区它是可以被垃圾收集器进行回收的,主要针对类型的卸载和常量池的回收。
方法区也可以产生OOM,当方法区无法满足新的内存分配需求时,将抛出OutOfMemoryError异常。
运行时常量池
运行时常量池是方法区的一部分。Class文件中除了有类的版本、字段、方法、接口等信息外,还有一项信息是常量池表,它用来存储编译期生成的各种字面量和符号引用。
如果动态链接那块没看懂,那么看了运行常量池再翻回去看看是不是好理解了。
一文看懂JVM内存区域分布与作用的更多相关文章
- 一文搞懂JVM内存结构+GC
一.jvm是干什么的? 大家都知道java是跨平台语言,一次编译可以在不同操作系统上运行,怎么做到的呢,看下图: javac把写的源代码(java文件),编译成字节码(class文件),字节码部署到l ...
- 一文搞懂jvm内存结构
一.jvm是干什么的? 大家都知道java是跨平台语言,一次编译可以在不同操作系统上运行,怎么做到的呢,看下图: javac把写的源代码(java文件),编译成字节码(class文件),字节码部署到l ...
- 小白也能看懂的JVM内存区域
前言 最近在准备面试题刷到了JVM这块,作为一个小白,巩固知识点最好的方式就是亲手写出来并分享:相信我的理解,同样是小白的你,一定有很大的帮助.不信,请你往下看! JVM内存区域简介 如果有人问Jav ...
- 一文看懂大数据的技术生态圈,Hadoop,hive,spark都有了
一文看懂大数据的技术生态圈,Hadoop,hive,spark都有了 转载: 大数据本身是个很宽泛的概念,Hadoop生态圈(或者泛生态圈)基本上都是为了处理超过单机尺度的数据处理而诞生的.你可以把它 ...
- 谈谈JVM内存区域的划分
我们知道,计算机CPU和内存的交互是最频繁的,内存是我们的高速缓存区,用户磁盘和CPU的交互,而CPU运转速度越来越快,磁盘远远跟不上CPU的读写速度,才设计了内存,用户缓冲用户IO等待导致CPU的等 ...
- [转帖]一文看懂mysql数据库本质及存储引擎innodb+myisam
一文看懂mysql数据库本质及存储引擎innodb+myisam https://www.toutiao.com/i6740201316745740807/ 原创 波波说运维 2019-09-29 0 ...
- 一文看懂Java序列化
一文看懂Java序列化 简介 Java实现 Serializable 最基本情况 类的成员为引用 同一对象多次序列化 子父类引用序列化 可自定义的可序列化 Externalizable:强制自定义序列 ...
- 初始jvm(一)---jvm内存区域与溢出
jvm内存区域与溢出 为什么学习jvm 木板原理,最短的一块板决定一个水的深度,当一个系统垃圾收集成为瓶颈的时候,那么就需要你对jvm的了解掌握. 当一个系统出现内存溢出,内存泄露的时候,因为你懂jv ...
- JVM内存区域划分及垃圾回收
第一部分.闲扯+概述 近来在研读<深入理解java虚拟机>一书,读完之后做个小结,算是记录一下自己的学习所得,在成长的路上,只能死磕. 要理解JVM,就要先从其内存区域划分开始,知道其由几 ...
随机推荐
- vue2.0与3.0中的provide和inject 用法
1.provide/inject有什么用? 常用的父子组件通信方式都是父组件绑定要传递给子组件的数据,子组件通过props属性接收,一旦组件层级变多时,采用这种方式一级一级传递值非常麻烦,而且代码可读 ...
- echo -e 命令详解
echo在php中是输入那么在linux中是不是也是输入呢,当然echo在linux也是输入不过它的用法比php强大多了可以带参数及一些东西,下面我们来看一篇关于linux echo命令介绍及-n.- ...
- AQS快速入门
一.模板方法模式 父子类多态,父类中用一个方法调用执行所有所需要的方法: 父类: 子类: 主线程执行时候调用父类的模板方法: 二.AQS思想 sync都是独占锁,lock显示锁也是,只有读写锁是共享锁 ...
- 在EXCEL中批量添加超链接
在单元格中输入函数 =HYPERLINK(链接位置,[显示文本])
- postgres 基础SQL语句 增删改
查看已创建的数据库:select datname from pg_database; 查看所有数据库的详细信息:select * from pg_database 创建数据库:create datab ...
- Modern PHP interface 接口
The right way /dev/hell Code Response.php 接口 demo: modern-php/├── data│ └── stream.txt└── interfac ...
- mysql where in 数组解决小tips
由于sql语法要求,不可在in后面直接连数组,若数组形式下,则需要转换成逗号隔开的字符串 <?php$arr = array(1,2,3,4,5);$arr_string= join(',', ...
- 51nod1675-序列变换【莫比乌斯反演】
正题 题目连接:http://www.51nod.com/Challenge/Problem.html#problemId=1675 题目大意 给出两个长度为\(n\)的序列\(a,b\),求有多少对 ...
- VUE -input输入框字母转大写
示例: 输入自动转--->大写 <input type="text" placeholder="请输入证件号码" maxlength="1 ...
- 重磅 | 阿里开源首个 Serverless 开发者平台 Serverless Devs
Serverless 从概念提出到应用,已经走过了 8 个年头,开发者对 Serverless 的使用热情不断高涨.为帮助开发者实现一键体验多云产品,极速部署 Serverless 项目,10 月 2 ...