JAVA基础—JVM内存结构基础需知

news2025/1/4 19:34:35

1.JVM内存结构

JVM内存结构分为5个区域:方法区,虚拟机栈,本地方法栈、堆、程序计数器。
在这里插入图片描述
1.方法区(Method Area):用于存储类的结构信息、常量、静态变量、即使编译器编译后的代码等数据。方法区也是所有线程共享的区域。
2. 堆(Heap):堆时Java虚拟机管理的最大的一块内存区域,用于存储对象实例。Java堆时所有线程共享的内存区域,在Jvm启动时就被创建。Java堆可以分为新生代(Young Generation)、老年代(Old Generation)等区域,用于实现垃圾回收。
3. 虚拟机栈(VM Stack):每个线程在创建时会被分配一个虚拟机栈,用于存储方法调用的栈帧。栈帧包含局部变量表、操作数栈、动态链接、方法返回地址等信息。在方法调用时,会创建一个新的栈帧压入虚拟机栈,并在方法返回时将栈帧出栈。
4. 本地方法栈(Nactive Method Stack):类似于虚拟机栈,用于支持本地方法(Native Method)的调用
5. 程序计数器(Program Counter Register):是一块较小的内存空间,可以看作时当前线程所执行的字节码的行号指示器。在多线程环境下,每个线程都有一个独立的程序计数器,用于唇齿当前线程正在执行的指令地址。

2.方法区(Method Area)—线程共享

在进行类加载时,方法区会存储类的元数据信息。方法区内的类卸载很苛刻,所以正常是认为方法区内没有垃圾回收的。
类的卸载通常需要满足一定的条件,包括:

  • 类实例的引用数量为零:即没有任何类的实例被引用,包括静态变量对该类的引用。
  • 类的ClassLoader被卸载:ClassLoader负责加载类到内存中,当ClassLoader被卸载时,它加载的类也会被卸载。
  • 没有被其他类引用:即没有其他类通过反射等方式引用该类。

在方法区,还有一个空间,运行时常量池(Runtime Constant Pool):是方法区的一部分,用于存储编译期生成的各种字面量和符号引用。

3.堆(Heap)—线程共享

堆(Heap)是Java虚拟机管理机管理的最大一块内存区域,用于存储对象实例。堆内存是所有线程共享的内存区域,在JVM启动时就被创建。在堆内存中,会被动态地分配内存,用于存储新创建的对象。

  • 堆内存通常被划分为几个不同的区域,包括:
    1. 新生代(Young Generation):新创建的对象会被分配到新生代中。新生代通常使用复制算法(Copying),将内存分为两块,一块为Eden区,另一块有两个 Survivor 区,通常称为 Survivor0 和 Survivor1(或者叫做 From 区和 To 区)。
      Survivor两个区是对称的,没有先后关系,所以在新生代的垃圾回收过程中,对象会从 Eden 区复制到其中一个 Survivor 区,然后经过多次垃圾回收后仍然存活的对象会被移动到另一个 Survivor 区。最终,经过多次垃圾回收后仍然存活的对象会被移动到老年代。因此,同一个 Survivor 区可能同时存在来自 Eden 区和另一个 Survivor 区的对象,而复制到老年代的对象只有从第一个 Survivor 区过来的对象。
    2. 老年代(Old Generation):老年代主要存储一些较大的、存活时间较长的对象。在新生代经过多次垃圾回收后仍然存活的对象会被移动到老年代。老年代通常使用标记-清除(Mark-Sweep)算法或标记-整理(Mark-Compact)算法进行垃圾回收。

在这里插入图片描述

  • 在堆中的字符串常量池(String Pool)

    字符串常量池用于存储字符串常量。在Java中,字符串常量通常在编译器就确定了其值,并且会被放入到字符串常量池中。当程序中需要使用相同内容的字符串常量时,虚拟机会直接从字符串常量池中获取,而不是创建一个新的字符串对象。
    举个例子,对于JVM底层,String str = new String(“test”)创建对象流程:

    1. “test”字符串:JVM会首先检查字符串常量池是否已经存在相同的字符串,如果存在则直接返回该对象的引用,否则就在字符串常量池中创建一个新的字符串对象。
    2. ‘new String(“test”)’这部分代码会在堆内存中创建一个新的字符串对象,即使字符串常量池已经存在了“test”的字符串常量。但因为使用了‘new’关键字,明确要求创建一个新的对象,而不是直接使用常量池中已有的对象。
      因此,这一行代码会生成两个对象。而日常我们创建字符串常量值,直接使用String bb=“bbb”,这种创建方式只会在字符串常量池创建一个对象。
      它和普通的堆内存有一些区别,例如,字符串常量池中的字符串对象是不可变的,而且具有一定的缓存机制,以提高字符串对象的复用率和性能。

4.JAVA虚拟机栈(VM Stack)—线程私有

首先知道:栈后进先出
虚拟机栈用于存储方法调用的信息,包括局部变量表、操作数栈、动态链接、方法返回地址等。

  1. 方法调用:每次方法调用时,都会创建一个新的栈帧压入虚拟机栈,方法执行结束后,对应的栈帧会被弹出。

    	  public static void main(String[] args) {
        int a = 1;
        int b = 2;
        int sum = add(a, b);
        System.out.println("sum: " + sum);
    	}
    	
    	public static int add(int a, int b) {
    	    return a + b;
    	}
    

    mian方法在jvm中的执行可以用以下步骤来描述:

    1. 调用 main 方法,创建 main 方法的栈帧。
    2. 在 main 方法中声明局部变量 a 和 b,并将值赋给它们。
    3. 调用 add 方法,创建 add 方法的栈帧。
    4. 在 add 方法中将 a 和 b 相加,并将结果返回。
    5. add 方法执行结束,其栈帧被弹出,返回到 main 方法。
    6. 在 main 方法中将 add 方法返回的结果存储到 sum 变量中。
    7. 打印 sum 的值。
    8. main 方法执行结束,其栈帧被弹出,程序结束执行。
  2. 局部变量:每个栈帧中都包含一个局部变量表,用于存储方法中的局部变量。局部变量表中存储的是基本数据类型和对象引用,不存储对象本身。
    在 Java 中,对象的引用通常是存储在栈上的,而对象实例则存储在堆上。当我们创建一个对象时,实际上是在堆上分配了一块内存来存储对象的实例数据,并返回一个引用指向这个对象。这个引用会被存储在栈上,作为对堆中对象的引用。

  3. 操作数栈:每个栈帧都包含一个操作数栈,用于存储方法执行过程中的操作数。操作数栈用于执行方法的运算操作,如加减乘除等。

  4. 异常处理:虚拟机栈也用于异常处理。当方法出现异常时,虚拟机会查找虚拟机栈中的异常处理器,以确定如何处理异常。

虚拟机栈的大小可以通过 JVM 的启动参数来指定,例如 -Xss 参数用于指定每个线程的栈大小。虚拟机栈的大小会影响方法调用的深度,如果方法调用的层级过深,可能会导致栈溢出异常。

5. 本地方法栈(Native Method Stack)—线程私有

本地方法栈与虚拟机栈类似,用于支持Java调用本地方法(Native Method)的过程。本地方法栈也是线程私有的,每个线程在调用本地方法时都会创建一个对应的本地方法栈。
本地方法栈与虚拟机栈区别在于,虚拟机栈用于执行Java方法的Java字节码,而本地方法栈用于执行本地方法的机器码(Native Code)。本地方法是使用本地语言(如C、C++)编写的方法,通过Java的本地接口(JNI)调用。
本地方法栈与虚拟机栈的大小可以分别设置,并且本地方法栈的大小可能会影响到本地方法的调用。如果本地方法栈空间不足,可能会导致栈溢出异常。

在Java中,Native指的是使用其他编程语言(如C、C++)等编写的方法,这些代码通过Java的本地接口(JNI、Java Native Interface)来与Java代码进行交互。通过使用Native方法,Java程序可以调用本地系统的功能或者特定的硬件设备,从而实现更高级的功能和性能优化。
使用 Native 方法需要在 Java 中声明 Native 方法,并使用 native 关键字修饰,然后通过 JNI 在本地代码中实现这些 Native 方法。在运行时,Java 虚拟机会加载本地库,并通过 JNI 调用本地方法。需要注意的是,使用 Native 方法会降低程序的可移植性,并增加程序的复杂度,因此应该谨慎使用。

6. 程序计数器(Program Counter Register)—线程私有

程序计数器是一块较小的内存空间,也可以称为寄存器,在Java虚拟机中用于存储当前正在执行的字节码指令的地址或索引。在多线程环境下,每个线程都有一个独立的程序计数器,用于指示当前线程执行的位置。
在Java虚拟机中,程序计数器不会发生内存溢出(OutOfMemoryError)的情况,因为它只是一个指示器,并不会存储任何对象或数据。
在这里插入图片描述
程序计数器在不同情况下记录的内容略有不同:

  1. 执行Java方法时:程序计数器记录的是正在执行的虚拟机字节码指令的地址,即程序计数器存储的是下一条要执行的指令在方法内的偏移量。这样,当线程中断或切换后再恢复执行时,可以准确地知道接下来应该执行哪条指令。
    举例:

    	public class Example {
        public static void main(String[] args) {
            int a = 1;
            int b = 2;
            int sum = add(a, b);
            System.out.println("sum: " + sum);
        }
        public static int add(int a, int b) {
            return a + b;
        }
    }
    

    假设 add 方法的字节码指令如下(简化表示):

    1. 将局部变量 a 压入操作数栈
    2. 将局部变量 b 压入操作数栈
    3. 执行加法操作
    4. 将结果存入局部变量表
    5. 返回结果
      当程序执行到 add 方法时,程序计数器会记录当前执行的位置,比如可能会记录为第一个字节码指令的地址。随着方法的执行,程序计数器会逐步指向下一条要执行的字节码指令,以便虚拟机可以准确地控制方法的执行流程。
  2. 执行Native方法时:由于Native方法是由本地语言编写地,不是Java字节码,因此程序计数器通常是空的或者。

7.小结

JVM的内存结构只是JVM中很基础的一部分,但了解JVM的结构,对于我们学习JAVA的基础类很有帮助,比如说引用对象(栈)和实例对象(堆)的存储区域、String在JVM的存特殊设计(字符串常量池)、JAVA类初始化元数据加载的空间(方法区)、基本数据类型存储空间(栈)、静态变量(方法区)等等。
下面是jvm结构的总结:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1520591.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Spring项目问题—前后端交互:Method Not Allowed

问题 前后端交互时出现Method Not Allowed问题 Ajax中使用的是get,方法仍然出现post方法报错 Resolved [org.springframework.web.HttpRequestMethodNotSupportedException: Request method POST not supported] 浏览器中没有报错,只是接收不到后端返…

Midjourney视觉垫图

https://github.com/lllyasviel/Fooocus/discussions/117https://github.com/lllyasviel/Fooocus/discussions/117掌握Midjourney的垫图技巧:AI绘画中的参考利器本期将深入了解AI绘画的垫图技巧,让作品获得更好的出图效果https://mp.weixin.qq.com/s/RS2…

【QT 5 +Linux下qt软件点击.sh脚本运行+Dconf编辑器+学习他人文章+番外篇:点击脚本运行软件】

【QT 5 Linux下qt软件点击.sh脚本运行Dconf编辑器学习他人文章番外篇:点击脚本运行软件】 1、前言2、实验环境3、自我学习总结-本篇总结1、说明:代替qt的快捷方式2、适用性更广3、了解工具:Dconf编辑器注意事项: 4、参考链接-感谢…

力扣L11--- 344.反转字符串(JAVA版)-2024年3月15日

1.题目 2.知识点 交换两个变量值的代码 char temps[left];//temp为暂时的变量,left是左指针,将left暂时存储在temp里面s[left]s[right];//将右指针的值赋给左指针s[right]temp;//将temp的值给右指针left;//左指针向左移动right--;//右指针向右移动3.代码…

Python QT 之PySide6简单入门

目录 1.开发环境配置 1.1 下载PySide6 2.2 配置pycharm相关快捷方式 PySide6_Designer - QT Designer 设计UI PySide6_UIC - 将QT Designer生成的UI文件转换为python文件 PySide6_RCC - 将RCC文件转换为python文件 2.第一个开发实例 2.1 QT desiger设计界面 2.2 将ui文…

南大通用数据库-Gbase-8a-学习-43-SQL长时间处于Writing to net状态排查

目录 一、问题截图 二、排查思路 1、Gbase8a SQL有几种状态 2、问题导致原因猜想 3、观察服务端(集群端)网络情况 4、观察客户端网络情况 5、排查客户端程序处理数据慢 5.1、send (1)声明 (2)作用…

【SCI论文】“学术丑闻揭露:当AI写作遭遇学术审稿,ChatGPT意外成为论文共作者!“

在最近的学术圈中出现了一篇令人哭笑不得的论文。这篇文章标题为“The three-dimensional porous mesh structure of Cu-base…”发表在《Surfaces and Interfaces》杂志上,竟然包含了ChatGPT的提示语,暴露出了审稿过程中可能的疏忽。 文章讨论了铜基金…

行业突破!四信实现低延时摄像头弱网状态100ms以内实时传输

随着人工智能、大数据、区块链等技术在城市中快速发展,人们日常生活中已经离不开网络的支撑,而实现“人与人”、“人与物”及“物与物”之间高速连接应用的“时延”,是网络支撑中最重要的存在。 以城市生活例子为例,当网络延时出现…

王勇:硬科技的下一站 | 演讲嘉宾公布

一、智能耳机与可穿戴专题论坛 智能耳机与可穿戴专题论坛将于3月27日同期举办! 智能耳机、可穿戴设备已经逐渐融入我们的生活,它们不仅带来了便捷与舒适,更在悄然改变着我们的生活方式和工作模式。在这里,我们将分享最新的研究成果…

图像分类技术在电商平台的创新应用与实践

一、引言 在当今快速发展的互联网电商领域,商家面临着激烈的竞争和不断变化的市场需求。我们在服务电商的过程中,利用AI大模型技术创新性地引入了图像分类技术,为供应链管理带来了革命性的变革。接下来,我们将深入探讨这一项目的…

【STM32学习】PWM学习,(二)驱动LED呼吸灯

上文学习了PWM的基本概述,和PWM的各种参数,本文 学习使用PWM信号去驱动LED实现呼吸灯的效果。 1、PWM驱动LED呼吸灯 1.1介绍 目标:单片机输出一个PWM信号,驱动LED呼吸亮灭。PWM占空比高,则LED更亮;PWM占空…

javase day05笔记

第5天课堂笔记 四舍五入问题,保留两位小数★ System.out.printf("%.2f\n" , d);选择结构★★★ ifif(){}else{}:二选一if(){}else if(){}else if(){} else{} :多重if:多选1 和 equals区别★★★ 基本数据类型:对比值…

STM32F103 CubeMX 使用USB生成鼠标设备

STM32F103 CubeMX 使用USB生成鼠标设备 1 配置cubeMX1.1配置外部晶振,配置debug口1.2 配置USB1.3 配置芯片的时钟1.4 生成工程 2. 编写代码2.1 添加申明2.2 main函数代码 1 配置cubeMX 1.1配置外部晶振,配置debug口 1.2 配置USB 1.3 配置芯片的时钟 需…

【算法与数据结构】深入解析二叉树(二)之堆结构实现

文章目录 📝二叉树的顺序结构及实现🌠 二叉树的顺序结构🌠 堆的实现🌠 堆的实现🌉堆向下调整算法🌉堆的创建🌉建堆时间复杂度🌉堆的插入🌉堆的删除 🌠堆向上调…

sqllab第十九关通关笔记

知识点: 错误注入 最大长度为32位;如果目标长度>32时,需要利用截取函数进行分段读取referer注入 insert语句update语句 通过admin admin进行登录发现页面打印除了referer字段的信息 这应该是一个referer注入 首先进行测试一下 构造payl…

MATLAB/SIMULINK流水账

01.模块大小的一致性 当模型建完以后,模型大小比较散乱,可以利用该功能快速整理模块的大小 例如:如下5个constant模块,大小不一 若想把所有的模块都调整至跟第3个模块一样的大小 需要先把5个模块全部选取起来,另外再…

开发指南006-后端配置文件

后端配置文件分为两层,一是部署目录中的内容如下: 这里最重要的是端口号,同一个目录下可以是一个jar包多个配置文件,启动批处理中,按一个配置文件启动一个程序的方式启动多个服务。例如上面目录里的启动批处理文件可以…

Observability:使用 Elastic AI Assistant 和 APM 分析 OpenTelemetry 应用程序

作者:来自 Elastic Bahubali Shetti OpenTelemetry 正在迅速成为云原生计算基金会 (CNCF) 内最广泛的项目,拥有与 Kubernetes 一样多的提交,并获得了客户的广泛支持。 许多公司正在采用 OpenTelemetry 并将其集成到他们的应用程序中。 Elasti…

【AI+应用】一步步搭建聊天机器人搭配多种国内外大模型以及api接口调用

如果你看过我之前写的一篇文章 【AI应用】怎么快速制作一个类chatGPT套壳网站, 你可能顺利地使用chatGPT、Gemini, 用得很happy。 突然有一天,你发现一些网站,除了chatGPT、Gemini ,还可以切换使用国内外其他的大模型…

“风口”上的量化大厂“绣球”抛向中低频人才

量化人才这几年是人才舞台上的“香饽饽”。 遵循着低频不如高频、小厂不如大厂的薪资逻辑,各路人才被各路机构“哄抢”,薪资一路走高。 但2024年的“信号”再强烈不过——量化大厂们到了改变的时候了。 而量化大厂们显然对此已“心知肚明”....... “…