目录
虚拟机栈 " >虚拟机栈
首页 Java java教程 案例解说JVM内存空间(建议收藏)

案例解说JVM内存空间(建议收藏)

Aug 15, 2023 pm 05:16 PM
jvm

今天,跟大家一起聊聊关于JVM内存空间的话题,这也是一线互联网大厂面试中经常被问及的问题,建议小伙伴们收藏后经常拿出来翻阅,重在理解。好了,不多说了,开始今天的正题。

JVM会把内存划分成不同的数据区域,那加载的类是分配到哪里呢?

下图是内存的各个区域,包括:方法区、堆、虚拟机栈、本地方法栈、程序计数器。

案例解说JVM内存空间(建议收藏)

方法区

方法区用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。类的加载中提到了类加载的五个阶段。在加载阶段,会将字节流所代表的静态存储结构转化为方法区的运行时数据结构,在准备阶段,会将变量所使用的内存都将在方法区中进行分配。

程序计数器

来一个简单的代码,计算(1+2)*3并返回

public int cal() {
    int a = 1;
    int b = 2;
    int c = 3;
    return (a + b) * c;
}
登录后复制

这段代码在加载到虚拟机的时候,就变成了以下的字节码,虚拟机执行的时候,就会一行行执行。

案例解说JVM内存空间(建议收藏)

java是多线程的,在线程切换回来后,它需要知道原先的执行位置在哪里。用来记录这个执行位置的,就是程序计数器,为了保证线程间的计数器相互不影响,这个内存区域是线程私有的。

虚拟机栈

虚拟机栈也是线程私有的,生命周期与线程相同。每个线程都有自己的虚拟机栈,如果这个线程执行了一个方法,就会创建一个栈帧,方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。比如下面的例子,fun1调用fun2,fun2调用fun3,fun3创建Hello对象。

public void fun1() {
    fun2();
}

public void fun2() {
    fun3();
}

public void fun3() {
    Hello hello = new Hello();
}
登录后复制

调用的时候,流程图如下:

案例解说JVM内存空间(建议收藏)

执行完成的时候,流程图如下:

案例解说JVM内存空间(建议收藏)

每一个栈帧都包括了局部变量表、操作数栈、动态连接、方法返回地址和一些额外的附加信息。局部变量主要是存放方法参数以及方法内部定义的局部变量,操作数栈是一个后入先出栈,当方法刚刚开始执行的时候,这个方法的操作数栈是空的,在方法的执行过程中,会有各种字节码指令往操作数栈中写入和提取内容,也就是出栈/入栈操作。

我们通过上面(1+2)*3的例子,把方法区、程序计数器、虚拟机栈的协同工作理一下。首先通过javap查看它的字节码,经过类加载器加载后,此时这个字节码存在方法区中。stack表示栈深度是2,locals是本地变量的slot个数,args_size是入参的个数,默认是this。栈的深度、本地变量个数,入参个数,都是在编译器决定的。

案例解说JVM内存空间(建议收藏)

如下图,指令的位置是方法区,局部变量和操作数栈的位置是虚拟机栈,程序计数器就在程序计数器(这个下面的图就不再重复)。当执行偏地址为0的指令的时候,程序计数器为0,局部变量第一个值是this,当前的指令就是方法区0:iconst_1,指令iconst_1就是把int常量值1进栈,这个1就到了虚拟机栈的操作数栈中。

案例解说JVM内存空间(建议收藏)

当执行偏地址为1的指令的时候,程序计数器为1,把操作数栈的值赋值到局部变量,此时操作数栈清空了,局部变量多了一个1,这条指令执行完,就是对应上面int a=1的语句。

案例解说JVM内存空间(建议收藏)

另外b,c两个语句的赋值,对应着2,3,4,5指令,这边不再重复。执行完5后,如下图所示:

案例解说JVM内存空间(建议收藏)

执行6的时候,是执行iload_1,就是把第二个int型局部变量压入栈顶,这里的变量是1。

案例解说JVM内存空间(建议收藏)

执行7的时候,是执行iload_2,就是把第三个int型局部变量压入栈顶,这里的变量是2。

案例解说JVM内存空间(建议收藏)

执行8的时候,是iadd语句,指的是栈顶的两个int型元素出栈,得到结果后再压入栈顶。

案例解说JVM内存空间(建议收藏)

执行9的时候,把栈顶的元素3,赋值到第五个局部变量。

案例解说JVM内存空间(建议收藏)

执行到11的时候,把第五个局部变量值压入栈顶,执行到13的时候,把第四个局部变量值压入栈顶,执行14的时候,栈顶的两个int型元素出栈,相乘后的结果入栈,执行15的时候,从当前方法返回当前栈顶int型元素。这些与上面的相加差不多,就不再赘述了。

堆内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。比如上面的fun1调用fun2,fun2调用fun3,fun3创建Hello对象。fun3方法中创建对象时,就是在堆中创建的,并且把地址赋值给fun3的局部变量。Java堆中还可以细分为:新生代和老年代;新生代还细分为Eden空间、From Survivor空间、To Survivor空间。

案例解说JVM内存空间(建议收藏)

总结

整体流程如下,先把java文件编译成class文件,通过类加载器加载到方法区。线程调用方法的时候,会创建一个栈帧,读取方法区的字节码执行指令,执行指令的时候,会把执行的位置记录在程序计数器中,如果创建对象,会在堆内存中创建,方法执行完,这个栈帧就会出栈。

案例解说JVM内存空间(建议收藏)

相关参数

-XX:PermSize:永久代内存容量。

-XX:MaxPermSize:永久代最大内存容量。

-XX:MetaspaceSize :元空间初始值的大小

-XX:MaxMetaspaceSize :元空间最大值大小

-XX:CompressedClassSpaceSize :元空间中存储Klass类元数据部分的空间大小

-Xss:栈内存容量。

-Xms:堆内存容量。

-Xmx:堆最大内存容量,通常和-Xms设置一样,防止运行时扩容产生的影响。

-Xmn:新生代内存容量,老年代就是堆内存容量-新生代内存容量

-XX:SurvivorRatio=8:新生代还细分为Eden空间、From Survivor空间、To Survivor空间,设置为8代表Eden空间:From Survivor空间:To Survivor空间=8:1:1,比如新生代有10M,那Eden空间占8M,From Survivor空间、To Survivor空间各占1M。

案例解说JVM内存空间(建议收藏)

以上是案例解说JVM内存空间(建议收藏)的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

一个分布式 JVM 监控工具,非常实用! 一个分布式 JVM 监控工具,非常实用! Aug 15, 2023 pm 05:15 PM

该项目为了方便开发者更快监控多个远程主机jvm,如果你的项目是Spring boot那么很方便集成,jar包引入即可,不是Spring boot也不用气馁,你可以快速自行初始化一个Spirng boot程序引入jar包即可

JVM命令行参数详解:掌控JVM运行的秘密武器 JVM命令行参数详解:掌控JVM运行的秘密武器 May 09, 2024 pm 01:33 PM

通过JVM命令行参数,您可以细粒度地调整JVM行为。其中通用参数包括:设置Java堆大小(-Xms、-Xmx)设置新生代大小(-Xmn)启用并行垃圾收集器(-XX:+UseParallelGC)减少Survivor区内存占用(-XX:-ReduceSurvivorSetInMemory)消除冗余垃圾回收(-XX:-EliminateRedundantGCs)打印垃圾回收信息(-XX:+PrintGC)使用G1垃圾收集器(-XX:-UseG1GC)设置最大垃圾回收暂停时间(-XX:MaxGCPau

JVM内存管理要点与注意事项 JVM内存管理要点与注意事项 Feb 20, 2024 am 10:26 AM

掌握JVM内存使用情况的要点与注意事项JVM(JavaVirtualMachine)是Java应用程序运行的环境,其中最为重要的就是JVM的内存管理。合理地管理JVM内存不仅可以提高应用程序的性能,还可以避免内存泄漏和内存溢出等问题。本文将介绍JVM内存使用的要点和注意事项,并提供一些具体的代码示例。JVM内存分区JVM内存主要分为以下几个区域:堆(He

Java错误:JVM内存溢出错误,如何处理和避免 Java错误:JVM内存溢出错误,如何处理和避免 Jun 24, 2023 pm 02:19 PM

Java是一种流行的编程语言,在开发Java应用程序的过程中,可能会遇到JVM内存溢出错误。这种错误通常会导致应用程序崩溃,影响用户体验。本文将探讨JVM内存溢出错误的原因和如何处理和避免这种错误。JVM内存溢出错误是什么?Java虚拟机(JVM)是Java应用程序的运行环境。在JVM中,内存被分为多个区域,其中包括堆、方法区、栈等。堆是用于存储创建的对象的

JVM虚拟机的作用及原理解析 JVM虚拟机的作用及原理解析 Feb 22, 2024 pm 01:54 PM

JVM虚拟机的作用及原理解析简介:JVM(JavaVirtualMachine)虚拟机是Java编程语言的核心组成部分之一,它是Java的最大卖点之一。JVM的作用是将Java源代码编译成字节码,并负责执行这些字节码。本文将介绍JVM的作用及其工作原理,并提供一些代码示例以帮助读者更好地理解。作用:JVM的主要作用是解决了不同平台上Java程序的可移

如何有效地调整JVM堆内存大小? 如何有效地调整JVM堆内存大小? Feb 18, 2024 pm 01:39 PM

JVM内存参数设置:如何合理调整堆内存大小?在Java应用程序中,JVM是负责管理内存的关键组件。其中,堆内存是用于存储对象实例的地方,堆内存的大小设置对应用程序的性能和稳定性有着重要影响。本文将介绍如何合理调整堆内存大小的方法,并附带具体代码示例。首先,我们需要了解一些关于JVM内存的基础知识。JVM的内存分成了几个区域,包括堆内存、栈内存、方法区等。其中

Java程序检查JVM是32位还是64位 Java程序检查JVM是32位还是64位 Sep 05, 2023 pm 06:37 PM

在编写java程序来检查JVM是32位还是64位之前,我们先讨论一下JVM。JVM是java虚拟机,负责执行字节码。它是Java运行时环境(JRE)的一部分。我们都知道java是平台无关的,但是JVM是平台相关的。我们需要为每个操作系统提供单独的JVM。如果我们有任何java源代码的字节码,由于JVM,我们可以轻松地在任何平台上运行它。java文件执行的整个过程如下-首先,我们保存扩展名为.java的java源代码,编译器将其转换为扩展名为.class的字节码。这发生在编译时。现在,在运行时,J

揭秘JVM工作原理:深入探索Java虚拟机的原理 揭秘JVM工作原理:深入探索Java虚拟机的原理 Feb 18, 2024 pm 12:28 PM

JVM原理详解:深入探究Java虚拟机的工作原理,需要具体代码示例一、引言随着Java编程语言的迅猛发展和广泛应用,Java虚拟机(JavaVirtualMachine,简称JVM)也成为了软件开发中不可或缺的一部分。JVM作为Java程序的运行环境,能够提供跨平台的特性,使得Java程序能够在不同的操作系统上运行。在本文中,我们将深入探究JVM的工作原

See all articles