Java内存区域介绍以及JDK1.8内存变化

简介: Java内存区域介绍以及JDK1.8内存变化

Java内存区域介绍以及JDK1.8内存变化

运行数据区域–>JDK1.8

1、程序计数器(Program Counter Register )

Java虚拟机在在执行Java程序的过程中会把他所管理的内存划分为若干个不同的数据。Java虚拟机所管理的内存将会包括以下几个运行时数据存储区域;

image-20220728195713848.png


程序计数器(Program CounterRegister) 是一块较小的内存空间,它的作用可以看做是当前线程所执行的字节码的行号指示器。在虚拟机的概念模型里, 字节码解释器工作时就是通过改变这个计数器的值来选去下一跳需要执行的字节码指令, 分支, 循环, 跳转, 异常处理,线程恢复等基础功能都需要依赖这个计数器来完。

由于Java虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的, 在任何一个确定的时刻, 一个处理器(对于多核处理器来说是一个内核) 只会执行一条线程中的指令。 因此, 为了线程切换后能恢复到正确的执行位置, 每条线程都需要有一个独立的程序计数器, 各条线程之间的计数器互不影响, 独立存储, 我们称这类内存区域为"线程私有内存"。

如果线程正在执行的是一个Java方法, 这个计数器记录的是正在执行的虚拟机字节码指令的地址; 如果正在执行的是Native方法, 这个计数器值则为空(Undefined)。此内存区域是唯一一个在Java虚拟机规范中没有规定任何OutOfMemoryError情况的区域。

2、Java虚拟机栈

与程序计数器一样,Java虚拟机栈(Java Virtual Machine Stacks) 也是线程私有的,它的生命周期与线程相同。虚拟机栈描述的是Java方法执行的内存模型 : 每个方法执行的时候都会创建一个方法栈帧,如下图用于存储 局部变量表, 操作栈, 动态链接, 方法出口等信息. 每一个方法被调用直至执行完成的过程, 就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程.

局部变量表存放了编译器可知的各种基本数据类型(int ,short,long,byte,long,float,double,boolean,char),对象引用(reference类型, 它不等同于对象本身, 根据不同的虚拟机实现, 他可能是一个指向对象起始地址的引用指针, 也可能指向一个代表对象的句柄或者其他与此对象相关的位置)和returnAddress类型(指向了一条字节码指令的地址)。

其中64位长度的long和double类型的数据会占用2个局部变量空间(Slot), 其余的数据类型只占用一个, 局部变量表所需的内存空间在编译期间完成分配, 当进入一个方法时, 这个方法需要在帧中分配多大的局部变量空间是完全确定的, 在方法运行期间不会改变局部变量表的大小。

如果线程请求的栈深度大于虚拟机所允许的深度, 将抛出StackOverflowError异常; 如果虚拟机栈可以动态扩展(当前大部分Java虚拟机都可动态拓展,只不过Java虚拟机规范中也允许固定长度的虚拟机栈),当拓展时无法申请到足够的内存时会抛出OutOfMemoryError异常。


f9de4af04b87810729a310b2ddad882d.png

3、本地方法栈

本地方法栈和虚拟机栈发挥的作用十分相似。同样线程是私有的,他们之间的区别是Java虚拟机为Java方法服务,而本地方法栈为虚拟机使用的Native方法服务。在JVM规范中,并没有对本地方发展的具体实现方法以及数据结构作强制规定,虚拟机可以自由实现它。在HotSopt虚拟机中直接就把本地方法栈和Java栈合二为一。与虚拟机栈一样,本地方法栈也会抛出StackOverflowError 异常和OutOfMemoryError 异常。


4、Java堆


d3c87aaf9c6e2743388d8fce33b8550c.png


5、方法区

方法区(Method Aera)与Java堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的信息,常量,静态变量,即编译器和变异后的代码等数据。虽然Java虚拟机规范把方法区描述为堆的一个逻辑部分, 但是它却有一个别名叫做Non-Heap非堆, 目的应该是与Java Heap 区分开来。

在JDK1.7之前HotSpot虚拟机使用永久代来实现方法区,永久代的大小在启动JVM时可以设置一个固定值(-XX:MaxPermSize),不可变;

在JDK1.7中 存储在永久代的部分数据就已经转移到Java Heap或者Native memory。譬如符号引用(Symbols)转移到了native memory,原本存放在永久代的字符常量池移出。但永久代仍存在于JDK 1.7中,并没有完全移除。

JDK1.8中进行了较大改动

移除了永久代(PermGen),替换云空间(MetaSpace)。

永久代中的 class metadata 转移到了 native memory(本地内存,而不是虚拟机);

永久代中的 interned Strings 和 class static variables 转移到了 Java heap;

永久代参数 (PermSize MaxPermSize) -> 元空间参数(MetaspaceSize MaxMetaspaceSize)

6、常量池

运行时常量池(Runtime Constant Pool) 是方法区的一部分(虚拟机规范)。 Class文件中除了有类的版本, 字段,方法, 接口等描述信息外, 还有一项信息是常量池(Constant Pool Table), 用于存放编译期生成的各种字面量和符号引用, 这部分内容将在类加载后存放到方法区的运行时常中。

运行时常量池相对于Class文件常量池的另外一个重要特征是具备动态性, Java语言并不要求常量一定只能在编译期产生, 也就是并非预置入Class文件中常量池的内容才能进入方法区运行时常量池, 运行期间也可能将新的常量放入池中, 这种特性被开发人员利用的比较多的便是String类的intern() 方法。

7、直接内存

在JDK1.4 中新加入的NIO 类,引入了一种基于通道(Channel)和缓冲区(Buffer)的I/O 形式,他可以使用Native 函数直接分配堆外内存,然后通过一个存储在Java 堆中的DirectByteBuffer 对象作为这块内存的引用进行操作。这样能在一些场所显著提高性能,因为避免了在Java 堆和Native 堆中来回复制数据。

直接内存(Direct Memory) 并不是虚拟机运行时数据区的一部分, 也不是Java虚拟机规范中定义的内存区域, 但是这部分内存也被频繁地使用, 而且也可能导致OutOfMemoryError异常出现。 显然, 本机直接内存的分配不会受到Java堆大小的限制, 但是, 既然是内存, 则肯定还是会受到本机总内存的大小及处理器寻址空间的限制。 服务器管理员配置虚拟机参数时, 一般会根据实际内存-Xmx等参数信息, 但经常会忽略到直接内存, 使得各个内存区域的总和大于物理内存限制(包括物理上的和操作系统级的限制), 从而导致动态扩展时出现OutOfMemoryError异常。


目录
相关文章
|
11天前
|
安全 Java 应用服务中间件
Spring Boot + Java 21:内存减少 60%,启动速度提高 30% — 零代码
通过调整三个JVM和Spring Boot配置开关,无需重写代码即可显著优化Java应用性能:内存减少60%,启动速度提升30%。适用于所有在JVM上运行API的生产团队,低成本实现高效能。
87 3
|
2月前
|
存储 缓存 Java
Java数组全解析:一维、多维与内存模型
本文深入解析Java数组的内存布局与操作技巧,涵盖一维及多维数组的声明、初始化、内存模型,以及数组常见陷阱和性能优化。通过图文结合的方式帮助开发者彻底理解数组本质,并提供Arrays工具类的实用方法与面试高频问题解析,助你掌握数组核心知识,避免常见错误。
|
1月前
|
缓存 监控 Kubernetes
Java虚拟机内存溢出(Java Heap Space)问题处理方案
综上所述, 解决Java Heap Space溢出需从多角度综合施策; 包括但不限于配置调整、代码审查与优化以及系统设计层面改进; 同样也不能忽视运行期监控与预警设置之重要性; 及早发现潜在风险点并采取相应补救手段至关重要.
197 17
|
5月前
|
存储 缓存 Java
【高薪程序员必看】万字长文拆解Java并发编程!(5):深入理解JMM:Java内存模型的三大特性与volatile底层原理
JMM,Java Memory Model,Java内存模型,定义了主内存,工作内存,确保Java在不同平台上的正确运行主内存Main Memory:所有线程共享的内存区域,所有的变量都存储在主存中工作内存Working Memory:每个线程拥有自己的工作内存,用于保存变量的副本.线程执行过程中先将主内存中的变量读到工作内存中,对变量进行操作之后再将变量写入主内存,jvm概念说明主内存所有线程共享的内存区域,存储原始变量(堆内存中的对象实例和静态变量)工作内存。
163 0
|
2月前
|
监控 Kubernetes Java
最新技术栈驱动的 Java 绿色计算与性能优化实操指南涵盖内存优化与能效提升实战技巧
本文介绍了基于Java 24+技术栈的绿色计算与性能优化实操指南。主要内容包括:1)JVM调优,如分代ZGC配置和结构化并发优化;2)代码级优化,包括向量API加速数据处理和零拷贝I/O;3)容器化环境优化,如K8s资源匹配和节能模式配置;4)监控分析工具使用。通过实践表明,这些优化能显著提升性能(响应时间降低40-60%)同时降低资源消耗(内存减少30-50%,CPU降低20-40%)和能耗(服务器功耗减少15-35%)。建议采用渐进式优化策略。
134 1
|
2月前
|
存储 监控 算法
Java垃圾回收机制(GC)与内存模型
本文主要讲述JVM的内存模型和基本调优机制。
|
2月前
|
安全 Oracle Java
JAVA高级开发必备·卓伊凡详细JDK、JRE、JVM与Java生态深度解析-形象比喻系统理解-优雅草卓伊凡
JAVA高级开发必备·卓伊凡详细JDK、JRE、JVM与Java生态深度解析-形象比喻系统理解-优雅草卓伊凡
199 0
JAVA高级开发必备·卓伊凡详细JDK、JRE、JVM与Java生态深度解析-形象比喻系统理解-优雅草卓伊凡
|
3月前
|
安全 Java 微服务
Java 最新技术和框架实操:涵盖 JDK 21 新特性与 Spring Security 6.x 安全框架搭建
本文系统整理了Java最新技术与主流框架实操内容,涵盖Java 17+新特性(如模式匹配、文本块、记录类)、Spring Boot 3微服务开发、响应式编程(WebFlux)、容器化部署(Docker+K8s)、测试与CI/CD实践,附完整代码示例和学习资源推荐,助你构建现代Java全栈开发能力。
395 0
|
4月前
|
Java 物联网 数据处理
Java Solon v3.2.0 史上最强性能优化版本发布 并发能力提升 700% 内存占用节省 50%
Java Solon v3.2.0 是一款性能卓越的后端开发框架,新版本并发性能提升700%,内存占用节省50%。本文将从核心特性(如事件驱动模型与内存优化)、技术方案示例(Web应用搭建与数据库集成)到实际应用案例(电商平台与物联网平台)全面解析其优势与使用方法。通过简单代码示例和真实场景展示,帮助开发者快速掌握并应用于项目中,大幅提升系统性能与资源利用率。
127 6
Java Solon v3.2.0 史上最强性能优化版本发布 并发能力提升 700% 内存占用节省 50%

热门文章

最新文章