【JVM】内存模型

文章目录

  • 内存模型的基本概念
    • 案例
  • 程序计数器
    • `Java`虚拟机栈
      • 局部变量表
        • 栈帧中局部变量表的实际状态
        • 栈帧中存放的数据有哪些
      • 操作数栈
      • 帧数据
    • 本地方法栈
    • 堆空间是如何进行管理的?
  • 方法区
    • 静态变量存储
  • 直接内存
    • 直接内存的作用

内存模型的基本概念

在前面的学习中,我们知道了字节码文件(.class)会通过类加载器加载JVM虚拟机中,接下来JVM虚拟机就会执行其中的字节码指令.我们把JVM虚拟机被分配的内存叫做运行时数据区域
内存模型就是指运行时数据区域中被划分的不同区域.
JDK6版本:
在这里插入图片描述字符串常量池存放在方法区中,方法区存放在堆中;
JDK1.7版本:
在这里插入图片描述

  • 方法区脱离堆,单独占用一部分内存

  • 字符串常量池依旧存储在堆中
    JDK1.8版本:
    在这里插入图片描述

  • 方法区发生移动,从JVM虚拟机内存中,移动到本地内存中

Java虚拟机(JVM)的内存模型是Java程序运行时内存管理的基础。它定义了Java程序如何在内存中分配、使用和回收资源

案例

class Person{

    int id;
    String name;
    public Person(int id,String name){
        this.id=id;
        this.name=name;
    }
}
public class JvmTest {
    public void func1(int a){
        int b=10;
        Person p=new Person(1,"张三");
        a=11;
    }

    public static void main(String[] args) {
        int a=10;
        new JvmTest().func1(a);
        System.out.println(a);

    }
}

在这里插入图片描述

程序计数器

  1. 控制程序解释执行指令的顺序.在代码执行过程中,程序计数器会记录下一行字节码指令的地址.执行完当前指令之后,虚拟机的执行引擎根据程序计数器执行下一行指令.程序计数器可以控制程序指令的进行,实现分治,跳转或者异常等等逻辑
  2. 保证在多线程的情况下线程之间的切换.JVM虚拟机需要通过程序计数器记录CPU切换前解释执行到哪一行指令并继续解释运行

程序计数器会不会发生内存溢出?
内存溢出:程序在使用某一块内存区域时,存放的数据需要占用的内存大小超过了虚拟机能够提供的内存上限
程序计数器不会发生内存溢出的情况.原因:每个程序计数器只会存储一个固定长度的内存地址,也就是字节码指令的内存地址.

Java虚拟机栈

保存在java中实现的方法
采用的数据结构来管理方法调用中的基本数据,先进后出,每一个方法的调用使用一个栈帧来保存.
Java虚拟机栈随着线程的创建而创建,随着线程的结束而销毁
在每一个栈帧中,存放的内容有:局部变量表,操作数栈,帧数据
在这里插入图片描述

局部变量表

在方法执行过程中存放所有的局部变量,编译成字节码文件时,就可以确定局部变量表的内容
在这里插入图片描述

栈帧中局部变量表的实际状态

栈帧中的局部变量表是一个数组,数组中的每一个位置称之为,longdouble类型占用两个槽,其他类型占用一个槽.
在这里插入图片描述

栈帧中存放的数据有哪些
  • 实例方法中的序号为0的位置存放的是this,指的是当前调用方法的实例对象,运行时会在内存中存放实例对象的地址
  • 方法参数也会保存在局部变量表中,其顺序与方法中参数定义的顺序一致

局部变量表保存的内容有:

  • 实例方法的this对象
  • 方法的参数
  • 方法体声明的局部变量

为了节省空间,局部变量表中的槽是可以复用的,一旦某个局部变量不再生效,当前槽就可以再次被使用

操作数栈

操作数栈是栈帧中虚拟机执行指令过程中用来存放临时数据的一块区域

  • 操作数栈是栈帧中虚拟机在执行指令的过程中用来存放中间数据的一块区域.他是一种栈式的数据结构,如果一条指令将一个值压入操作数栈,则后面的指令可以弹出并使用该值.

比如:在字节码指令执行的过程中,会产生一些临时数据,这些临时数据会先存放到操作数栈中,然后再通过下一条指令放入到局部变量表中

  • 在编译期就可以确定操作数栈的最大深度,从而执行时正确的分配内存大小

帧数据

(这个并不是由虚拟机设定标准)
帧数据主要包含动态链接,方法出口,异常表引用

  • 动态链接:当前类的字节码指令引用了其他类的属性或者方法时,需要将符号引用(编号)转换成对应的运行时常量池中的内存地址.动态链接就保存了编号到运行时常量池的内存地址的映射关系.
    在这里插入图片描述

  • 方法出口:方法在正确或者异常结束时,当前栈帧会被弹出,同时程序计数器应该指向上一个栈帧中的下一条指令的地址.所以在当前栈帧中,需要存储此方法出口的地址.

  • 异常表:存放的是代码中异常的处理信息,包含了异常捕获的生效范围以及异常发生后跳转到的字节码指令位置.

Java虚拟机栈是否会出现栈内存溢出?

  • Java虚拟机栈如果栈帧过多,占用内存超过栈内存可以分配的最大容量,就会出现栈溢出(虚拟机为每一个线程分配的栈的大小是有限的)
  • Java虚拟机栈内存溢出时会出现StackOverflowError的错误

本地方法栈

保存的是在java中实现的使用native修饰的,实际是由C++编写的本地方法

  • Java虚拟机栈存储了Java方法调用时的栈帧,而本地方法栈存储的是native本地方法的栈帧.
  • HotSpot虚拟机中,Java虚拟机栈和本地方法栈实现上使用了同一个栈空间.本地方法栈在栈内存上生成一个栈帧,临时保存方法的参数同时方便出现异常时也把本地方法的栈信息打印出来.
    在这里插入图片描述

一般Java程序中堆内存是空间最大的一块内存区域.创建出来的对象都存在于堆上
Java 堆是所有线程共享的一块内存,在虚拟机启动时创建,几乎所有的对象实例都存放在这里,是垃圾收集器管理的主要区域
栈上的局部变量表中,可以存放堆上对象的引用.静态变量也可以存放堆对象的引用,通过静态变量就可以实现对象在线程之间的共享.
在这里插入图片描述

堆内存是否会出现溢出?
堆内存大小是有上限的,当对象一直向堆中放入对象达到上限之后,就会抛出OutOfMemory错误

堆空间是如何进行管理的?

堆空间有三个需要关注的值:uesd,total,max

  • used指的是当前已经使用的堆内存;
  • totaljava虚拟机已经分配可用堆内存;
  • maxjava虚拟机可以分配的最大堆的内存
    在这里插入图片描述

随着堆中对象增多,当total可以使用的内存即将不足的时候,虚拟机会继续分配内存给堆,扩展total的大小

  • 如果堆内存不足,java虚拟机就会不断地分配内存,total值会变大.
  • 是不是当used=total=max,就会导致内存溢出?
    答案:不一定

在实际应用中一般都需要设置totalmax的值

  • 要修改堆的大小,可以使用虚拟机参数-Xmx(max最大值)和-Xms(初始的total)
    • 语法:-Xmx值,-Xms
    • 单位:字节(默认,必须是1024倍数),K或者k(KB),m或者M(MB),g或者G(GB)
    • 限制:Xmx必须大于2MB,Xms必须大于1MB

Java服务端程序开发的时候,建议将-Xmx-Xms设置为相同的值(total=max),这样在程序启动之后可使用的总内存就是最大内存,而无需向Java虚拟机再次申请,减少了申请并分配内存时间上的开销,同时也不会出现内存过剩之后堆收缩的情况

方法区

方法区是存放每个类基础信息的位置,线程共享,主要包含三部分内容:

  • 类的元信息:每个类的基本信息
    一般称之为InstanceKlass对象.在类加载阶段完成
    在这里插入图片描述
  • 运行时常量池
    • 常量池中存放的是字节码中的常量池内容
    • 字节码文件中通过编号查表的方式找到常量,这种常量池称之为静态常量池
    • 常量池加载到内存中之后,可以通过内存地址快速的定位到常量池中的内容,这种常量池称之为运行时常量池.
      在这里插入图片描述
    • 字符串常量池:保存了字符串常量
      字符串常量池存储在代码中定义的常量字符串内容.比如:"123",这个123就会被放入字符串常量池
      在这里插入图片描述
      这里我们再来举个例子加深印象:
      举例1:
public class StringTest {
    public static void main(String[] args) {
        String a="1";
        String b="2";
        String c="12";
        String d=a+b;
        System.out.println(c==d);
    }
}

这里的运行结果就代表了我们的d是存放在字符创常量池中还是堆内存中.
运行结果false,原因如下:
在这里插入图片描述
举例2:

public class StringTest {
    public static void main(String[] args) {
        String a="1";
        String b="2";
        String c="12";
        String d="1"+"2";
        System.out.println(c==d);
    }
}

运行结果是:true,为什么?
我们来观察一下此时的字节码指令状态:
在这里插入图片描述
所以,此处d存放在常量池中的原因是:这里并没有使用StringBuilder对象来进行字符串的相加,而是直接使用的ldc字节码指令进行的,没有使用对象,所以就不需要存放在

静态变量存储

  • JDK7之前的版本中,静态变量是存放在方法区中的,也就是永久代
  • JDK7及其之后的版本中,静态变量时存放在堆中的Class对象中,脱离了永久代

直接内存

首先我们要确定的是,直接内存并不属于Java运行时的内存区域.
JDK1.4中引入了NIO机制,使用了直接内存,主要为了解决以下两个问题:

  • Java堆中的对象如果不再使用要回收,回收时会影响对象的创建和使用(可能会出现卡顿的现象)
  • IO操作比如读文件,需要先把文件读入直接内存中,再把数据复制到Java堆中.
    现在放入直接放入到直接内存中即可,同时在Java堆上维护直接内存的引用,减少了数据复制的开销.写文件也是这种思路.
    在这里插入图片描述

直接内存的作用

  • 提高读写文件的性能
  • 避免垃圾回收机制影响对象的创建和使用
  • 在`JDK1.78即之后存放方法区

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

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

相关文章

论文笔记:Pre-training to Match for Unified Low-shot Relation Extraction

论文来源:ACL 2022 论文地址:https://aclanthology.org/2022.acl-long.397.pdf 论文代码:https://github.com/fc-liu/MCMN (笔记不易,请勿恶意转载抄袭!!!) 目录 A…

从头预训练一只迷你 LLaMA 3_llama3 预训练预处理

我将向你展示如何使用 LLama 3.1(一个本地运行的模型)来执行GraphRAG操作,总共就50号代码。。。 首先,什么是GraphRAG?GraphRAG是一种通过考虑实体和文档之间的关系来执行检索增强生成的方式,关键概念是节…

Elasticsearch学习笔记(七)安装并配置Metricbeat

Metricbeat 是一个轻量级的开源数据采集器,专门用于收集操作系统和服务的指标(metrics)。它是 Elastic Stack(即 ELK Stack)的一部分,通常用于监控系统性能、收集应用程序和服务器的性能指标,并…

【大模型】AI视频课程制作工具开发

1. 需求信息 1.1 需求背景 讲师们在制作视频的过程中,发现录制课程比较麻烦,要保证环境安静,保证录制过程不出错,很容易反复重复录制,为了解决重复录制的工作量,想通过 ai 课程制作工具,来解决…

字节跳动青训营——入营考核解答(持续更新中~~~)

考核内容: 在指定的题库中自主选择不少于 15 道算法题并完成解题,其中题目难度分配如下: 简单题不少于 10 道中等题不少于 4 道困难题不少于 1 道 解答代码 5.简单四则运算 (中) 代码实现: import ja…

TON(六)——fift算法,注释的改写

系列文章目录 TON(五) TON(四) TON(三) TON(二) TON(一) 前言 fift是一门十分强大的栈编程语言,,在TON中它是由c编译而成的语言…

WordPress官方发布“新”插件“SCF”(安全自定义字段)

安全自定义字段 (SCF) 为您提供了处理数据所需的所有工具,从而将 WordPress 网站转变为成熟的内容管理系统。 使用 SCF 插件可以完全控制您的 WordPress 编辑屏幕、自定义字段数据等。 按需添加字段—SCF字段生成器允许您快速轻松地将字段添加到 WP 编辑屏幕&…

第一个servlet程序

文章目录 在原有工程上建立模块前端配置前后端映射关系添加外部依赖库后端代码启动配置 在原有工程上建立模块 添加web框架 前端 应用结构 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>第一…

什么是SYN flood,如何处理

在数字化时代&#xff0c;随着互联网的普及和技术的飞速发展&#xff0c;网络安全问题变得日益严峻。Flood攻击&#xff0c;作为一种典型的网络攻击手段&#xff0c;对个人和企业的信息安全构成了重大威胁。通过深入了解Flood攻击的概念、特点、影响及解决方案&#xff0c;我们…

SpringSecurity源码分析以及如何解决前后端分离出现的跨域问题

解决Security前后端分离出现的跨域问题 一. Security源码分析 首先在看源码之前我们先来看这张图 , 这张图展示了Security执行的全部流程 从上图可知Security执行的入口是UsernamePasswordAuthenticationFilter这个抽象类 , 那我们就先从该类进行分析 1. UsernamePasswordAu…

【智慧大屏】BI智慧大屏,大屏可视化解决方案(word原件)

1.系统概述 1.1.需求分析 1.2.重难点分析 1.3.重难点解决措施 2.系统架构设计 2.1.系统架构图 2.2.关键技术 2.3.接口及要求 3.系统功能设计 3.1.功能清单列表 3.2.数据源管理 3.3.数据集管理 3.4.视图管理 3.5.仪表盘管理 3.6.移动端设计 3.1.系统权限设计 3.…

Scala入门基础(12)抽象类

抽象类&#xff0c;制定标准&#xff0c;不要求去具体实现 包含了抽象方法的类就是抽象类。抽象方法只是有方法名&#xff0c;没有具体方法体的方法 定义抽象类要用abstract&#xff08;抽象&#xff09;关键字 用智能驾驶技术举例&#xff1a;演示&#xff09…

深入理解WPF中的命令机制

Windows Presentation Foundation&#xff08;WPF&#xff09;是微软推出的一种用于构建桌面客户端应用程序的技术。它被认为是现代Windows应用程序的基础&#xff0c;具有强大的图形和媒体处理能力。在WPF中&#xff0c;“命令”是一个重要的概念&#xff0c;它为应用程序开发…

2024.10月11日--- SpringMVC拦截器

拦截器 1 回顾过滤器&#xff1a; Servlet规范中的三大接口&#xff1a;Servlet接口&#xff0c;Filter接口、Listener接口。 过滤器接口&#xff0c;是Servlet2.3版本以来&#xff0c;定义的一种小型的&#xff0c;可插拔的Web组件&#xff0c;可以用来拦截和处理Servlet容…

力扣 142.环形链表Ⅱ【详细解释】

一、题目 二、思路 三、代码 /*** Definition for singly-linked list.* class ListNode {* int val;* ListNode next;* ListNode(int x) {* val x;* next null;* }* }*/ public class Solution {public ListNode detectCycle(ListNode hea…

LSL常见应用场景及示例<一>

目录 往期推荐 场景1&#xff1a;如何在指定内存定义中定位一个函数&#xff1f; 场景2&#xff1a;如何在绝对内存偏移地址处定位一个函数&#xff1f; 场景3&#xff1a;如何在绝对地址处定位一个函数&#xff1f; 场景4&#xff1a;有多个函数必须位于特定的内存定义中。…

vue3+ts+vite--路由跳转,params传参好像丢失了?

前言 相信大家一定写过后台管理系统&#xff0c;有一个很普遍的功能&#xff0c;就是点击编辑&#xff0c;根据id&#xff0c;跳转到相对应的编辑页面&#xff0c;id是通过路由params传递过去了&#xff0c;但是还有一个需求是要将父组件的名称也传递过去 &#xff0c;过程特别…

从0到1封装一个image/pdf预览组件

iShot_2024-10-14_16.47.10 目录结构 content.vue <template><div class"no-content-block"><i class"iconfont icondocument large-file" /><div class"text-wrapper">{{ t(__ui__.siPreview.previewSupported) }}<…

Spring Cloud Sentinel配置

Spring Cloud Sentinel 文章目录 Spring Cloud Sentinel1. Sentinel Dashboard 启动2. Spring Cloud 客户端配置3. Sentinel Dashboard 限流配置流控模式直连关联链路 流控规则快速失败Warm Up排队等待 4. Sentinel Dashboard 熔断配置5. Sentinel Dashboard 热点配置 1. Senti…

MEMC功能详解

文章目录 MEMC的工作原理&#xff1a;优点&#xff1a;缺点&#xff1a;适用场景&#xff1a;1. Deblur&#xff08;去模糊&#xff09;2. Dejudder&#xff08;去抖动&#xff09;总结两者区别&#xff1a; MEMC&#xff08;Motion Estimation and Motion Compensation&#x…