极客视点
极客时间编辑部
极客时间编辑部
113241 人已学习
免费领取
课程目录
已完结/共 3766 讲
2020年09月 (90讲)
时长 05:33
2020年08月 (93讲)
2020年07月 (93讲)
时长 05:51
2020年06月 (90讲)
2020年05月 (93讲)
2020年04月 (90讲)
2020年03月 (92讲)
时长 04:14
2020年02月 (87讲)
2020年01月 (91讲)
时长 00:00
2019年12月 (93讲)
2019年11月 (89讲)
2019年10月 (92讲)
2019年09月 (90讲)
时长 00:00
2019年08月 (91讲)
2019年07月 (92讲)
时长 03:45
2019年06月 (90讲)
2019年05月 (99讲)
2019年04月 (114讲)
2019年03月 (122讲)
2019年02月 (102讲)
2019年01月 (104讲)
2018年12月 (98讲)
2018年11月 (105讲)
时长 01:23
2018年10月 (123讲)
时长 02:06
2018年09月 (119讲)
2018年08月 (123讲)
2018年07月 (124讲)
2018年06月 (119讲)
时长 02:11
2018年05月 (124讲)
时长 03:16
2018年04月 (120讲)
2018年03月 (124讲)
2018年02月 (112讲)
2018年01月 (124讲)
时长 02:30
时长 02:34
2017年12月 (124讲)
时长 03:09
2017年11月 (120讲)
2017年10月 (86讲)
时长 03:18
时长 03:31
时长 04:25
极客视点
15
15
1.0x
00:00/05:51
登录|注册

一文讲清JVM内存结构

讲述:丁婵大小:8.04M时长:05:51
JVM 一直都是程序员面试的必考点,但是要把它搞清楚又好像不是特别容易。JVM 的知识点太散,不系统,所以不便于归纳总结。近日,公众号“Java 大联盟”的作者楠哥梳理了 JVM 的结构,希望给技术同学带来参考。
JVM 可以分为 5 个部分,分别是:
类加载器(Class Loader):加载字节码文件到内存。
运行时数据区(Runtime Data Area):JVM 核心内存空间结构模型。
执行引擎(Execution Engine):对 JVM 指令进行解析,翻译成机器码,解析完成后提交到操作系统中。
本地库接口(Native Interface):供 Java 调用的融合了不同开发语言的原生库。
本地方法库(Native Libraies):Java 本地方法的具体实现。
JVM 的结构如下图所示:
这其中最复杂的是运行时数据区,它也是 JVM 内存结构最重要的部分。运行时数据区又可以分为方法区、虚拟机栈、本地方法栈、堆以及程序计数器,并且方法区和堆是线程共享的,虚拟机栈、本地方法栈、程序计数器是线程隔离的。下面详细讲解运行时数据区的各个组成部分。

1. 方法区

方法区存储虚拟机加载的类信息、常量、静态变量以及即时编译器编译后的代码等数据。方法区是一种规范,它的其中一种实现是永久代。JDK 7 以前的版本字符串常量池是放在永久代中的,JDK 7 将字符串常量池移动到了堆中,JDK 8 直接删除了永久代,改用元空间替代永久代。

2. 本地方法栈

本地方法栈与 Java 栈的作用和原理基本相同,都可以用来执行方法,不同点在于 Java 栈执行的是 Java 方法,本地方法栈执行的是本地方法。
什么是 Java 的本地方法呢?Java 是基于应用层的高级编程语言,无法访问操作系统底层信息,如底层硬件设备等,这个时候就需要使用其他语言来完成其欠缺的功能了,比如 C 语言。本地方法的使用原理如下所示:
在 Java 程序中声明 native 修饰的方法,只有方法定义,没有方法实现,将该 Java 文件编译成字节码文件。
用 javah 编译字节码文件,生成一个 .h 文件。
写一个 .cpp 文件实现 .h 文件中的方法。
将 .cpp 文件编译成动态链接库文件 .dll 。
使用 System.loadLibrary() 加载动态连接库文件。
这样就可以实现本地方法的调用,用 Java 调用而非 Java 编写的接口,基本原理是利用反射机制,在运行时找到 .dll 文件并且解析,根据动态链接库中的文件名称创建出对象和方法,然后就可以利用对象调用方法了。

3. 程序计数器

程序计数器占用的内存空间较小,是当前线程所执行的字节码行号指示器,通过改变这个计数器的值来选取下一条需要执行的字节码指令。多个线程之间的程序计数器相互独立,为了保证每个线程恢复后都可以找到具体的执行位置。

4.Java 堆

Java 堆用来存放实例化对象,它被所有线程共享,在虚拟机启动时创建,用来存放对象实例,其占用了 Java 内存的大部分空间,是 GC 的主要管理区域,又可分为年轻代、老年代、永久代。
年轻代又可分为 Eden,from Survivor,to Survivor。Eden 区用来存放刚刚创建的对象,如果 Eden 区放不下,则放在 Survivor 区,甚至老年代中。Survivor 区又可分为 Survivor From 和 Survivor To,GC 回收时使用,将 Eden 中存活的对象存入 Survior From 中,下一次回收时,将 Survior From 中的对象存入 Survior To 中,清除 Survior From ,下一次回收时重复此步骤,Survior From 变成 Survior To,Survivor To 变成 Survivor From,依次循环,同时每次回收,对象的年龄都 +1,年龄增加到一定程度的对象,移动到老年代中。
老年代是存放生命周期较长的对象,而永久代在 JDK 8 之后已经被元空间替代。元空间使用本地内存,永久代使用 JVM 内存,所以使用元空间的好处在于程序的内存不再受限于 JVM 内存,本地内存剩余多少空间,元空间就可以有多大,解决了空间不足的问题。

5. 虚拟机栈

Java 栈中存放的是多个栈帧,每个栈帧对应一个被调用的方法,主要包括局部变量表、操作数栈、动态链接、方法返回地址(方法出口)。每一个方法的执行,JVM 都会创建一个栈帧,并且将栈帧压入 Java 栈,方法执行完毕,该栈帧出栈。也就是说,每个方法的执行都是一个栈帧的入栈和出栈过程,Java 虚拟机栈用来存储栈帧,方法调用结束之后,帧会被销毁。
以上就是 JVM 的内存结构,你都学会了吗?
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结
该免费文章来自《极客视点》,如需阅读全部文章,
请先领取课程
免费领取
登录 后留言

全部留言(2)

  • 最新
  • 精选
  • gmthal
    很棒,网上搜一大堆垃圾文章,啥也说不清楚
  • zero
    很实用
收起评论
大纲
固定大纲
1. 方法区
2. 本地方法栈
3. 程序计数器
4.Java 堆
5. 虚拟机栈
显示
设置
留言
2
收藏
99+
沉浸
阅读
分享
手机端
快捷键
回顶部