Java内存模型

article/2025/10/5 18:55:07

Java内存模型

    • 1.内存模型概念图
    • 2.线程共享区
    • 方法区
      • 常量池
        • 运行时常量池
        • 全局字符串池
        • class文件常量池
    • 堆空间
    • 3.线程独占区
      • 虚拟机栈
      • 本地方法栈
      • 程序计数器
    • 4.对象的创建

1.内存模型概念图

在这里插入图片描述

2.线程共享区

方法区

方法区也是线程共享区用于储存虚拟机加载的类信息(类的版本、字段、方法、接口),常量,静态变量,即时编译后的代码等数据
方法区逻辑上属于堆的一部分,但是与堆进行了区分,通常又叫非堆
HotSpot虚拟机使用永久代来实现方法区,使得HotSpot虚拟机的垃圾收集器可以像管理内存一样管理这部分内存,能省去专门为方法区专门为方法区编写内存管理代码工作,所有开发者喜欢将方法区称为永久代本质两者并不等价对于其虚拟机来说不存在永久代的概念
方法区可以选择不实现垃圾收集,一般来说这个区域对于内存回收的条件比较苛刻,但是这部分区域的回收确实是必要的
当方法区无法满足内存分配需求时,将会抛出OutOfMemoryError异常

常量池

运行时常量池

   1.    运行时常量池是方法区的一部分1 .1  Class文件除了有类的版本、字段、方法、接口等描述信息外,还有一项信息就是常量池,用于存放编译器生成的各种字面量和符号引用,这部分内容在类加载后加入方法区运行时常量池存放1. 2  运行时常量相当于class文件中的常量池有所不同的其具备了动态性,class文件中常量池中的常量在编译期间就定义好了,而运行时常量池在程序运行期间也可以将常量加入该常量中,最常见的方法就是调用string类的intern()方法

全局字符串池

 全局字符串池的内容是在类加载完成,经过验证,准备阶段之后在堆中生成字符串对象实例,然后该字符串对象实例的引用存到String pool中(记住:String pool中存的时引用值而不是具体的实例对象、具体的实例对象是在堆中开辟了一块空间存放的。)在HotSpot VM里实现的String  pool功能的是一个StringTable类,他是一个哈希表,里面存的是驻留字符串(也就是我们常说的用双引号括起来的)的引用(而不是字符串实例本身),也就是说在堆中的某些字符串实例被这个StringTable引用之后就等用被赋予了“驻留字符串”的身份。这个StringTable 在每个hotshot vm的实例只有一份,被所有类共享。

class文件常量池

我们都知道,class文件中除了包含类的版本、字段、方法、接口、等描述信息外、还有一项信息就是常量池(Constant pool table)用于存放编译器生成的各种字面量和符号引用,字面量就是我们所说的常量概念,如文本字符串、被声明为final的常量值等,符号引用时一组符号来描述所引用的目标,符号可以时任何形式的字面量只要使用时无歧义的定位到目标位置就行(它与直接引用区分一下,直接引用一般时指方法区的本地指针,相对偏移量或时一个能简介定位搭配目标的句柄)一般包括三类常量
类和接口的全限定名
字段的名称和描述符
方法的名称和描述符

举个实例来说明一下:

String str1 = "abc"; String str2 = new String("def"); String str3 = "abc"; String str4 = str2.intern(); String str5 = "def"; System.out.println(str1 == str3);//true System.out.println(str2 == str4);//false System.out.println(str4 == str5);//true

1 2 3 4 5 6 7 8

   上面程序的首先经过编译之后,在1.该类的class常量池中存放一些符号引用,2.然后类加载之后,将class常量池中存放的符号引用转存到运行时常量池中,3.然后经过验证,准备阶段之后,在堆中生成驻留字符串的实例对象(也就是上例中str1所指向的”abc”实例对象),4.然后将这个对象的引用存到全局String Pool中,也就是StringTable中,5.最后在解析阶段,要把运行时常量池中的符号引用替换成直接引用,那么就直接查询StringTable,保证StringTable里的引用值与运行时常量池中的引用值一致,大概整个过程就是这样了。(先存放类的符号引用(类名 描述符等)之类的东西然后类加载之后把这些东西存放在运行时常量池  然后在堆中生成实例  然后把对象的引用值存在字符串常量池中 然后解析阶段把,要把运行时常量池中的符号引用替换成直接引用)回到上面的那个程序,现在就很容易解释整个程序的内存分配过程了,首先,在堆中会有一个”abc”实例,全局StringTable中存放着”abc”的一个引用值,然后在运行第二句的时候会生成两个实例,一个是”def”的实例对象,并且StringTable中存储一个”def”的引用值,还有一个是new出来的一个”def”的实例对象,与上面那个是不同的实例,当在解析str3的时候查找StringTable,里面有”abc”的全局驻留字符串引用,所以str3的引用地址与之前的那个已存在的相同,str4是在运行的时候调用intern()函数,返回StringTable中”def”的引用值,如果没有就将str2的引用值添加进去,在这里,StringTable中已经有了”def”的引用值了,所以返回上面在new str2的时候添加到StringTable中的 “def”引用值,最后str5在解析的时候就也是指向存在于StringTable中的”def”的引用值,那么这样一分析之后,下面三个打印的值就容易理解了。

堆空间

JVM管理的最大以快内存区域,存放着内存实例是线程共享区
堆是垃圾收集器管理的主要区域,因此称为GC堆
JAVA堆的分类
3.1 从内存的回收的角度上看,可以分为新生代(Eden空间,From Survivor 空间, To Survivor空间)及老年代(Tenured Gen)
3.2 从内存分配的角度上看,为了解决分配内存的线程安全性问题,线程共享的JAVA堆中可能划分楚多个线程私有的分配缓冲区(TLAB)
JAVA堆可以处于物理上不连续的内存空间中,只要逻辑上连续即可。
可以通过参数Xms-Xms 来指定运行时堆内存的大小 堆内存空间不足也会抛OutOfMemoryError异常。

3.线程独占区

虚拟机栈

每个线程都有一个私有的栈,随者线程的创建而创建,生命周期与线程相同
虚拟机栈里面存着一种叫做“栈帧”的东西,每个方法都会创建一个栈帧,栈帧中存放了局部变量表,操作数栈、动态链接、方法出口等信息
2.1 局部变量表存放了编译期可知的各种基本数据类型和对象引用类型,通常我们所说的栈内存指的就是局部变量表这一部分
在这里插入图片描述
2.2 64位的long和double类型的数据会占用2各局部变量的空间,其余的数据类型只占用1个
2.3局部变量表所需的内存空间在编译器完成分配,当进入一个方法时,这个方法需要在帧分配多少内存是固定的,运行的期间不会改变局部变量表的大小
方法的调用到执行完毕,对应的就是栈帧的入栈和出栈的过程
栈的大小可以固定也可以动态扩展
4.1固定大小的情况下,当栈调用深度大于jvm所允许的范围,会抛出StackOverFlowError异常
4.2在动态扩展的情况下,若扩展时无法申请到足够的内存,会抛出OutOfMemoryError
5.栈内存溢出模拟

public class MainTest {public static void main(String[] args){new MainTest().test();}private void test() {System.out.println("run...");test();}} 	

报错如下

Exception in thread "main" java.lang.StackOverflowErrorat sun.nio.cs.UTF_8$Encoder.encodeLoop(UTF_8.java:691)at java.nio.charset.CharsetEncoder.encode(CharsetEncoder.java:579)

图例:
在这里插入图片描述

本地方法栈

1.和虚拟机栈类似,两者的区别就是虚拟机栈为虚拟机执行java方法服务,本地方法为虚拟机执行native方法服务
2.hotShot虚拟机不区分虚拟机栈和本地方法栈,两者是一块
3.与虚拟机栈一样,已本地方法栈也会抛出StackOverflowError和OutOfMemoryEorr异常

程序计数器

1.程序计数器是一块较小的空间,他可以看作当前线程所执行的字节码的行号指示器
在这里插入图片描述
2.如果线程执行的是java方法,这个计数器记录的是正在执行虚拟机字节码指令的地址(可以理解为上图所示的行号),如果正在执行的是native(本地方法:操作系统的方法)这个计数器的值为under fined
3.JVM的多线程是通过线程轮流切换并分配CPU执行时间片的方式来实现的,任何一个时刻,一个CPU只会执行一条线程中的指令。为了保证线程切换后能恢复到正常的执行位置,每条线程都需要有一个独立的程序计数器,各线程中独立储存,互不影响。
4.此区域是唯一一个再java虚拟机规范中没有规定任何OutOfMemoryError情况的区域,因为程序计数器是由虚拟机内部维护的,不需要开发者进行操作

4.对象的创建

在这里插入图片描述


http://chatgpt.dhexx.cn/article/LCBjJOpJ.shtml

相关文章

一文看懂Java内存模型(JMM)

文章目录 Java内存模型介绍总览图Java内存模型图线程、主内存、工作内存关系图CPU缓存架构图Java内存模型与硬件内存架构的关系 什么是Java内存模型Java内存模型的意义Java内存模型规范 Java内存模型的主要结构1、程序计数器(Program Counter Register)2…

SPSS建立时间序列模型

原始数据可能并不是时间序列,因此,对这样的数据建立时间序列模型,分为以下几步: 1 生成时间序列:定义新的时间变量,并对原始数据进行平稳处理 a)定义时间变量: 选择按什么时间序列进行定义&am…

时间序列模型(ARIMA和ARMA)完整步骤详述

我于2019年发布此篇文章至今收获了许多人的指点,当时的代码的确晦涩难懂,近期有空,将代码重新整理了一遍,重新发送至此。希望能够帮助大家更好地理解。 建模步骤: 目录 数据包和版本申明 步骤一:数据准备…

机器学习之时间序列模型

一、时间序列概念 在生产和科学研究中,对某一个或一组变量x(t)进行观察测量,将在一系列时刻t1, t2, …, tn (t为自变量)按照时间次序排列,并用于解释变量和相互关系的数学表达式。在相等的时间间隔内收集到的不同时间点的数据集合我们称之为时…

数学建模学习笔记(十)——时间序列模型

文章目录 一、时间序列综述二、时间序列数据以及基本概念三、时间序列分解四、指数平滑模型五、一元时间序列分析的模型六、AR(p)模型七、MA(q)模型八、ARMA(p, q)模型九、模型选择:AIC 和 BIC …

时间序列模型步骤教程(ARIMA)

目录 0、前言一、数据准备&探索1、平稳性1.1 平稳性检验1.2 数据处理(平滑、变换、差分、分解)1.2.1 对数变换1.2.2 平滑法(移动平均&指数平均)1.2.3 差分法1.2.4 分解 2、非白噪声检验 二、模型(ARIMA&#x…

时间序列模型分析

目录 一个引言 定义 确定性时间序列分析方法概述 确定性时间序列模型类型 移动平均法 简单移动平均法 加权移动平均法 趋势移动平均法 指数平滑法 一次指数平滑法 1.预测模型​编辑 2.加权系数的选择​编辑 3.初始值的确定​编…

时间序列模型相关说明和模型介绍

一、什么是时间序列? 时间序列是在规律性时间间隔记录的观测值序列。依赖于观测值的频率,典型的时间序列可分为每小时、每天、每周、每月、每季度和每年为单位记录。 import pandas as pd df pd.read_csv(https://raw.githubusercontent.com/selva86/datasets/d…

常用的时间序列模型

白噪声模型 时间序列算法之ARIMA模型 对非平稳时间序列的分析方法可以分为确定性因素分解的时序分析和随机时序分析两个大类。 确定性因素分解的方法把所有序列的变化都归结为4个因素:长期趋势、季节变动、循环变动和随机波动。其中长期趋势和季节变动的规律性信息通…

数学建模之时间序列模型及其应用

摘要 时间序列模型就是将预测对象按照时间顺序排列起来,用这一组时间序列过去的变化规律,推断今后变化的可能性及变化趋势、变化规律。 时间序列模型也是一种回归模型,其一方面承认事物发展的延续性,运用过去的数据来推测事物的发展趋势;另一方面又考虑到偶然因素产生的随机性…

集成时间序列模型提高预测精度

使用Catboost从RNN、ARIMA和Prophet模型中提取信号进行预测 集成各种弱学习器可以提高预测精度,但是如果我们的模型已经很强大了,集成学习往往也能够起到锦上添花的作用。流行的机器学习库scikit-learn提供了一个StackingRegressor,可以用于…

时间序列规则和时间序列模型

1. 时间序列规则 1.1 什么是时间序列规则 对于赛题/业务的规则之前已经描述了它的重要性和应用,在此不再赘述。这章主要了解时间序列及其规则,和周期的应用。 1.1.1 时间序列 时间序列(或称动态数列):指将同一统计…

时间序列模型算法 - Prophet,LSTM(二)

时间序列模型 - Prophet 1.时间序列简介1.1 时间序列 - 平稳性检验1.1.1 log法1.1.2 差分法 1.2 平稳性的单位根检验 2.ARIMA3.Prophet3.1 Prophet的优点3.2 安装Prophet3.3 数据处理3.4 预测 4.LSTM4.1 数据处理4.2 训练预测 1.时间序列简介 在做时间序列时,首先要…

时间序列模型-ARIMA

一、ARIMA模型基本概念 1.1 自回归模型(AR) 描述当前值与历史值之间的关系,用变量自身的历史数据对自身进行预测;自回归模型必须满足平稳性的要求;(何为平稳性:见时间序列数据分析基本概念&am…

ARMA 时间序列模型

更好的理解协方差以及相关系数 ###X因素和Y因素协方差公式: 自相关系数ACF 直观上来说,ACF 描述了一个观测值和另一个观测值之间的自相关,包括直接和间接的相关性信息。 其实自相关系数可以这么理解:把一列数据按照滞后数拆成两…

时间序列模型简介

时间序列模型简介 尽管此前我们已经用到了time series这个专业名词,但我们对时序特征进行的处理,并不是time series这个专业名词所代表的真正含义,既时间序列。尽管本阶段我们并不会讲解时间序列模型,但既然讨论了时序特征&#x…

时间序列的7种预测模型

背景 时间序列问题比较常见,比如股市,工业生产指标等。 导入必要的Python包: from statsmodels.tsa.api import ExponentialSmoothing, \ SimpleExpSmoothing, Holtimport statsmodels.api as sm1. 朴素估计 y ^ t 1 y t \hat{y}_{\math…

算法模型---时间序列模型

文章来源 时间序列 时间序列是时间间隔不变的情况下收集的不同时间点数据集合,这些集合被分析用来了解长期发展趋势及为了预测未来。 时间序列与常见的回归问题的不同点在于: 1、时间序列是跟时间有关的;而线性回归模型的假设:观察结果是独立的在这种情…

ADF单位根检验三种形式_[STATA] 时间序列模型 ARIMA检验

___ ____ ____ ____ ____ (R) /__ / ____/ / ____/___/ / /___/ / /___/ 13.1 Statistics/Data Analysis 此次系列文章的主题是通过Stata软件来分析时间序列的平稳和非平稳关系,以及如何通过Stata软件来进行不同时间序列模型的预测性分析。…

机器学习——时间序列模型

文章目录 1. 基本概念1.1 自相关函数ACF(autocorrelation function)1.2 偏自相关函数PACF(partial autocorrelation function) 2. 常见模型2.1 自回归模型(AR)2.2 移动平均模型(MA)2…