用几张图深度剖析Java内存模型

简介: 首先看一张图:下图是Java虚拟机运行时数据区,JVM的内存模型可以分为方法区、虚拟机栈、本地方法栈、堆和程序计数器。

网络异常,图片无法展示
|


听说微信搜索《Java鱼仔》会变更强哦!


本文收录于githubgitee ,里面有我完整的Java系列文章,学习或面试都可以看看哦


(一)基础概念介绍


首先看一张图:下图是Java虚拟机运行时数据区,JVM的内存模型可以分为方法区、虚拟机栈、本地方法栈、堆和程序计数器。


网络异常,图片无法展示
|


首先还是介绍一下基本概念


程序计数器


程序计数器的作用可以看成是当前线程所执行的字节码的行号指示器。字节码解释器工作时就是通过改变计数器的值来选择下一条需要执行的字节码的指令。java虚拟机的多线程是通过线程轮流切换来分配处理器执行时间的方式实现的,为了线程切换之后能恢复到正确的执行位置,每个线程就需要一个独立的程序计数器。


java虚拟机栈: java虚拟机栈线程私有,每个方法被执行的同时都会创建一个栈帧用于存放局部变量表、操作数栈、动态链接、方法出口等信息。


本地方法栈: 本地方法栈的功能和虚拟机栈类似,本地方法栈为虚拟机用到的Native方法服务,一个Native Method就是一个java调用非java代码的接口,本地方法栈也会抛出StackOverFlow和OutOfMemoryError异常


java堆java堆可以说是java虚拟机中所管理的内存最大的一块,java堆被所有线程共享,虚拟机启动的时候创建。java堆中存放的对象实例的数组。几乎所有的对象实例以及数组都在堆上分配,java堆也是垃圾回收器管理的主要区域,java堆可以处于物理上不连续的内存空间中,只要逻辑上是连续的即可,这和磁盘空间很相似。当一个堆无法再扩展时,会抛出OutOfMemoryError异常。


方法区: 方法区也是线程共享的内存区域,用于存放已经被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据,java虚拟机对方法区的限制十分宽松,和java堆一样不需要连续的内存外,还可以选择不实现垃圾回收。


(二)Java虚拟机栈与程序计数器


虚拟机栈中保存的主要内容是栈帧,每次方法调用就会使得一个栈帧被压入到虚拟机栈。比如上一篇文章讲JVM字节码的时候,我们用到了这样一段代码:


publicclassMain {
publicstaticintcalculate(){
inta=1;
intb=2;
intc=(a+b)*10;
returnc;
    }
publicstaticvoidmain(String[] args) {
System.out.println(calculate());
    }
}

在JVM虚拟机栈中,结构就是这样的:

网络异常,图片无法展示
|


局部变量表存放了编译器可知的八个基本数据类型、对象引用、和returnAddress类型(指向了一条字节码指令的地址)。


操作数栈主要用来进行一系列出入栈的数值操作。


有关局部变量表、操作数栈、程序计数器更加详细的应用可以看我的前一篇文章:两张图让你快速读懂JVM字节码指令


动态链接:动态链接是值在程序运行期间将符号引用转换为直接引用。在一段代码中,类名、常量名、修饰符、对象名等都是符号引用,而如何通过符号找到具体的引用就需要动态链接做一层转换,将符号引用转换为直接引用。比如:JVM就能通过对象名就链接到堆中真实的对象。


动态链接的工作内容和类加载过程中解析这一步是一样的,只不过解析是将一些静态方法或变量(比如main()方法、static变量)替换为指向数据所存内存的直接引用。


方法出口:当一个方法执行之后,返回的方式可能是正常执行结束返回,也可能是抛出异常的返回。无论采用哪种方式,在方法退出之后都需要回到方法调用的位置,因此这些信息就会被保存到方法出口中。


JVM模式每个线程的虚拟机栈大小是1M,也可以通过-Xss调整虚拟机栈的大小。


(三)方法区


方法区是线程共享的内存区域,用于存放已经被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。关于方法区的概念,很多人其实都是浑的。方法区、永久代、元空间之间的区别大家都知道吗?


其实方法区是JVM规范中的一个概念,在不同的Java虚拟机以及不同版本的Java虚拟机中,方法区都有各自的实现。以最流行的HotSpot 虚拟机为例,在JDK1.8之前,方法区的实现叫做永久代,放在JVM内存之中。到了JDK1.8,方法区的实现变成了元空间,放在直接内存中。


(四)本地方法栈


本地方法栈的作用是在Java中调用非Java代码,他的功能和虚拟机栈类似。本地方法栈的存在应该算是历史遗留问题,Java刚出来的时候C、C++是当时绝对的统治者,因此在Java中免不了会去调用这一类代码,也因此需要本地方法栈。


(五)堆


堆是JVM虚拟机中最核心的部分了,绝大部分的垃圾回收都在堆中完成。


网络异常,图片无法展示
|


JVM堆分为新生代和老年代,默认比例为1:2,其中新生代又分为Eden区和两个

survivor区,比例为8:1:1。关于堆的大部分内容我已经放到垃圾回收部分进行讲解。


(六)总结


当真正去深入理解JVM虚拟机的时候,会发现它并不像想象中那么难,一个JVM虚拟机实际上就包含了这几样东西,最后再画张图描述一下常用JVM参数针对的位置。

网络异常,图片无法展示
|



相关文章
|
1月前
|
存储 缓存 安全
Java内存模型深度解析:从理论到实践####
【10月更文挑战第21天】 本文深入探讨了Java内存模型(JMM)的核心概念与底层机制,通过剖析其设计原理、内存可见性问题及其解决方案,结合具体代码示例,帮助读者构建对JMM的全面理解。不同于传统的摘要概述,我们将直接以故事化手法引入,让读者在轻松的情境中领略JMM的精髓。 ####
39 6
|
23天前
|
安全 Java 程序员
深入理解Java内存模型与并发编程####
本文旨在探讨Java内存模型(JMM)的复杂性及其对并发编程的影响,不同于传统的摘要形式,本文将以一个实际案例为引子,逐步揭示JMM的核心概念,包括原子性、可见性、有序性,以及这些特性在多线程环境下的具体表现。通过对比分析不同并发工具类的应用,如synchronized、volatile关键字、Lock接口及其实现等,本文将展示如何在实践中有效利用JMM来设计高效且安全的并发程序。最后,还将简要介绍Java 8及更高版本中引入的新特性,如StampedLock,以及它们如何进一步优化多线程编程模型。 ####
24 0
|
1月前
|
存储 算法 Java
Java内存管理深度剖析与优化策略####
本文深入探讨了Java虚拟机(JVM)的内存管理机制,重点分析了堆内存的分配策略、垃圾回收算法以及如何通过调优提升应用性能。通过案例驱动的方式,揭示了常见内存泄漏的根源与解决策略,旨在为开发者提供实用的内存管理技巧,确保应用程序既高效又稳定地运行。 ####
|
25天前
|
存储 监控 算法
Java内存管理深度剖析:从垃圾收集到内存泄漏的全面指南####
本文深入探讨了Java虚拟机(JVM)中的内存管理机制,特别是垃圾收集(GC)的工作原理及其调优策略。不同于传统的摘要概述,本文将通过实际案例分析,揭示内存泄漏的根源与预防措施,为开发者提供实战中的优化建议,旨在帮助读者构建高效、稳定的Java应用。 ####
37 8
|
23天前
|
存储 监控 算法
深入探索Java虚拟机(JVM)的内存管理机制
本文旨在为读者提供对Java虚拟机(JVM)内存管理机制的深入理解。通过详细解析JVM的内存结构、垃圾回收算法以及性能优化策略,本文不仅揭示了Java程序高效运行背后的原理,还为开发者提供了优化应用程序性能的实用技巧。不同于常规摘要仅概述文章大意,本文摘要将简要介绍JVM内存管理的关键点,为读者提供一个清晰的学习路线图。
|
27天前
|
存储 算法 Java
Java 内存管理与优化:掌控堆与栈,雕琢高效代码
Java内存管理与优化是提升程序性能的关键。掌握堆与栈的运作机制,学习如何有效管理内存资源,雕琢出更加高效的代码,是每个Java开发者必备的技能。
53 5
|
25天前
|
存储 算法 Java
Java内存管理深度解析####
本文深入探讨了Java虚拟机(JVM)中的内存分配与垃圾回收机制,揭示了其高效管理内存的奥秘。文章首先概述了JVM内存模型,随后详细阐述了堆、栈、方法区等关键区域的作用及管理策略。在垃圾回收部分,重点介绍了标记-清除、复制算法、标记-整理等多种回收算法的工作原理及其适用场景,并通过实际案例分析了不同GC策略对应用性能的影响。对于开发者而言,理解这些原理有助于编写出更加高效、稳定的Java应用程序。 ####
|
25天前
|
安全 Java 程序员
Java内存模型的深入理解与实践
本文旨在深入探讨Java内存模型(JMM)的核心概念,包括原子性、可见性和有序性,并通过实例代码分析这些特性在实际编程中的应用。我们将从理论到实践,逐步揭示JMM在多线程编程中的重要性和复杂性,帮助读者构建更加健壮的并发程序。
|
1月前
|
算法 Java 开发者
Java内存管理与垃圾回收机制深度剖析####
本文深入探讨了Java虚拟机(JVM)的内存管理机制,特别是其垃圾回收机制的工作原理、算法及实践优化策略。不同于传统的摘要概述,本文将以一个虚拟的“城市环卫系统”为比喻,生动形象地揭示Java内存管理的奥秘,旨在帮助开发者更好地理解并调优Java应用的性能。 ####
|
1月前
|
Java
java内存区域
1)栈内存:保存所有的对象名称 2)堆内存:保存每个对象的具体属性 3)全局数据区:保存static类型的属性 4)全局代码区:保存所有的方法定义
24 1