Java内存分布归纳整理详解

发布时间 - 2026-01-11 00:45:13    点击率:

Java内存分布:Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域:方法区、虚拟机栈、本地方法栈、堆、程序计数器。

1.程序计数器

程序计数器是一块较小的内存空间,它可以看做是当前线程所执行的字节码的行号指示器。在虚拟机的概念模型中,字节码解释器工作时就是通过改变这个计数器的值来选取吓一条需要执行的字节码指令。

分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。

为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器,各条线程之间计数器互不影响,独立存储,所以该类内存区域为 “线程私有“ 的内存。

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

2.Java虚拟机栈

与程序计数器一样,Java虚拟机栈也是线程私有的,它的生命周期和线程相同。虚拟机栈描述的是Java方法执行的内存模型;每个方法在执行的同时都会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息。

每一个方法从调用到执行完成,都对应着一个栈帧在虚拟机栈中入栈到出栈的过程。

局部变量表存放了编译期可知的各种基本数据类型、对象引用(不等同于对象,是指向对象的引用)和returnAddress类型。如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常,如果无法申请到足够的内存会抛出OutOfMemory异常。

3.本地方法栈

本地方法栈和虚拟机栈之间的区别是虚拟机栈为虚拟机执行的Java(字节码)服务,而本地方法栈则为虚拟机使用到的Native方法服务。

4.Java堆

Java堆是被所有线程共享的一块内存区域,在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例,Java堆是垃圾回收器管理的主要区域

5.方法区

方法区和Java堆一样,是各个线程共享的内存区域,用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。

6.运行时常量池

运行时常量池是方法区的一部分。Class文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池,用于存放编译期生成的各种字面量和符号引用,这部分内容将会在类加载后进入方法区的运行时常量池中存放。

网上很多解释常量池会以字符串为例:

比如

String s1 = "Hello";
String s2 = "Hello";
String s3 = "Hel" + "lo";
String s4 = "Hel" + new String("lo");
String s5 = new String("Hello");
String s6 = s5.intern();
String s7 = "H";
String s8 = "ello";
String s9 = s7 + s8;
 
System.out.println(s1 == s2); // true
System.out.println(s1 == s3); // true
System.out.println(s1 == s4); // false
System.out.println(s1 == s9); // false
System.out.println(s4 == s5); // false
System.out.println(s1 == s6); // true

s1==s2为true很好理解,指向同一个常量池的内存地址。

s1==s3为true:对于s3而言,由于拼接的都是字面量,那么编译器会进行优化,其实就是指s3="Hello"

s1==s4为false:由于new String("lo")并不是一个字面量,而是一个变量,这样的话编译器不会进行优化,因为该变量可能会发生变化。

s1==s9为false:和上面一样的道理。

s4==s5:两个不同对象的引用当然不同。

s1==s6:由于String.intern()方法是指:如果常量池已经包含一个等于此 String 对象的字符串(该对象由 equals(Object) 方法确定),则返回池中的字符串。否则,将此 String 对象添加到池中,并且返回此 String 对象的引用。 它遵循对于任何两个字符串 s 和 t,当且仅当 s.equals(t) 为 true 时,s.intern() == t.intern() 才为 true。

希望本篇文章对您有所帮助


# Java内存分布详解  # Java内存分布  # 再也不用怕! 让你彻底搞明白Java内存分布  # Java内存模型之happens-before概念详解  # Java基础之Unsafe内存操作不安全类详解  # java boolean占用内存大小说明  # java内存分布实现代码  # 的是  # 池中  # 行号  # 则为  # 抛出  # 都是  # 量表  # 加载  # 很好  # 是指  # 已被  # 会在  # 把它  # 这部  # 它可以  # 为例  # 时就  # 跳转  # 将此  # 较小 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 详解vue.js组件化开发实践  Windows家庭版如何开启组策略(gpedit.msc)?(安装方法)  Laravel怎么生成二维码图片_Laravel集成Simple-QrCode扩展包与参数设置【实战】  Win11搜索不到蓝牙耳机怎么办 Win11蓝牙驱动更新修复【详解】  WEB开发之注册页面验证码倒计时代码的实现  使用豆包 AI 辅助进行简单网页 HTML 结构设计  如何在云虚拟主机上快速搭建个人网站?  Laravel如何集成Inertia.js与Vue/React?(安装配置)  Laravel与Inertia.js怎么结合_使用Laravel和Inertia构建现代单页应用  如何用景安虚拟主机手机版绑定域名建站?  Python制作简易注册登录系统  Laravel如何使用Blade模板引擎?(完整语法和示例)  Gemini手机端怎么发图片_Gemini手机端发图方法【步骤】  详解ASP.NET 生成二维码实例(采用ThoughtWorks.QRCode和QrCode.Net两种方式)  Laravel路由怎么定义_Laravel核心路由系统完全入门指南  Laravel如何使用Guzzle调用外部接口_Laravel发起HTTP请求与JSON数据解析【详解】  Windows10怎样连接蓝牙设备_Windows10蓝牙连接步骤【教程】  济南网站建设制作公司,室内设计网站一般都有哪些功能?  Laravel项目结构怎么组织_大型Laravel应用的最佳目录结构实践  网站图片在线制作软件,怎么在图片上做链接?  Laravel如何保护应用免受CSRF攻击?(原理和示例)  Laravel API资源类怎么用_Laravel API Resource数据转换  Laravel如何实现用户密码重置功能?(完整流程代码)  HTML5打空格有哪些误区_新手常犯的空格使用错误【技巧】  如何在服务器上三步完成建站并提升流量?  html5如何设置样式_HTML5样式设置方法与CSS应用技巧【教程】  如何批量查询域名的建站时间记录?  jQuery 常见小例汇总  Laravel怎么连接多个数据库_Laravel多数据库连接配置  如何快速搭建二级域名独立网站?  高防服务器租用首荐平台,企业级优惠套餐快速部署  Laravel的契約(Contracts)是什么_深入理解Laravel Contracts与依赖倒置  Laravel怎么实现模型属性的自动加密  Laravel表单请求验证类怎么用_Laravel Form Request分离验证逻辑教程  Laravel如何实现文件上传和存储?(本地与S3配置)  如何在HTML表单中获取用户输入并结合JavaScript动态控制复利计算循环  Python正则表达式进阶教程_复杂匹配与分组替换解析  Laravel如何创建和注册中间件_Laravel中间件编写与应用流程  如何快速重置建站主机并恢复默认配置?  免费网站制作appp,免费制作app哪个平台好?  高防服务器租用指南:配置选择与快速部署攻略  js实现点击每个li节点,都弹出其文本值及修改  高端建站如何打造兼具美学与转化的品牌官网?  如何用搬瓦工VPS快速搭建个人网站?  如何用PHP快速搭建高效网站?分步指南  logo在线制作免费网站在线制作好吗,DW网页制作时,如何在网页标题前加上logo?  如何在万网主机上快速搭建网站?  夸克浏览器网页跳转延迟怎么办 夸克浏览器跳转优化  javascript中的数组方法有哪些_如何利用数组方法简化数据处理  如何在 React 中条件性地遍历数组并渲染元素