再探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包含一套字节码指令集,一组寄存器,一个栈,一个垃圾回收堆和一个 ...
随机推荐
- Python基础语法之“print()”函数
print()函数是Python入门的第一个必学知识点,它经常被用来调试已写的代码,检验效果,今天小老鼠就带你盘点一下print()函数在Python中如何使用. print()函数的工作流程是这样的 ...
- 用struts的action运行jsp页面
struts是开源框架.使用Struts的目的是为了帮助我们减少在运用MVC设计模型来开发Web应用的时间.如果我们想混合使用Servlets和JSP的优点来建立可扩展的应用,struts是一个不错的 ...
- MySql多表查询优化
一.多表查询连接的选择 相信内连接,左连接什么的大家都比较熟悉了,当然还有左外连接什么的,基本用不上,我就补贴出来了,这个图只是让大家熟悉一下各种连接查询.然后要告诉大家的是,需要根据查询的信息,想好 ...
- 解Bug之路-记一次JVM堆外内存泄露Bug的查找
解Bug之路-记一次JVM堆外内存泄露Bug的查找 前言 JVM的堆外内存泄露的定位一直是个比较棘手的问题.此次的Bug查找从堆内内存的泄露反推出堆外内存,同时对物理内存的使用做了定量的分析,从而实锤 ...
- 用Java模拟游戏重力的实现(弹跳)
年末开了Java实训大作业 想了好几天决定选择马里奥小游戏 发现即使做出来但是跳跃功能是很“笨拙”的,和我们玩的游戏不一样,没有跳跃速度的快慢什么的,后来才知道这个叫做游戏里面重力的模拟. 组队做系统 ...
- Koa源码解析,带你实现一个迷你版的Koa
前言 本文是我在阅读 Koa 源码后,并实现迷你版 Koa 的过程.如果你使用过 Koa 但不知道内部的原理,我想这篇文章应该能够帮助到你,实现一个迷你版的 Koa 不会很难. 本文会循序渐进的解析内 ...
- intput子系统
1.按键驱动程序的第一个版本:day07/04 //内核模块的基本要求 init.h module.h LICENSE struct cdev btn_cdev; b ...
- Python 中class的小例子
class Song(): def __init__(self,lyrics): self.lyrics=lyrics def sing_a_song(self): for line in self. ...
- while or if
多线程 wait && notifyAll 模式实现时,如果 锁中有判断,对共享对象有curd 操作时,有可能出现异常 即,判断 条件 这个时候关键字有 if 改为while 即可 ...
- 商城08——activeMQ 使用消息队列同步索引库
1. 课程计划 1.什么是MQ 2.MQ的应用场景 3.ActiveMQ的使用方法. 4.使用消息队列实现商品同步. 2. 同步索引库分析 方案一:在taotao-manager中,添加商品的业务 ...