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

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结构的总结:
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Ansys Lumerical | 激光雷达天线仿真

附件下载 联系工作人员获取附件 在本文中,我们将了解如何根据激光雷达应用需求设计和优化相控阵光栅天线。 概述 激光雷达(LIDAR)是“light detection and ranging”的简称,近年来由于在机器人、自动驾驶汽车、高精度测绘等领域…

自动写作软件哪个好?分享7款独家推荐

随着人工智能技术的不断发展,自动写作软件正逐渐成为现代写作的利器。这些AI写作工具能够帮助用户高效地生成文章、报告、新闻稿等内容,为写作工作带来了极大的便利。然而,市面上的自动写作软件琳琅满目,让人眼花缭乱。为了帮助读…

Java多线程学习(一)

1、什么是多线程 进程的执行需要依赖线程。线程是进程的最小执行单位,每一个进程中最少有一个线程。 例如:使用某网盘下载时,当我们同时进行下载和上传操作时(同一时间同时进行),就使用到了多线程&#x…

德国法兰克福交易所股票清单列表数据API接口

# Restful API https://tsanghi.com/api/fin/stock/XFRA/list?token{token}更新时间:收盘后3~4小时。 更新周期:每天。 请求方式:GET。 # 测试:返回不超过10条数据(2年历史) https://tsanghi.com/api/fin/…

【Java,Redis】Redis 数据库存取字符串数据以及类数据

1、 字符串存取数据 Resource private StringRedisTemplate stringRedisTemplate;//从Redis中获取string字符串 stringRedisTemplate.opsForValue().get("cache:shop:"id); //Json -> class Shop shop JSONUtil.toBean(ShopJson,Shop.class); //字符串写入redis…

基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的自动驾驶目标检测系统详解(深度学习+Python代码+PySide6界面+训练数据集)

摘要:开发自动驾驶目标检测系统对于提高车辆的安全性和智能化水平具有至关重要的作用。本篇博客详细介绍了如何运用深度学习构建一个自动驾驶目标检测系统,并提供了完整的实现代码。该系统基于强大的YOLOv8算法,并对比了YOLOv7、YOLOv6、YOLO…

什么是VR应急预案演练虚拟化|VR体验馆加盟|元宇宙文旅

VR 应急预案演练虚拟化指的是利用虚拟现实(Virtual Reality,VR)技术进行应急预案演练的过程。在传统的应急预案演练中,人们通常需要在实际场地或模拟环境中进行演练,这可能存在一些限制,如成本高昂、场地受…

解析KafkaConsumer类的神奇之道

欢迎来到我的博客,代码的世界里,每一行都是一个故事 解析KafkaConsumer类的神奇之道 前言KafkaConsumer双线程设计主线程(消费线程):心跳线程:示例代码: KafkaConsumer线程不安全线程安全的替代…

PHP爬虫技术:利用simple_html_dom库分析汽车之家电动车参数

摘要/导言 本文旨在介绍如何利用PHP中的simple_html_dom库结合爬虫代理IP技术来高效采集和分析汽车之家网站的电动车参数。通过实际示例和详细说明,读者将了解如何实现数据分析和爬虫技术的结合应用,从而更好地理解和应用相关技术。 背景/引言 随着电…

非空约束

oracle从入门到总裁:​​​​​​https://blog.csdn.net/weixin_67859959/article/details/135209645 非空约束 所谓的非空约束,指的是表中的某一个字段的内容不允许为空。如果要使用非空约束,只需要在每个列的后面利用“NOT NULL”声明即可 -- 删除数…

Java习题中 哈希表的理论 有效的字母异位词 快乐数 两数之和

关于 哈希表的理论 今天最大的疑惑好像就是map的复杂度怎么算哈哈,一般n个元素map的复杂度就是On哦,不需要想得太复杂了,冲突的空间并不会造成一个量级,改变n前面的常数不会影响空间复杂度哈提醒!熟悉好map,set的API哦 关于 有效的字母异位词 为什么遍历第二个字符…

Linux异步通知实验:应用程序对异步通知的处理

一. 简介 前面文章学习了 应用程序对异步通知的处理方法,另一篇文章实现了Linux驱动对异步通知的处理: Linux应用程序对异步通知的处理-CSDN博客 Linux异步通知实验:驱动中异步通知的处理-CSDN博客 本文继续Linux异步通知实验&#xff0c…

想进阿里?先搞懂Spring Bean作用域!

大家好,我是小米!今天我来和大家分享一下 Java 开发中一项非常重要的技术——参数校验。参数校验在我们的代码中起着至关重要的作用,它能够确保我们的应用程序接收到正确的数据,并且保证了系统的安全性和稳定性。在过去,我们可能会通过繁琐的 if-else 来进行参数校验,但是…

AI视频矩阵混剪系统|罐头鱼AI批量混剪定时发送

AI视频矩阵混剪系统:智能创作与发布的完美结合 随着社交媒体平台的快速发展,视频已成为各行业推广和传播的热门方式。然而,对于许多人来说,制作高质量的视频仍然是一项挑战。Q:290615413但现在,有了AI视频矩阵混剪系统…

lftp服务与http服务(包含scp服务)详解

目录 前言: 1.lftp服务 1.1lftp服务的介绍以及应用场景 1.2安装lftp服务 1.2进行配置 1.3实际操作 2.http服务 2.1http服务介绍以及应用场景 2.1安装httpd服务 2.2进行配置 2.3实际操作 3.scp服务 3.1scp服务的介绍以及应用场景 致谢: 前言: 在当今互联网…

xss.haozi.me靶场“0x0B-0x12”通关教程

君衍. 一、0x0B 实体编码绕过二、0x0C script绕过三、0x0D 注释绕过四、0X0E ſ符号绕过五、0x0F 编码解码六、0x10 直接执行七、0x11 闭合绕过八、0x12 闭合绕过 XSS-Labs靶场“1-5”关通关教程 XSS-Labs靶场“6-10”关通关教程 Appcms存储型XSS漏洞复现 XSS-Labs靶场“11-13、…

CSS学习-选择器

一、基本选择器 1. 通配选择器 作用:可以选中所有的 HTML 元素。 语法: * { 属性名: 属性值; }举例: /* 选中所有元素 */ * { color: orange; font-size: 40px; }主要用于:清除样式。 2. 元素选择器 作用:为页面…

57、服务攻防——应用协议RsyncSSHRDP漏洞批扫口令猜解

文章目录 口令猜解——Hydra-FTP&RDP&SSH配置不当——未授权访问—Rsync文件备份协议漏洞——应用软件-FTP&Proftpd搭建 口令猜解——Hydra-FTP&RDP&SSH FTP:文本传输协议,端口21;RDP:windows上远程终端协议…

多媒体会议系统的优势与核心组成

随着科技的发展,多媒体会议系统已经成为现代商务沟通的重要工具。这种集成了多种通信和信息技术的系统,旨在提高会议的效率和参与度,具有诸多优势。本文将对多媒体会议系统进行详细的介绍和分析,并探讨其对现代商务沟通的影响。 …

Python程序设计基础——代码习题

1 __name__属性 import demodef main():if __name__ __main__:print(这个程序被直接运行。)elif __name__demo:print(这个程序作为模块被使用。) main()3.3 编写程序,生成包含1000个0~100之间的随机整数,并统计每个元素出现的次数。 import randomx[r…