0

0

JVM内存模型与运行时数据区域的详解(图文)

不言

不言

发布时间:2018-10-16 17:02:12

|

3820人浏览过

|

来源于segmentfault思否

转载

本篇文章给大家带来的内容是关于jvm内存模型与运行时数据区域的详解(图文),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

一、java内存模型

1487783328-5bc4b84f6fbd1_articlex.png

java定义内存模型的目的是:为了屏蔽各种硬件和操作系统的内存访问之间的差异。

java内存模型规定了所有的变量都存储在主内存中,每条线程拥有自己的工作内存,工作内存保存了主内存中变量的副本。

线程对变量操作只能在工作内存中进行,不能直接读写主内存的变量。

不同线程之间的变量访问需要通过主内存来完成。

1、java内存模型和java运行时数据区域的关系:主内存对应着java堆,工作内存对应着java栈。

2、volatile关键字,使得变量的更新在各个工作内存中都是实时可见的。在DCL的单例模式中有运用到

二、java运行时数据区域/内存区域

因为jvm的运行时数据区域一直在改善,所以不同jdk版本之间会有不同。

1、jdk1.7之前的jvm内存区域,拥有永久代

2014176931-5bc4b84f87394_articlex.png

1、程序计数器的作用,因为.java文件被编译成.class文件,它作为当前线程所执行的字节码的行号指示器。当字节码解释器工作时,就是通过改变这个计算器的值来选取下一条要执行的字节码指令。每条线程都有一个独立的程序计数器。

2、本地方法栈就是执行本地native方法的栈,native方法由虚拟机实现!

3、java虚拟机栈描述的是该线程执行java方法(method)时的内存模型。每一个方法都对应一个栈帧,栈帧中的局部变量表存储了方法中的基本数据类型变量、对象引用变量。

3615879256-5bc4b84f79b60_articlex.png

如上图所示,局部变量表保存了方法中声明的8种基本类型变量和对象引用变量。每一个栈帧中还有一个指向运行时常量池的引用,这是指String类型。下面有一个经典的String对象生成的面试题!

4、java堆是JVM中内存最大的一块,被所有线程共享。几乎所有的对象实例都在这里分配,所以java堆也是JVM垃圾回收的主要区域。java堆又被分成了年轻代,老年代;年轻代进一步可以划分为Eden空间,From Survivor空间、To Survivor空间。

3845570429-5bc4b84f1afc4_articlex.png

当我们使用new关键字分配对象时,就是在java堆中生成对象。

下面分析一下对象生成时的情况。

  1. 因为Eden最大,所以新生成的对象都分配到Eden空间,当Eden空间快满时,进行一次Minor GC,然后将存活的对象复制到From Survivor空间。这时,Eden空间继续向外提供堆内存。

  2. 后面继续生成的对象还是放到Eden空间,当Eden空间又要满的时候,这时候Eden空间和From Survivor空间同时进行一次Minor GC,然后把存活对象放到To Survivor空间。这时,Eden空间继续向外提供堆内存。

  3. 接下来的情况和2一致。Eden空间快满的时候,Eden空间和To Survivor空间进行一次Minor GC,然后存活的对象放到From Survivor空间。

  4. 接下来的情况和3一致。Eden空间快慢的时候,Eden空间和From Survivor空间进行一次Minor GC,然后存活的对象放到To Survivor空间。

  5. 就是说2个Survivor中的一个用来提供对象保存。当Eden空间和某一块Survivor空间GC后,另一块Survivor空间放不下GC后存活的对象;或者是连续Minor GC15次左右的情况;就把这部分存活对象放入到老年代空间。

  6. 当老年代空间也放满的时候,进行Major GC,对老年代空间进行回收。(也叫做Full GC,Full GC的内存消耗很大,应该避免)

年轻代使用的是复制算法:每次Minor GC把Eden区和一块Survivor区的存活对象复制到另一块Survivor区。老年代使用的是标记-整理算法:每次Major GC把存活对象都想内存空间的一端移动,然后直接清理掉端边界以外的内存。

大对象如数组、很长的字符串,直接进入老年代空间。

5、方法区用于存储JVM加载的类信息、final常量、static静态变量等数据,方法区中的数据都是整个程序中唯一的。方法区还包含了运行时常量池,主要存放编译期生成的字面量和符号引用(在类加载后放入)。String对象的字面量就会被放入到运行时常量池中。

天工大模型
天工大模型

中国首个对标ChatGPT的双千亿级大语言模型

下载

垃圾回收在方法区主要是对常量的回收和对类型的卸载。

2、jdk1.8及之后的jvm内存区域,元空间取代了永久代

776192883-5bc4b84f01b34_articlex.png

元空间和永久代的性质是一样的,都是对JVM方法区的实现,作用是一样的。不过元空间与永久代之间最大的区别在于:元空间并不在虚拟机JVM内存中,而是使用本地内存。

为什么用元空间取代永久代呢?

  1. 字符串存在永久代中,容易出现性能问题和内存溢出。

  2. 类及方法的信息等比较难确定其大小,因此对于永久代的大小指定比较困难,太小容易出现永久代溢出,太大则容易导致老年代溢出。

  3. 永久代会为GC带来不必要的复杂度,并且回收效率偏低。

直接内存

JDK1.4之后加入的NIO,引入了基于通道channel和缓冲区buffer的IO,直接使用native函数分配堆外内存,显著提高IO性能,避免了原来BIO的在java堆和naive堆中来回复制数据。

1947740664-5bc4b84ef3fc1_articlex.png

3、字符串String生成时的内存分配情况

参考文章:Java中字符串常量池的详解

4、生成对象时的内存情况

下面来分析一下我们常见的生成对象或基本数据类型变量的内存模型。这样可以对JVM有一个更好的理解。

int i =3;,一个方法对应一个栈帧,方法中的基本数据类型变量直接在栈帧中分配。如果是static、final类型的基本数据类型则存储在运行时常量池中,和String一样。

Object o1 = new Object();,对象引用(Object o1)存储在栈帧中,但是对象数据(new Object())存储在java堆中,对象类型数据(Class等信息)存储在方法区中。

String s1 = new String("abcd");,使用new声明的对象,对象引用(String s1)存储在栈帧中,对象数据(new String(“abcd”))存储在java堆中,字符串值(“abcd”)存储在运行时常量池中。

String s2 = “abc”,对象引用(String s2)存储在栈帧中,字符串值(“abc”)存储在运行时常量池中。

3883870872-5bc4b84f0831f_articlex.png

java栈、java堆、方法区这3者之间的关系大概就是上面的分析所示。

3、各种异常分析

1、java堆内存溢出错误OutOfMemoryError

如果java堆中分配的对象太多,且GC后内存空间还是不够用。下面通过循环生成对象来消耗内存空间进行测试。

相关指令:VM Args: -Xms20m -Xmx40m,表示JVM分配的堆内存最小为20MB,最大为40MB。

 public static void main(String[] args) {
   while (true) {
     List<Object> list = new ArrayList<>(10);
     list.add(new Object());
   }
 }

2、java栈堆栈溢出错误StackoverflowError

如果java栈的栈深度大于JVM允许的深度,就会抛出该错误。下面通过无限递归调用来进行堆栈进行测试。

相关指令:VM Args: -Xss128k,表示JVM分配的栈容量为128KB。

public class StackOOM {
    
    private int length = 1;
    
    public void stackLeak() {
        length++;
        stackLeak();
    }
    
    public static void main(String[] args) {
        StackOOM stackOOM = new StackOOM();
        stackOOM.stackLeak();
    }
}

2546966542-5bc4b84f04c85_articlex.png


热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

76

2026.03.11

Go高并发任务调度与Goroutine池化实践
Go高并发任务调度与Goroutine池化实践

本专题围绕 Go 语言在高并发任务处理场景中的实践展开,系统讲解 Goroutine 调度模型、Channel 通信机制以及并发控制策略。内容包括任务队列设计、Goroutine 池化管理、资源限制控制以及并发任务的性能优化方法。通过实际案例演示,帮助开发者构建稳定高效的 Go 并发任务处理系统,提高系统在高负载环境下的处理能力与稳定性。

38

2026.03.10

Kotlin Android模块化架构与组件化开发实践
Kotlin Android模块化架构与组件化开发实践

本专题围绕 Kotlin 在 Android 应用开发中的架构实践展开,重点讲解模块化设计与组件化开发的实现思路。内容包括项目模块拆分策略、公共组件封装、依赖管理优化、路由通信机制以及大型项目的工程化管理方法。通过真实项目案例分析,帮助开发者构建结构清晰、易扩展且维护成本低的 Android 应用架构体系,提升团队协作效率与项目迭代速度。

83

2026.03.09

JavaScript浏览器渲染机制与前端性能优化实践
JavaScript浏览器渲染机制与前端性能优化实践

本专题围绕 JavaScript 在浏览器中的执行与渲染机制展开,系统讲解 DOM 构建、CSSOM 解析、重排与重绘原理,以及关键渲染路径优化方法。内容涵盖事件循环机制、异步任务调度、资源加载优化、代码拆分与懒加载等性能优化策略。通过真实前端项目案例,帮助开发者理解浏览器底层工作原理,并掌握提升网页加载速度与交互体验的实用技巧。

97

2026.03.06

Rust内存安全机制与所有权模型深度实践
Rust内存安全机制与所有权模型深度实践

本专题围绕 Rust 语言核心特性展开,深入讲解所有权机制、借用规则、生命周期管理以及智能指针等关键概念。通过系统级开发案例,分析内存安全保障原理与零成本抽象优势,并结合并发场景讲解 Send 与 Sync 特性实现机制。帮助开发者真正理解 Rust 的设计哲学,掌握在高性能与安全性并重场景中的工程实践能力。

223

2026.03.05

PHP高性能API设计与Laravel服务架构实践
PHP高性能API设计与Laravel服务架构实践

本专题围绕 PHP 在现代 Web 后端开发中的高性能实践展开,重点讲解基于 Laravel 框架构建可扩展 API 服务的核心方法。内容涵盖路由与中间件机制、服务容器与依赖注入、接口版本管理、缓存策略设计以及队列异步处理方案。同时结合高并发场景,深入分析性能瓶颈定位与优化思路,帮助开发者构建稳定、高效、易维护的 PHP 后端服务体系。

458

2026.03.04

AI安装教程大全
AI安装教程大全

2026最全AI工具安装教程专题:包含各版本AI绘图、AI视频、智能办公软件的本地化部署手册。全篇零基础友好,附带最新模型下载地址、一键安装脚本及常见报错修复方案。每日更新,收藏这一篇就够了,让AI安装不再报错!

169

2026.03.04

Swift iOS架构设计与MVVM模式实战
Swift iOS架构设计与MVVM模式实战

本专题聚焦 Swift 在 iOS 应用架构设计中的实践,系统讲解 MVVM 模式的核心思想、数据绑定机制、模块拆分策略以及组件化开发方法。内容涵盖网络层封装、状态管理、依赖注入与性能优化技巧。通过完整项目案例,帮助开发者构建结构清晰、可维护性强的 iOS 应用架构体系。

246

2026.03.03

C++高性能网络编程与Reactor模型实践
C++高性能网络编程与Reactor模型实践

本专题围绕 C++ 在高性能网络服务开发中的应用展开,深入讲解 Socket 编程、多路复用机制、Reactor 模型设计原理以及线程池协作策略。内容涵盖 epoll 实现机制、内存管理优化、连接管理策略与高并发场景下的性能调优方法。通过构建高并发网络服务器实战案例,帮助开发者掌握 C++ 在底层系统与网络通信领域的核心技术。

34

2026.03.03

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 4.3万人学习

C# 教程
C# 教程

共94课时 | 11.2万人学习

Java 教程
Java 教程

共578课时 | 81万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号