4

Java 虚拟机原理 (一) 内存划分

 3 years ago
source link: https://blog.duval.top/2021/01/07/Java-%E8%99%9A%E6%8B%9F%E6%9C%BA%E5%8E%9F%E7%90%86-1-%E5%86%85%E5%AD%98%E5%88%92%E5%88%86/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Java 虚拟机技术是每个 Java 开发工程师都应该深入掌握的。本系列文章将深入介绍 JVM 相关技术,主要包括内存划分、对象创建回收与分配以及垃圾收集三大部分。本系列文章将力求全面概要地汇总核心知识点,并使知识点串联成面,以方便学习、工作以及备忘复习。本文将介绍第一部分:内存划分。

JDK 体系架构

先从宏观上来看 JVM 所处的位置,且看官方文档的体系架构图

JDK体系架构图.png

JDK体系架构图.png

  • JVM(Java Virtual Machine):处于整个体系最底层,直接与不同的操作系统打交道,因此针对不同的系统有相应的 JVM 实现。Java 程序正是借助 JVM 实现了“一处编写处处运行“的跨平台能力;
  • JRE(Java SE Runtime Environment):Java 运行时环境,是在 JVM 基础上增加 Java 基础类库。Java 程序可以运行在 JRE 之上;
  • JDK(Java SE Development Kit):Java 开发工具包,是在 JRE 基础上增加了开发 Java 程序所需要的各种工具包。

因此本系列文章主要探讨最底层的 JVM 底层原理。

JVM 内存模型

JVM 内存模型图.jpg

JVM 内存模型图.jpg

上图展示的是以下样例代码的内存模型:

public class App {

    private int plus() {
        int a = 1;
        int b = 1;
        int c = a + b;
        return c;
    }

    public static void main(String[] args) {
        App obj = new App();
        System.out.println(obj.plus());
    }
}

JVM 运行时数据区域包括以下五部分:

  • 程序计数器:每个线程都会有独立的程序计数器,用于记录当前程序运行到的位置,以便线程切换时能够恢复到当前运行位置;
  • Java 虚拟机栈:即是图中线程内部的 Java 线程栈。每个线程也都拥有自己的线程栈。线程栈遵循先进后出(FILO)原则,内部包含多个栈帧。每一个栈帧由局部变量表、操作数栈、动态链接以及方法出口等构成;
  • 本地方法栈:与虚拟机栈类似,但保存的是 native 方法调用栈;
  • 堆:运行时数据区域中最大的一部分,是大部分对象保存的地方。JVM 常常使用分代收集算法回收该区域;
  • 方法区:JDK8 里变更为元空间(metaspace),直接保存在直接内存中(注意直接内存不属于 JVM 运行时数据区域)。方法区主要保存类信息、运行时常量池、静态变量、即时编译器编译后的代码等数据。

此外,直接内存也是非常重要一部分内存空间。 JVM 元数据空间以及 Java NIO 等都是用到直接内存。

JVM 参数

JVM 提供了若干参数来控制上述各个区域的大小,如下图所示:

JVM 内存模型与调优参数.jpg

JVM 内存模型与调优参数.jpg

配置样例如:

java -Xmx6g -Xms6g -Xmn3g -Xss512K -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:SurvivorRatio=8 -XX:MetaspaceSize=64m ‐XX:MaxMetaspaceSize=128M -jar myapp.jar

需要注意,元数据空间在缺省参数的情况下,默认初始大小为21M,如果发生空间不足,会触发 Full GC 进行扩容,且最大扩容空间可为所有的机器内存。所以一定要配置元数据空间参数,且 MetaspaceSize 和 MaxMetaspaceSize 最好相等,从而从根源上杜绝 Full GC 扩容。

  • JVM内存模型:该文将 Java 内存模型介绍得非常具体详细。

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK