JVM 内存结构快速入门

文章目录

    • 一、简介
    • 二、JVM内存区域
      • 2.1 方法区
        • 2.3.2 永久代和元空间
      • 2.2 堆
        • 2.1.2 对象的创建和销毁
      • 2.2 栈内存
        • 2.2.1 栈帧的组成和作用
        • 2.2.2 栈的特点
      • 2.4 程序计数器
        • 2.4.1 程序计数器的作用和使用场景

一、简介

  Java 内存模型(Java Memory Model,JMM)是一种规范,定义了 Java 程序中多线程并发访问共享变量时的行为和规则。

二、JVM内存区域

  线程共享:方法区、堆
  线程独有:栈、程序计数器

在这里插入图片描述

2.1 方法区

  方法区是JVM中的一块内存区域,在JVM启动时被创建,与堆内存分开管理。方法区的大小可以通过-XX:MetaspaceSize-XX:MaxMetaspaceSize参数进行调整。

  存储的内容有:

  • 类的结构信息:包括类的字段、方法、父类、接口等
  • 常量池
  • 静态变量
  • 即时编译器编译后的代码

2.3.2 永久代和元空间

  在Java虚拟机(JVM)的不同版本中,永久代(Permanent Generation)和元空间(Metaspace)是用于存储类相关信息的内存区域,都是实现方法区的方式。

  1. 永久代(Permanent Generation):
    1.8版本以前有永久代,永久代放在JVM内存中,在某些情况下存在一些问题。例如,如果加载的类过多或过大,永久代的大小可能会不够,导致OutOfMemoryError。由于这些问题,从JDK 8开始,永久代被元空间所取代。

  2. 元空间(Metaspace):
    元空间是JDK 8及更高版本中取代永久代的新的内存区域。元空间同样用于存储类的结构信息、常量池、静态变量和即时编译器编译后的代码等。与永久代不同,元空间的大小不再受限于固定的内存大小,而是根据应用程序的需求进行动态分配。元空间的数据存储在本地内存(Native Memory)中,而不是像永久代那样存储在Java运行时内存中。这意味着元空间的大小受限于可用的物理内存。如果元空间的内存耗尽,JVM依然会抛出OutOfMemoryError。
    在这里插入图片描述

2.2 堆

  堆内存是Java程序中最大的一块内存区域,用于存储对象实例和数组。堆内存可以划分为不同的代,包括新生代(Eden区、Survivor区)和老年代。新创建的对象会被分配到新生代的Eden区,经过垃圾回收后,仍然存活的对象会被移到Survivor区,最终进入老年代。

1.8版本的堆结构:
  新生代与老年代的比例是1:2
  Eden、s0、s1的比例是8比1比1
在这里插入图片描述

1.9及以后的堆结构
  G1将内存划分成了多个大小相等的Region(默认是512K),Region逻辑上连续,物理内存地址不连续。同时每个Region被标记成E、S、O、H,分别表示Eden、Survivor、Old、Humongous。其中E、S属于年轻代,O与H属于老年代。

  H表示Humongous。从字面上就可以理解表示大的对象(下面简称H对象)。当分配的对象大于等于Region大小的一半的时候就会被认为是巨型对象。H对象默认分配在老年代,可以防止GC的时候大对象的内存拷贝。
在这里插入图片描述

2.1.2 对象的创建和销毁

  在Java中,对象的创建通过new关键字实现。当调用new关键字创建对象时,JVM会在堆内存中分配一块内存空间用于存储对象的实例变量,并执行构造方法对对象进行初始化。对象的销毁由垃圾回收器负责,当对象不再被引用时,垃圾回收器会回收该对象的内存空间。

  创建流程:

  1. ⾸先检查这个指令的参数是否能在常量池中定位到⼀个类的符号引⽤
  2. 检查这个符号引⽤代表的类是否已被加载、解析和初始化过。如果没有,就先执⾏相应的类加载过程
  3. 类加载检查通过后,接下来虚拟机将为新⽣对象分配内存。
  4. 内存分配完成之后,虚拟机将分配到的内存空间(但不包括对象头)都初始化为零值。
  5. 接下来设置对象头,请求头⾥包含了对象是哪个类的实例、如何才能找到类的元数据信息、对象的 哈希码、对象的 GC 分代年龄等信息
    在这里插入图片描述

2.2 栈内存


  栈分为本地方法栈和java方法栈。
在这里插入图片描述

  每个线程在创建时都会创建一个java方法栈,栈内会保存一个个的栈帧,每个栈帧对应一个方法。
  栈采用先进后出的数据结构,方法的调用和返回都是通过栈帧的入栈和出栈来实现的。
在这里插入图片描述

2.2.1 栈帧的组成和作用

  栈帧是栈内存中的一个元素,用于存储方法的局部变量表、操作数栈、动态链接、方法返回地址等信息。局部变量表用于存储方法的局部变量和参数,操作数栈用于存储方法执行过程中的操作数和中间结果。栈帧的作用是提供方法调用和执行的环境,保证方法的独立性和数据的隔离性。
在这里插入图片描述

2.2.2 栈的特点

  1. 栈是线程私有的
  2. 一个方法开始执行栈帧入栈、方法执行完对应的栈帧就出栈,所以虚拟机栈不需要进行垃圾回收
  3. 虚拟机栈存在OutOfMemoryError、以及StackOverflowError
  4. 线程太多,就可能会出现OutOfMemoryError,线程创建时没有足够的内存去创建虚拟机栈了
  5. 方法调用层次太多,就可能会出现StackOverflowError(栈的大小有限)
  6. 可以通过-Xss来设置虚拟机栈的大小

2.4 程序计数器

2.4.1 程序计数器的作用和使用场景

  程序计数器是一块较小的内存区域,用于存储当前线程执行的字节码指令的地址。程序计数器在多线程环境下,每个线程都有独立的程序计数器,用于记录各个线程执行的位置,保证线程切换后能正确恢复执行。

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

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

相关文章

Qt读写Excel--QXlsx编译为静态库2

1、概述🥔 在使用QXlsx时由于源码文件比较多,如果直接加载进项目里面,会增加每次编译的时间; 直接将源码加载进项目工程中,会导致项目文件非常多,结构变得更加臃肿; 所以在本文中将会将QXlsx编译…

基于docker部署的Selenium Grid分布式自动化测试

01、什么是Selenium Grid Selenium Grid是Selenium套件的一部分,它专门用于并行运行多个测试用例在不同的浏览器、操作系统和机器上。 Selenium Grid有两个版本——老版本Grid 1和新版本Grid 2。我们只对新版本做介绍,因为Selenium团队已经逐渐遗弃老版…

UE5 实现残影效果

文章目录 前言实现效果示例1示例2示例3示例4实现扩展前言 本文采用虚幻5.2.1版本,对角色生成残影效果进行讲解,以一种简单的、通俗易懂的、高性能的方式来实现此效果。此效果可以在角色使用某一技能时触发,比如使用攻击招式、闪现等等。 实现效果 示例1 在昏暗的环境示例…

mysql主从复制搭建(一主一从)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言MySQL复制过程分为三部: 一、准备工作二、配置>主库Master三、配置>从库SlaveSlave_IO_Running: YesSlave_SQL_Running: Yes 四、测试至此&am…

【虫洞攻击检测】使用多层神经网络的移动自组织网络中的虫洞攻击检测研究(Matlab代码实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…

【Redis实践篇】使用Redisson 优雅实现项目实践过程中的5种场景

文章目录 1.前言2.使用方式1. 添加Redisson依赖:2. 配置Redis连接信息3. 使用场景3.1. 分布式锁3.2. 限流器(Rate Limiter)3.3. 可过期的对象(Expirable Object)3.4. 信号量(Semaphore)3.5. 分布…

一百五十五、Kettle——Linux上安装的kettle9.3连接MySQL数据库

一、目的 kettle9.3在Linux上成功安装后,就建立数据库连接,第一个就是MySQL数据库 二、前提准备 提前准备好MySQL驱动包 (一)MySQL版本 (二)注意:由于我的MySQL版本比较高,所以特…

应急响应-钓鱼邮件的处理思路溯源及其反制

0x00 钓鱼邮件的危害 1.窃取用户敏感信息,制作虚假网址,诱导用户输入敏感的账户信息后记录 2.携带病毒木马程序,诱导安装,使电脑中病毒木马等 3.挖矿病毒的传输,勒索病毒的传输等等 0x01 有指纹的钓鱼邮件的溯源处理…

numba 入门示例

一维向量求和: C A B 在有nv 近几年gpu的ubuntu 机器上, 环境预备: conda create -name numba_cuda_python3.10 python3.10 conda activate numba_cuda_python3.10conda install numba conda install cudatoolkit conda install -c nvi…

Nginx安装及Minio集群反向动态代理配置(二)

安装所需插件 1、安装gcc gcc是linux下的编译器在此不多做解释,感兴趣的小伙伴可以去查一下相关资料,它可以编译 C,C,Ada,Object C和Java等语言 命令:查看gcc版本 [rootwww ~]# gcc -v -bash: gcc: 未找到命令 说明没有安装: 那就直接yu…

猿辅导《暑假一本通》:28天科学规划,帮助孩子保持学习状态

一直以来,有效利用寒、暑假期查漏补缺、解决偏科问题、初步养成好的自主学习习惯等是很多家长对学生的期望。但当前市面上教辅品类繁多,内容质量却参差不齐。据北京开卷统计数据显示,2022年前三季度零售市场上的教辅图书超过8000种&#xff0…

DevOps系列文章 之 SpringBoot整合GitLab-CI实现持续集成

在企业开发过程中,我们开发的功能或者是修复的BUG都需要部署到服务器上去,而这部分部署操作又是重复且繁琐的工作,GitLab-CI 持续集成为我们解决了这一痛点,将重复部署的工作自动化,大大的节省了程序员们的宝贵时间。本…