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

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

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

相关文章

【数据库】Oracle内存结构与参数调优

Oracle内存结构与参数调优 Oracle 内存结构概览oracle参数配置概览重要参数(系统运行前配置):次要参数(可在系统运行后再优化调整): Oracle数据库服务器参数如何调整OLTP内存分配操作系统核心参数配置Disabling ASMM(禁…

React18 后台管理模板项目:现代、高效与灵活

🎉 给大家推荐一款React18TypescriptVitezustandAntdunocss且超级好用的中后台管理框架 项目地址 码云:https://gitee.com/nideweixiaonuannuande/xt-admin-react18github:https://github.com/1245488569/xt-admin-react18 演示地址 http…

2024年【安全员-A证】复审考试及安全员-A证模拟试题

题库来源:安全生产模拟考试一点通公众号小程序 安全员-A证复审考试参考答案及安全员-A证考试试题解析是安全生产模拟考试一点通题库老师及安全员-A证操作证已考过的学员汇总,相对有效帮助安全员-A证模拟试题学员顺利通过考试。 1、【多选题】《安全生产…

男生穿什么裤子最帅?目前最流行的男裤子款式分享

现在不少男生朋友都觉得裤子特别难选,尤其是市面上经常会有一些面料劣质、版型不正确的款式,导致大家选衣服就尤其容易踩雷。所以今天就来和大家分享一下哪些口碑较好的男装品牌值得推荐! 男装裤子怎么选?市面上的品牌多得数不胜数…

layuiAdmin-通用型后台模板框架【广泛用于各类管理平台】

1. 主页 1.1 控制台 2. 组件 3. 页面 3.1 个人主页 3.2 通讯录 3.3 客户列表 3.4 商品列表 3.5 留言板 3.6 搜索结果 3.7 注册 3.8 登入 3.9 忘记密码 4. 应用 4.1 内容系统 4.1.1 文章列表 4.1.2 分类管理 4.1.3 评论管理 4.2 社区系统 4.2.1 帖子列表 4.2.2 回…

2024年【危险化学品经营单位安全管理人员】考试及危险化学品经营单位安全管理人员考试题

题库来源:安全生产模拟考试一点通公众号小程序 危险化学品经营单位安全管理人员考试根据新危险化学品经营单位安全管理人员考试大纲要求,安全生产模拟考试一点通将危险化学品经营单位安全管理人员模拟考试试题进行汇编,组成一套危险化学品经…

第二百零四回

文章目录 1 .概念介绍2. 使用方法3. 示例代码 我们在上一章回中介绍了自定义缓冲组件相关的内容,本章回中将介绍一个和它类似的组件:下拉刷新组件.闲话休提,让我们一起Talk Flutter吧。 1 .概念介绍 我们在本章回介绍的下拉刷新组件叫Refres…

Java基础-复制

复制 前言引用拷贝浅拷贝深拷贝重写clone()方法序列化 前言 在编码中,我们可能会遇到需要将对象的属性复制到另一个对象中,这种情况叫做拷贝. 拷贝与Java内存结构有密切关系,拷贝有三种情况,引用拷贝,深拷贝和浅拷贝,下面来了解一下. 引用拷贝 引用拷贝会生成一个新的对象引…

15届蓝桥杯第二期模拟赛题单详细解析

文章目录 🧡🧡t1_求余🧡🧡思路代码 🧡🧡t2_灌水🧡🧡思路代码 🧡🧡t3_字符显示🧡🧡思路代码 🧡🧡t4_区间最大和…

携手共进办公网络安全

一、引言 在数字化时代的今天,办公网络安全问题已日益成为企业发展的重要课题。随着信息技术的快速发展,网络安全威胁也呈现出多样化、复杂化的趋势。这些危害可能源于网络本身的漏洞、人为因素或外部威胁,给企业的信息安全和正常运营带来严…

游戏组队新姿势!Xinstall一键拉起,好友秒速加入你的战队!

在如今的游戏世界中,与好友一起组队开黑已成为一种潮流。然而,繁琐的组队过程往往让玩家们望而却步。这时,你需要一款强大的辅助工具——Xinstall,它是一站式App全渠道统计服务商,专注于提供App传参安装、全渠道广告效…

springboot274基于web的电影院购票系统

电影院购票系统设计与实现 摘 要 传统办法管理信息首先需要花费的时间比较多,其次数据出错率比较高,而且对错误的数据进行更改也比较困难,最后,检索数据费事费力。因此,在计算机上安装电影院购票系统软件来发挥其高效…

strcmp的模拟实现

一:strcmp函数的定义: strcmp函数功能的解释: 比较两个字符串的大小(按照字符串中字符的ascll码值)。 标准规定: 第一个字符串大于第二个字符串,则返回大于 0 的数字 第一个字符串等于第二个…

市场复盘总结 20240315

仅用于记录当天的市场情况,用于统计交易策略的适用情况,以便程序回测 短线核心:不参与任何级别的调整,采用龙空龙模式 一支股票 10%的时候可以操作, 90%的时间适合空仓等待 二进三: 进级率中 0% 最常用的二…

【Linux】IPC-信号

💻文章目录 📄前言信号概念信号阻塞概念 信号的处理信号的使用 📓总结 📄前言 信号,一种无论是生活还是编程都离不开的东西。生活中,我们通过信号来对外部发生的事情进行反应,就好像你的手机来了…

Vue.js+SpringBoot开发个人健康管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 健康档案模块2.2 体检档案模块2.3 健康咨询模块 三、系统展示四、核心代码4.1 查询健康档案4.2 新增健康档案4.3 查询体检档案4.4 新增体检档案4.5 新增健康咨询 五、免责说明 一、摘要 1.1 项目介绍 基于JAVAVueSpri…

程序员必备开发工具、程序员必备集成开发环境(IDE)

🌟 前言 欢迎来到我的技术小宇宙!🌌 这里不仅是我记录技术点滴的后花园,也是我分享学习心得和项目经验的乐园。📚 无论你是技术小白还是资深大牛,这里总有一些内容能触动你的好奇心。🔍 &#x…

CTP-API开发系列之十:v6.7.0-Python版封装(Windows/Linux)(附源码)

CTP-API开发系列之十:v6.7.0-Python版封装(Windows/Linux)(附源码) CTP-API开发系列之十:v6.7.0-Python版封装(Windows/Linux)(附源码)资源获取准备工作Windo…

2023年全球软件质量效能大会(QECon上海站):智慧碰撞,质量与效能的新篇章(附大会核心PPT资料下载)

在数字化浪潮席卷全球的今天,软件行业正以前所未有的速度发展。作为推动这一进程的重要力量,软件质量与效能的提升显得尤为关键。2023年全球软件质量&效能大会(QECon上海站)的盛大召开,无疑为业界提供了一次难得的…

【b站咸虾米】2 Vue基础(上) 2021最新Vue从基础到实例高级_vue2_vuecli脚手架博客案例

课程地址:【2021最新Vue从基础到实例高级_vue2_vuecli脚手架博客案例】 https://www.bilibili.com/video/BV1pz4y1S7bC/?share_sourcecopy_web&vd_sourceb1cb921b73fe3808550eaf2224d1c155 目录 2 Vue基础 上 2.0 补充知识 2.0.1 Vue实例的作用范围 2.0.2 t…