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

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

JVM内存模型和Java内存模型都是面试的热点问题,名字看感觉都差不多,实际上他们之间差别还是挺大的。

通俗点说,JVM内存结构是与JVM的内部存储结构相关,而Java内存模型是与多线程编程相关@mikechen

什么是JVM

JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一个虚构出来的计算机,有着自己完善的硬件架构,如处理器、堆栈等。

为什么需要JVM?

Java语言使用Java虚拟机屏蔽了与具体平台相关的信息,使得Java语言编译程序只需生成在Java虚拟机上运行的目标代码( 字节码),就可以在多种平台上不加修改地运行。

Java文件必须先通过一个叫javac的编译器,将代码编译成class文件,然后通过JVM把class文件解释成各个平台可以识别的机器码,最终实现跨平台运行代码。

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

JVM内存模型

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

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

在JVM1.8中,图中的 方法区为元数据区,下面展开谈一谈这五个区域的作用。

堆(Heap)

在 Java 中,堆被划分成两个不同的区域:新生代 ( Young )、老年代 ( Old ),新生代 ( Young ) 又被划分为三个区域:Eden、From Survivor、To Survivor。

下图中的Perm代表的是永久代,但是注意永久代并不属于堆内存中的一部分,同时jdk1.8之后永久代也将被移除。

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

堆是java虚拟机所管理的内存中最大的一块内存区域,也是被各个线程共享的内存区域,该内存区域存放了对象实例及数组(但不是所有的对象实例都在堆中)。

其大小通过-Xms(最小值)和-Xmx(最大值)参数设置(最大最小值都要小于1G),前者为启动时申请的最小内存,默认为操作系统物理内存的1/64,后者为JVM可申请的最大内存,默认为物理内存的1/4,默认当空余堆内存小于40%时,JVM会增大堆内存到-Xmx指定的大小,可通过-XX:MinHeapFreeRation=来指定这个比列。

当空余堆内存大于70%时,JVM会减小堆内存的大小到-Xms指定的大小,可通过XX:MaxHeapFreeRation=来指定这个比列,当然为了避免在运行时频繁调整Heap的大小,通常-Xms与-Xmx的值设成一样。堆内存 = 新生代+老生代+持久代。

在我们垃圾回收的时候,我们往往将堆内存分成新生代和老生代(大小比例1:2),新生代中由Eden和Survivor0,Survivor1组成,三者的比例是8:1:1,新生代的回收机制采用复制算法,在Minor GC的时候,我们都留一个存活区用来存放存活的对象,真正进行的区域是Eden+其中一个存活区,当我们的对象时长超过一定年龄时(默认15,可以通过参数设置),将会把对象放入老生代,当然大的对象会直接进入老生代,老生代采用的回收算法是标记整理算法。

方法区(Method Area)

其实方法区是在JDK1.8以前的版本里存在的一块内存区域,主要就是存放从class文件里加载进来的类的,而且常量池也是在这块区域内的。

但是在JDK1.8之后,这块区域摇身一变,换了名字,叫做”Metaspace”,翻译过来就是”元数据空间”的意思,当然它只是改了个名,实现的功能是没变的。

方法区(Method Area)与Java堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据。

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

1.类型信息

对每个加载的类型(类class、接口interface、枚举enum、注解annotation),JVM必须在方法区中存储以下类型信息:
①这个类型的完整有效名称(全名=包名.类名)
②这个类型直接父类的完整有效名(对于interface或是java.lang.0bject,都没有父类)
③这个类型的修饰符(public, abstract,final的某个子集)
④这个类型直接接口的一个有序列表

2.域信息(Field)成员变量

JVM必须在方法区中保存类型的所有域的相关信息以及域的声明顺序。
域的相关信息包括:域名称、域类型、域修饰符(public, private,protected,static,final, volatile, transient的某个子集)

3.方法(Method)信息

JVM必须保存所有方法的以下信息,同域信息一样包括声明顺序:

  • 方法名称
  • 方法的返回类型(或void)·方法参数的数量和类型(按顺序)
  • 方法的修饰符(public, private,protected,static, final,synchronized,native,abstract的一个子集)
  • 方法的字节码(bytecodes)、操作数栈、局部变量表及大小(abstract和native方法除外)

虚拟机栈(JVM Stack)

虚拟机栈(Java Virtual Machine Stack),早期也叫Java栈,每个线程在创建时都会创建一个虚拟机栈,其内部保存一个个的栈帧(Stack Frame),对应着一次次的Java方法调用。

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

每个方法被执行的时候都会创建一个”栈帧”,用于存储局部变量表(包括参数)、操作栈、方法出口等信息。

每个方法被调用到执行完的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。

栈帧(Stack Frame) 是用于虚拟机执行时方法调用和方法执行时的数据结构,它是虚拟栈的基本元素,栈帧由局部变量区、操作数栈等组成,如下图所示:

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

每一个方法从调用到方法返回都对应着一个栈帧入栈出栈的过程。最顶部的栈帧称为当前栈帧,栈帧所关联的方法称为当前方法,定义这个方法的类称为当前类,该线程中,虚拟机有且也只会对当前栈帧进行操作。

栈帧的作用有存储数据,部分过程结果,处理动态链接,方法返回值和异常分派。

每一个栈帧包含的内容有局部变量表、操作数栈、动态链接、方法返回地址和一些额外的附加信息。在编译代码时,栈帧需要多大的局部变量表,多深的操作数栈都可以完全确定的,并写入到方法表的code属性中。

本地方法栈(Native Stack)

本地方法栈(Native Method Stacks)与虚拟机栈所发挥的作用是非常相似的,其区别不过是虚拟机栈为虚拟机执行Java 方法(也就是字节码)服务,而本地方法栈则是为虚拟机使用到的Native 方法服务。

虚拟机规范中对本地方法栈中的方法使用的语言、使用方式与数据结构并没有强制规定,因此具体的虚拟机可以自由实现它。

甚至有的虚拟机(譬如Sun HotSpot 虚拟机)直接就把本地方法栈和虚拟机栈合二为一。

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

程序计数器(PC Register)

在JVM的概念模型里,字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令。

分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。

JVM的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的,为了各条线程之间的切换后计数器能恢复到正确的执行位置,所以每条线程都会有一个独立的程序计数器。

当线程正在执行一个Java方法,程序计数器记录的是正在执行的JVM字节码指令的地址;如果正在执行的是一个Natvie(本地方法),那么这个计数器的值则为空(Underfined)。

程序计数器占用的内存空间很少,也是唯一一个在JVM规范中没有规定任何OutOfMemoryError(内存不足错误)的区域。

JVM内存模型小结

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

这些地方也是我们平时开发中最常接触到的地方,所以对其有所掌握了解还是很有必要的,也有助于JVM问题排查。

作者简介

mikechen

,10年+大厂架构经验,《BAT架构技术500期》系列文章作者,曾就职于阿里、淘宝、百度等一线互联网大厂。

阅读mikechen的互联网架构更多技术文章合集
Java并发 |JVM |MySQL |Spring |Redis |分布式 |高并发 |架构师

Original: https://www.cnblogs.com/mikechenshare/p/16562589.html
Author: mikechen的互联网架构
Title: JVM内存模型和结构详解(五大模型图解)

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/616057/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 【java线程】新版基于生产者队列消费者的表迁移器

    前作: 【代码下载地址】 【主要改进点】 1.原来的DataQueue是手写的,实际上使用java提供的java.util.concurrent.BlockingQueue就完全够…

    Java 2023年5月29日
    093
  • Java中使用feign遇到的坑

    1.解析接口返回的数据时,失败了。 feign.codec.DecodeException: Could not extract response: no suitable Htt…

    Java 2023年5月29日
    095
  • BP神经网络– C语言实现 上

    在上一篇文章中,介绍了BP神经网络的基本模型、模型中的一些术语并对模型进行了数学上的分析,对它的原理有了初步的认识。那么如何用程序语言来具体的实现它,将是我们下一步需要讨论的问题。…

    Java 2023年6月15日
    0107
  • FLASH CS4 制作渐变 动画 有补间动画 传统补间

    下了个FLASH CS4 ,也许太久没玩FLASH了,很多东西都物是人非了,要弄个动画渐变一直不成功。 点来点去,发现有个”添加传统补间”,试一下,可以进行…

    Java 2023年6月13日
    070
  • [nginx] async_mode_nginx CPU 100% deadlock问题分析

    很遗憾只定位到了一个比较小的问题范围,理清了root cause, 但是没有找到复现的边界条件以及solution. Hi all, I have the quite same p…

    Java 2023年5月30日
    086
  • 面向对象设计与构造2022第四单元总结

    一、总结本单元作业的架构设计 ​ 这里展示一下第三次作业的类图,相当于整个单元的架构设计。 ​ 首先,通过第四单元手册的学习,我们可以得知UML类图、顺序图和状态图每一种图它的元素…

    Java 2023年6月10日
    082
  • java释放资源、try()用法

    不用写一大堆finally来关闭资源,所有实现Closeable的类声明都可以写在里面,最常见于流操作,socket操作,新版的httpclient也可以;需要注意的是,try()…

    Java 2023年5月29日
    068
  • asp.net实现视频在线播放

    利用ASP.net实现在线音频、视频播放功能ASP.net实现音乐,视频播放功能的实例:今天主要介绍的是借助于微软提供的Media Player插件来实现该插件默认是没有添在加工具…

    Java 2023年5月29日
    071
  • 在 IDEA 里下个五子棋不过分吧?

    大家好,我是二哥呀!今天给大家分享一个基于Netty的IDEA即时聊天插件,可以实现即时聊天、游戏对战(下棋)。 GitHub 地址:https://github.com/anli…

    Java 2023年6月9日
    085
  • 【java基础】枚举

    public enum Color { Red,Blue,Green; } Color red = Color.Red;//枚举&amp…

    Java 2023年6月9日
    0118
  • RabbitMQ访问Web端口报错User can only log in via localhost

    RabbitMQ访问Web端口报错User can only log in via localhost 一、错误信息 在项目开发过程中,通过浏览器访问Web端口时报错 User c…

    Java 2023年6月8日
    0118
  • Spring实例化bean之后的处理, 关于BeanPostProcessor接口的使用

    业务需求:缓存页面,展示需要缓存的所有对象,每类对象在字典表中有编码对应,点击某个对象可以缓存某类对象,每类对象都有自己的缓存runner(弱弱的说一句,本人看到这里的第一反应就是…

    Java 2023年6月8日
    074
  • md-resume-demo

    小明 概况: 6年工作经验 | 男 | 26岁(1990年5月16日)…

    Java 2023年6月5日
    0342
  • http服务端架构演进

    摘要 在 详解http报文相关文章中我们介绍了http协议是如何工作的,那么构建一个真实的网…

    Java 2023年6月8日
    0102
  • java学习之爬虫

    对比与Python的爬虫机制和java的爬虫机制来详解一下java的爬虫,对于一般性的需求无论java还是python都可以胜任。如需要模拟登陆、对抗防采集选择python更方便些…

    Java 2023年6月13日
    0103
  • spring cloud(二)简单快速的实现负载均衡的功能

    上篇参考:Spring Cloud快速使用教程(一) 在快速搭建Spring Cloud我们如果要简单快速的使用负载均衡可以如下实现 以下是实现示例: 使用Spring Cloud…

    Java 2023年5月30日
    081
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球