以前学JVM的时候看过《深入理解JVM》,当时看的很模糊也记了些笔记,更像是为了应付面试。事实是确实把笔记都背上了,春招找实习的时候,内存管理、类加载、垃圾回收三连背一遍。后来自己做项目的时候,涉及到JVM的部分还是不怎么理解,最近重读了上面的书并且看了一些技术大佬的专栏,用博客记录下自己学习过程与思考。

本篇文章关注两个问题:

  1. Java字节码是什么?Java源代码怎么变成Java字节码的?

  2. 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内存模型的更多相关文章

  1. JVM内存模型和性能优化 转

    JVM内存模型和性能优化 JVM内存模型优点 内置基于内存的并发模型:      多线程机制 同步锁Synchronization 大量线程安全型库包支持 基于内存的并发机制,粒度灵活控制,灵活度高于 ...

  2. JVM内存模型和性能优化

    JVM内存模型优点 内置基于内存的并发模型:      多线程机制 同步锁Synchronization 大量线程安全型库包支持 基于内存的并发机制,粒度灵活控制,灵活度高于数据库锁. 多核并行计算模 ...

  3. 记录JVM内存模型,参数含义和优化

    一.JVM内存模型 (图片来自网络) 根据Java虚拟机规范,JVM将内存划分为: New(年轻代) Tenured(年老代) Perm (永久代) 其中New和Tenured属于堆内存,堆内存会从J ...

  4. JVM的stack和heap,JVM内存模型,垃圾回收策略,分代收集,增量收集

    (转自:http://my.oschina.net/u/436879/blog/85478) 在JVM中,内存分为两个部分,Stack(栈)和Heap(堆),这里,我们从JVM的内存管理原理的角度来认 ...

  5. JVM内存模型以及垃圾收集策略解析

    http://xmuzyq.iteye.com/blog/599750 一 JVM内存模型 1.1 Java栈 Java栈是与每一个线程关联的,JVM在创建每一个线程的时候,会分配一定的栈空间给线程. ...

  6. JVM内存模型及垃圾收集策略解析

    一 JVM内存模型 1.1 Java栈 Java栈是与每一个线程关联的,JVM在创建每一个线程的时候,会分配一定的栈空间给线程.它主要用来存储线程执行过程中的局部变量,方法的返回值,以及方法调用上下文 ...

  7. JVM内存模型及垃圾收集策略解析(一)

    JVM内存模型是Java的核心技术之一,之前51CTO曾为大家介绍过JVM分代垃圾回收策略的基础概念,现在很多编程语言都引入了类似Java JVM的内存模型和垃圾收集器的机制,下面我们将主要针对Jav ...

  8. 老李谈JVM内存模型

    老李谈JVM内存模型   poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣,请大家咨询qq:908821478,咨 ...

  9. jvm内存模型-回收算法-和内存分配以及jdk、jre、jvm是什么关系(阿里,美团,京东面试题)

    1.什么是jvm?(1)jvm是一种用于计算设备的规范,它是一个虚构出来的机器,是通过在实际的计算机上仿真模拟各种功能实现的.(2)jvm包含一套字节码指令集,一组寄存器,一个栈,一个垃圾回收堆和一个 ...

随机推荐

  1. Java实现 LeetCode 820 单词的压缩编码(字典树)

    820. 单词的压缩编码 给定一个单词列表,我们将这个列表编码成一个索引字符串 S 与一个索引列表 A. 例如,如果这个列表是 ["time", "me", & ...

  2. Java实现 蓝桥杯VIP 算法训练 递归求二进制表示位数

    问题描述 给定一个十进制整数,返回其对应的二进制数的位数.例如,输入十进制数9,其对应的二进制数是1001,因此位数是4. 样例输入 一个满足题目要求的输入范例. 9 样例输出 与上面的样例输入对应的 ...

  3. Java实现 蓝桥杯VIP 算法训练 奇偶判断

    问题描述 能被2整除的数称为偶数,不能被2整除的数称为奇数.给一个整数x,判断x是奇数还是偶数. 输入格式 输入包括一个整数x,0<=x<=100000000. 输出格式 如果x是奇数,则 ...

  4. Java实现蓝桥杯VIP 算法训练 P0502

    试题 算法训练 P0502 资源限制 时间限制:1.0s 内存限制:256.0MB 编写一个程序,读入一组整数,这组整数是按照从小到大的顺序排列的,它们的个数N也是由用户输入的,最多不会超过20.然后 ...

  5. java中Condition类的详细介绍(详解)

    已找不到原文了,还望原文博主看到能告诉小白一下,一定标注原文地址 一 condition 介绍及demo Condition是在java 1.5中才出现的,它用来替代传统的Object的wait(). ...

  6. Java实现 洛谷 P1280 尼克的任务

    import java.util.Scanner; public class Main { public static class edg{ private int to; private int n ...

  7. 解读三组容易混淆的Dockerfile指令

    长话短说,今天分享三组容易混淆的Dockerfile指令, 帮助大家编写更优雅的Dockfile文件.构建更纯净的Docker镜像. COPY vs ADD COPY.ADD主体功能类似:从指定位置拷 ...

  8. Spring AOP学习笔记02:如何开启AOP

    上文简要总结了一些AOP的基本概念,并在此基础上叙述了Spring AOP的基本原理,并且辅以一个简单例子帮助理解.从本文开始,我们要开始深入到源码层面来一探Spring AOP魔法的原理了. 要使用 ...

  9. Spring系列.依赖注入配置

    依赖注入的配置 Spring的依赖注入分为基于构造函数的依赖注入和基于setter方法的依赖注入. 基于构造函数的依赖注入 <!-- 通过构造器参数索引方式依赖注入 --> <bea ...

  10. 对于Python的GIL锁理解

    GIL是什么 首先需要明确的一点是GIL并不是Python的特性,它是在实现Python解析器(CPython)时所引入的一个概念.就好比C++是一套语言(语法)标准,但是可以用不同的编译器来编译成可 ...