前言
JVM 系列:
JVM 学习笔记 - 带你掌握 JVM 类加载机制
本 JVM 系列属于本人学习过程当中总结的一些知识点, 目的是想让读者更快地掌握 JVM 相关的知识要点, 难免会有所侧重, 若想要更加系统更加详细的学习 JVM 知识, 还是需要去阅读专业的书籍和文档.
本文主题内容:
JVM 内存区域概览
堆区的空间分配是怎么样? 堆溢出的演示
创建一个新对象内存是怎么分配的?
方法区 到 Metaspace 元空间
栈帧是什么? 栈帧里有什么? 怎么理解?
本地方法栈
程序计数器
Code Cache 是什么?
注: 请 区分 JVM 内存结构 (内存布局) 和 JMM(Java 内存模型) 这两个不同的概念!
概览
内存是非常重要的系统资源, 是硬盘和 CPU 的中间仓库及桥梁, 承载着操作系统和应用程序的实时运行. JVM 内存布局规定了 Java 在运行过程中内存申请, 分配, 管理的策略 , 保证了 JVM 的高效稳定运行.
上图描述了当前比较经典的 JVM 内存布局.(堆区画小了 2333, 按理来说应该是最大的区域)
如果按照线程是否共享来分类的话, 如下图所示:
PS: 线程是否共享这点, 实际上理解了每块区域的实际用处之后, 就很自然而然的就记住了. 不需要死记硬背.
下面让我们来了解下各个区域.
一, Heap (堆区)
1.1 堆区的介绍
我们先来说堆. 堆是 OOM 故障最主要的发生区域. 它是内存区域中最大的一块区域, 被所有线程共享, 存储着几乎所有的实例对象, 数组. 所有的对象实例以及数组都要在堆上分配, 但是随着 JIT 编译器的发展与逃逸分析技术逐渐成熟, 栈上分配, 标量替换优化技术将会导致一些微妙的变化发生, 所有的对象都分配在堆上也渐渐变得不是那么 "绝对" 了.
延伸知识点: JIT 编译优化中的一部分内容 - 逃逸分析.
- >java -XX:+PrintFlagsFinal -version
- [Global flags]
- ...
- uintx InitialSurvivorRatio = 8
- uintx NewRatio = 2
- ...
- java version "1.8.0_131"
- Java(TM) SE Runtime Environment (build 1.8.0_131-b11)
- Java HotSpot(TM) 64-Bit Server VM (build 25.131-b11, mixed mode)
- /**
- * VM Args:-Xms10m -Xmx10m -XX:+HeapDumpOnOutOfMemoryError
- * @author Richard_Yi
- */
- public class HeapOOMTest {
- public static final int _1MB = 1024 * 1024;
- public static void main(String[] args) {
- List<byte[]> byteList = new ArrayList<>(10);
- for (int i = 0; i <10; i++) {
- byte[] bytes = new byte[2 * _1MB];
- byteList.add(bytes);
- }
- }
- }
- java.lang.OutOfMemoryError: Java heap space
- Dumping heap to java_pid32372.hprof ...
- Heap dump file created [7774077 bytes in 0.009 secs]
- Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
- at jvm.HeapOOMTest.main(HeapOOMTest.java:18)
- Metaspace in Java 8
- http://lovestblog.cn/blog/2016/10/29/metaspace/
- public int test(int a, int b) {
- Object obj = new Object();
- return a + b;
- }
- /**
- * @author Richard_yyf
- */
- public class OperandStackTest {
- public int sum(int a, int b) {
- return a + b;
- }
- }
- > javap -v OperandStackTest.class> 1.txt
- public int sum(int, int);
- descriptor: (II)I
- flags: ACC_PUBLIC
- Code:
- stack=2, locals=3, args_size=3 // 最大栈深度为 2 局部变量个数为 3
- 0: iload_1 // 局部变量 1 压栈
- 1: iload_2 // 局部变量 2 压栈
- 2: iadd // 栈顶两个元素相加, 计算结果压栈
- 3: ireturn
- LineNumberTable:
- line 10: 0
来源: https://segmentfault.com/a/1190000021424972