Code前端首页关于Code前端联系我们

JVM内存模型和Java结构详解(五张主要模型图)

terry 2年前 (2023-09-24) 阅读数 51 #后端开发

JVM 内存模型和Java结构详解 (五大模型图解)

JVM内存模型和Java内存模型都是面试的热门话题。名字虽然相似,但实际上却有很大的区别。

通俗地说,JVM内存结构与JVM内部存储结构有关,而Java内存模型与@mikechen多线程编程有关。

什么是 JVM

JVM 是 Java 虚拟机的缩写。 JVM是用其完整的硬件系统(如处理器、堆栈等)创建的计算机。

为什么需要 JVM?

Java语言使用Java虚拟机来保护特定领域的信息,因此Java编译器只需要创建在机器上运行的目标代码(字节码)虚拟Java,并且可以运行在许多平台上无需修改。

Java文件首先要经过一个叫javac的编译器运行,将代码编译成class文件,然后使用JVM将class文件翻译成各个平台都能接受的机器码,最终会达到跨平台跑步。代码。

JVM 内存模型和Java结构详解 (五大模型图解)

JVM内存模型

JVM内存模型可以分为两部分,如下图所示。栈区和方法是所有线程共有的,而虚拟机栈、本地方法栈和程序计数器是线程无关的。

JVM 内存模型和Java结构详解 (五大模型图解)

在JVM1.8中,镜像的方法区就是元数据区。下面我们就来说一下这五个区域的作用。

在Java中,堆分为两个不同的类别:Young和Old,而Young又分为三个类别:Eden、From Survivor、To Survivor。下图中的

Perm代表持久代,但是注意持久代并不在堆内存中,jdk1.8之后持久代也会被移除。

JVM 内存模型和Java结构详解 (五大模型图解)

堆是Java虚拟机管理的最大的内存区域。也是不同线程共享的内存区域。该内存区域存储实例和数组(并非所有实例都在堆上)。

大小设置为-,后者是JVM能够实现的最大内存,默认为物理内存的1/4。默认情况下,当空闲堆内存小于40%时,JVM会将堆内存增加到-Xmx指定的大小,可以通过-XX:MinHeapFreeRation=来指定这个比例。

当空闲堆内存超过70%时,JVM会按照-指定的大小减少堆内存大小,通常-Xms和-Xmx设置为相同的值。平均内存=年轻代+老年代+长期代。

我们在进行垃圾回收时,通常会将堆内存划分为新生代和老年代(大小1:2)。新一代由Eden、Survivor0和Survivor1组成。三者的比例为8:1:1,新一代处理机制采用重复算法。在 Minor GC 期间,我们都会离开生活区以保存仍然活着的东西。真正的区域是伊甸园+生活区之一。当我们的对象年龄超过一年时(默认值为15(可以通过参数设置),就会将该对象设置到老年代。当然,主对象会直接进入老年代。使用的处理算法在旧的生成中是标记和排序的算法,池也在这个区域中。

但是JDK1.8之后改名了这个区域被称为“Metaspace”,意思是“元数据空间”当然,它只是名字变了,功能没变。

方法区和Java堆一样,是每个线程共享的内存区域,运行时编译器用来存储类型等数据虚拟机隐藏的信息、常量、静态变量和编译代码缓存。

JVM 内存模型和Java结构详解 (五大模型图解)

1。输入信息

对于每种对象类型(类、接口、枚举、注解),JVM 必须在方法区中存储以下类型信息:
① 这是一个有效的类型名称(全名=包名) .classname)
② 该类型的直接父类的完全有效名称(对于接口或 java.lang.0object,无父类)
③ 该类型的修饰符(public、abstract、final 的一部分) )

由此类直接接口定义的列表

2.字段信息(Field)成员变量

JVM必须存储该类型的所有字段与字段相关的信息以及字段声明的顺序。
域名相关信息包括:域名、域名类型、域名修改(公共部分、私有、受保护、静态、最终、变量、瞬态)

3。方法信息

JVM 必须存储所有方法的以下信息,包括范围信息等声明命令:

  • 方法名称
  • 方法返回类型(或无)・方法参数的数量和类型(在order)
  • 方法表示法的修改(public、private、protected、static、final、synchronized、native、abstract的部分)
  • 方法字节码(bytecode)、操作数栈、局部变量表和大小(abstract和abstract除外) Native方法)

虚拟机堆栈(JVM Stack)

虚拟机堆栈(Java虚拟机堆栈),早期也称为Java堆栈。每个线程在创建时都会创建一个虚拟机栈,内部会保存每个栈结构。 (Stack Frame),对应每个Java方法的调用。

虚拟机的作用:监控Java程序的执行。它保存局部变量和方法的部分结果,并参与调用和返回方法。

每个方法执行完毕后,会创建一个“栈帧”,用于存储局部变量表(包括参数)、栈、退出方法等信息。

每个方法从调用到执行完成的步骤对应于上图中虚拟机栈中从入栈到出栈的步骤。

堆栈帧(Stack Frame)是虚拟机执行过程中用来调用和执行方法的数据结构。它是虚拟化堆栈的主要组件。栈结构由局部变量区、操作数栈等组成,如下图所示。显示:

JVM 内存模型和Java结构详解 (五大模型图解)

每个方法都对应着从调用到返回的压入栈映像的过程。最顶层的栈帧称为当前栈帧,与该栈帧关联的方法称为当前方法,定义该方法的类称为当前类。在这个线程中,虚拟机已经并且只工作在当前的堆栈系统上。

帧栈的功能包括数据存储、部分进程响应、动态链接管理、方法返回值、特殊调度等。

包含局部变量表、操作数栈、动态链接、方法返回地址和其他附加信息。编译代码时,可以完全确定局部变量表的大小和栈帧所需的栈操作数的深度,并写入方法表的代码属性中。

本机堆栈

本机方法堆栈和虚拟机的工作方式相同。唯一的区别是,虚拟机栈实现了虚拟服务的Java方法(即Bytecode),而本地方法栈则服务于虚拟机使用的Native方法。

虚拟机规范没有规定本地存储方法的语言、用法和数据结构,因此各个虚拟机可以自由实现。

有些虚拟机(如Sun HotSpot虚拟机)直接将本地方法栈和虚拟机栈合二为一。

和虚拟机栈一样,本地方法栈区也会抛出StackOverflowError和OutOfMemoryError异常。

程序计数器(PC寄存器)

在JVM运行时模型中,字节码解释器通过更改此代码的值来选择下一条要执行的字节码指令。

所有基本操作,如分支、换行、跳转、特殊处理和线程检索都依赖于该计数器。

JVM的多线程是通过逐个切换线程并分配处理器的执行时间来实现的。为了在线程之间切换后将计数器重置到正确的执行位置,每个线程将有一个独立的程序计数器。

当线程执行Java方法时,程序计数器获取正在执行的JVM字节码指令的地址;如果执行 Natvie(本机方法),则该计数器的值为 null (Underfined)。

程序计数器的内存空间非常小,并且是JVM描述符唯一没有OutOfMemoryError(无内存错误)的区域。

JVM内存模型概述

本文介绍了JVM虚拟机中操作数据区的五个内存区域:堆、方法区、虚拟机栈、本地方法栈、程序计数器。

这些也是我们日常开发中交互最频繁的地方,所以了解它们很重要,同时也有助于解决JVM问题。

及以上!

关于作者

mikechen,10年以上大型企业架构经验,《BAT 架构技术 500 期》系列作者,曾就职于阿里巴巴、淘宝、百度等领先互联网公司。

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门