再探JVM内存模型
以前学JVM的时候看过《深入理解JVM》,当时看的很模糊也记了些笔记,更像是为了应付面试。事实是确实把笔记都背上了,春招找实习的时候,内存管理、类加载、垃圾回收三连背一遍。后来自己做项目的时候,涉及到JVM的部分还是不怎么理解,最近重读了上面的书并且看了一些技术大佬的专栏,用博客记录下自己学习过程与思考。
本篇文章关注两个问题:
Java字节码是什么?Java源代码怎么变成Java字节码的?
- Java字节码进入JVM后是怎么存储的?
为了解释上面问题,假设现在我们有一个Main类,调用compute方法执行计算操作,代码如下:
public class Math {
public static final Integer CONSTANT = 10;
public int compute() {
int a = 1;
int b = 2;
int c = (a + b) * 10;
return c;
}
public static void main(String[] args) {
Math math1 = new Math();
Math math2 = new Math();
math1.compute();
math2.compute();
}
}
对于第一个问题: Class文件是一组以8位字节位基础的单位的二进制流,下图就是显示了如何生成字节码文件。

使用Sublime Text查看Math.class,图片只截取了部分,编辑器是使用16进制显示的。为了方便查看,我们使用 javap -c 指令对代码进行反汇编,就可以得得到可读性更强的文件。


那么Class文件被加载后在JVM中是如何存储的呢?我们以 HotSpot VM为例,这是目前使用最广泛的Java虚拟机。虚拟机主要由类装载子系统、运行时数据区和执行引擎三部分组成。JVM内存模型将运行时数据区分为五个部分,下面图中其中紫色部分是线程私有的,黄色是线程公有的。我们对着字节码文件详细的解释下这个5个部分分别存放的是什么。
栈又叫做线程栈,生命周期与线程相同。栈主要由局部变量表、操作数栈、动态链接、方法出口组成。当main方法运行时JVM会在栈内存区域给主线程分配一块内存,main方法和compute方法执行时,会创建单独的栈帧用于存储方法的一些信息。配合着字节码来说明:
- 局部变量表:存放的是方法在执行时各种基本类型和引用类型变量,以及returnAddress类型(指向了一条字节码指令的地址);
- 方法出口:保存的是方法执行完后回到主线程的哪个位置。对于main栈帧,局部变量表里的math变量存放的是堆内存中math变量的地址。
- 操作数栈:临时存放方法执行时的变量
- 动态链接:Class 文件中存放了大量的符号引用,这些符号引用指向的是方法。程序运行期间调用方法时,根据运行时常量池的参数,静态符号引用变成直接引用;对象头里的指针会动态的找到方法区中存储的调用方法的信息。

程序计数器:记录的是字节码指令正在执行或者即将执行的行号。
本地方法栈:作用和虚拟机栈类似,为native修饰的方法服务。
方法区:JDK1.8及以后称为元空间,存储被虚拟机加载的类信息、常量、静态变量等。1.8以后方法区使用的是本机的内存。
堆:堆是JVM内存模型中最大的一块,虚拟机启动时就会创建,存储的是大部分对象。
整个代码的执行流程在JVM内存中是这样的,不作更详细的解释了,关键信息在图中已标明。
参考资料:《深入理解Java虚拟机》第二版 周志朋
《深入拆解Java虚拟机》郑雨迪
《JVM虚拟机底层原理分析与性能调优》程序员诸葛
再探JVM内存模型的更多相关文章
- JVM内存模型和性能优化 转
JVM内存模型和性能优化 JVM内存模型优点 内置基于内存的并发模型: 多线程机制 同步锁Synchronization 大量线程安全型库包支持 基于内存的并发机制,粒度灵活控制,灵活度高于 ...
- JVM内存模型和性能优化
JVM内存模型优点 内置基于内存的并发模型: 多线程机制 同步锁Synchronization 大量线程安全型库包支持 基于内存的并发机制,粒度灵活控制,灵活度高于数据库锁. 多核并行计算模 ...
- 记录JVM内存模型,参数含义和优化
一.JVM内存模型 (图片来自网络) 根据Java虚拟机规范,JVM将内存划分为: New(年轻代) Tenured(年老代) Perm (永久代) 其中New和Tenured属于堆内存,堆内存会从J ...
- JVM的stack和heap,JVM内存模型,垃圾回收策略,分代收集,增量收集
(转自:http://my.oschina.net/u/436879/blog/85478) 在JVM中,内存分为两个部分,Stack(栈)和Heap(堆),这里,我们从JVM的内存管理原理的角度来认 ...
- JVM内存模型以及垃圾收集策略解析
http://xmuzyq.iteye.com/blog/599750 一 JVM内存模型 1.1 Java栈 Java栈是与每一个线程关联的,JVM在创建每一个线程的时候,会分配一定的栈空间给线程. ...
- JVM内存模型及垃圾收集策略解析
一 JVM内存模型 1.1 Java栈 Java栈是与每一个线程关联的,JVM在创建每一个线程的时候,会分配一定的栈空间给线程.它主要用来存储线程执行过程中的局部变量,方法的返回值,以及方法调用上下文 ...
- JVM内存模型及垃圾收集策略解析(一)
JVM内存模型是Java的核心技术之一,之前51CTO曾为大家介绍过JVM分代垃圾回收策略的基础概念,现在很多编程语言都引入了类似Java JVM的内存模型和垃圾收集器的机制,下面我们将主要针对Jav ...
- 老李谈JVM内存模型
老李谈JVM内存模型 poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣,请大家咨询qq:908821478,咨 ...
- jvm内存模型-回收算法-和内存分配以及jdk、jre、jvm是什么关系(阿里,美团,京东面试题)
1.什么是jvm?(1)jvm是一种用于计算设备的规范,它是一个虚构出来的机器,是通过在实际的计算机上仿真模拟各种功能实现的.(2)jvm包含一套字节码指令集,一组寄存器,一个栈,一个垃圾回收堆和一个 ...
随机推荐
- Java实现 LeetCode 662 二叉树最大宽度(递归)
662. 二叉树最大宽度 给定一个二叉树,编写一个函数来获取这个树的最大宽度.树的宽度是所有层中的最大宽度.这个二叉树与满二叉树(full binary tree)结构相同,但一些节点为空. 每一层的 ...
- Java实现十六进制转十进制
基础练习 十六进制转十进制 时间限制:1.0s 内存限制:512.0MB 提交此题 锦囊1 锦囊2 问题描述 从键盘输入一个不超过8位的正的十六进制数字符串,将它转换为正的十进制数后输出. 注:十六进 ...
- Java实现 LeetCode 315 计算右侧小于当前元素的个数
315. 计算右侧小于当前元素的个数 给定一个整数数组 nums,按要求返回一个新数组 counts.数组 counts 有该性质: counts[i] 的值是 nums[i] 右侧小于 nums[i ...
- Java实现 LeetCode 19删除链表的倒数第N个节点
19. 删除链表的倒数第N个节点 给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点. 示例: 给定一个链表: 1->2->3->4->5, 和 n = 2. 当 ...
- java实现第六届蓝桥杯星系炸弹
星系炸弹 题目描述 在X星系的广袤空间中漂浮着许多X星人造"炸弹",用来作为宇宙中的路标. 每个炸弹都可以设定多少天之后爆炸. 比如:阿尔法炸弹2015年1月1日放置,定时为15天 ...
- 解Bug之路-记一次存储故障的排查过程
解Bug之路-记一次存储故障的排查过程 高可用真是一丝细节都不得马虎.平时跑的好好的系统,在相应硬件出现故障时就会引发出潜在的Bug.偏偏这些故障在应用层的表现稀奇古怪,很难让人联想到是硬件出了问题, ...
- Linux 用户管理命令-usermod和chage
usermod和useradd命令的使用相类似,useradd针对的是新创建的用户可以修改他的信息,usermod则可以修改已经存在的用户的信息,选项也基本相同 usermod [选项] 用户名 -L ...
- PAT 有几个PAT
字符串 APPAPT 中包含了两个单词 PAT,其中第一个 PAT 是第 2 位(P),第 4 位(A),第 6 位(T):第二个 PAT 是第 3 位(P),第 4 位(A),第 6 位(T). 现 ...
- Mybatis多表操作
一:引言 在学习完前面的mybatis基本语法后,大家都有个认知,这个Mybatis太强大了,比之前使用JDBC写方便多了,但是你们当初在使用原生JDBC写SQL查询的时候有没有遇到过多表查询呢?肯定 ...
- 【大厂面试06期】谈一谈你对Redis持久化的理解?
Redis持久化是面试中经常会问到的问题,这里主要通过对以下几个问题进行分析,帮助大家了解Redis持久化的实现原理. 1.Redis持久化是什么? 2.Redis持久化有哪些策略?各自的实现原理是怎 ...