0

0

Java程序运行时的内存模型简介_理解JVM环境的基础构成

P粉602998670

P粉602998670

发布时间:2026-02-12 16:03:10

|

886人浏览过

|

来源于php中文网

原创

java堆存对象和数组等线程共享数据,栈存线程私有的局部变量、参数等;对象总在堆里因栈仅存引用,实际数据需垃圾回收与线程隔离支持。

java程序运行时的内存模型简介_理解jvm环境的基础构成

Java堆和栈到底存什么,为什么对象总在堆里

Java程序运行时的内存划分不是凭空设计的,而是为了配合垃圾回收和线程隔离。堆(Heap)是所有线程共享的区域,你用 new 创建的对象、数组,全在这里分配;栈(Java Virtual Machine Stacks)则是每个线程私有的,只存局部变量、方法参数、返回地址这些生命周期明确的小东西。

常见错误现象:把大对象(比如几十MB的字节数组)反复在方法里声明,栈不会崩,但堆会快速撑满——因为栈只存引用,实际数据还在堆上。

  • 基本类型变量(intboolean)在栈里存值;引用类型变量(如 StringArrayList)在栈里存地址,对象本体一定在堆里
  • 逃逸分析可能让某些对象“栈上分配”,但这只是JVM优化,开发者不能直接控制,也不该依赖
  • 栈空间默认较小(一般1MB左右),递归过深或局部变量过多会触发 StackOverflowError;堆空间默认较大(如G1默认初始4MB,可动态扩展),但溢出报的是 OutOfMemoryError: Java heap space

JVM方法区去哪儿了:从永久代到元空间的变化

方法区存放类信息、常量、静态变量、即时编译后的代码。它不等同于“永久代(PermGen)”,后者只是JDK 7及之前HotSpot对方法区的一种实现;JDK 8起彻底移除了永久代,改用本地内存实现的元空间(Metaspace)。

使用场景:动态生成类(如Spring CGLIB代理、Groovy脚本热加载)容易撑爆方法区。以前调 -XX:MaxPermSize,现在得调 -XX:MaxMetaspaceSize

立即学习Java免费学习笔记(深入)”;

Qoder
Qoder

阿里巴巴推出的AI编程工具

下载
  • 字符串常量池在JDK 7后从永久代移到了堆中,所以 String.intern() 的行为变了:重复字符串不再导致永久代OOM,但可能加重堆压力
  • 元空间使用本地内存,理论上只受系统限制,但没设 -XX:MaxMetaspaceSize 时仍可能因类加载器泄漏(如Web应用热部署未清理)导致本地内存耗尽
  • java.lang.OutOfMemoryError: Metaspace 出现时,优先检查是否频繁定义新类,而不是盲目加大参数

直接内存不是JVM内存,但Java程序一样会用到

直接内存(Direct Memory)不在JVM规范定义的运行时数据区里,它由操作系统管理,但Java通过 java.nio.ByteBuffer.allocateDirect() 可以申请。典型用于NIO读写、Netty零拷贝等高性能场景。

容易踩的坑:直接内存不受 -Xmx 控制,但总量受 -XX:MaxDirectMemorySize 限制(默认等于 -Xmx)。忘了设这个值,又大量用 allocateDirect,就会触发 OutOfMemoryError: Direct buffer memory

  • 直接内存的GC不走常规堆回收流程,依赖 Cleaner 机制,在Full GC时才尝试释放——这意味着它可能比堆对象更晚被回收
  • ByteBuffer.wrap(byte[]) 是堆内缓冲区,allocateDirect() 才是真正的直接内存;别以为用了NIO就自动走直接内存
  • 监控工具如JConsole、VisualVM默认不显示直接内存用量,需看 java.lang:type=MemoryPool,name=Code Cache 之外的 java.lang:type=MemoryPool,name=Metaspacejava.lang:type=MemoryPool,name=Compressed Class Space 并不包含它,得查 java.lang:type=MemoryPool,name=Direct Buffer Pool(如果支持)或用 jstat -gcCCSTYGC 之外的 DC(Direct Count)字段

线程本地变量(ThreadLocal)的内存归属容易误判

ThreadLocal 变量本身是堆上的对象,但它持有的值(ThreadLocalMap 中的 Entry)是绑定在线程栈所关联的本地存储里的。关键点在于:这些值的生命周期取决于线程,而不是声明它的类或方法。

常见错误现象:Web容器中用 ThreadLocal 存用户上下文,但没在Filter或拦截器末尾调用 remove(),导致线程复用(如Tomcat线程池)时旧数据残留,甚至引发内存泄漏——因为 ThreadLocalMapEntry 是弱引用Key,但Value是强引用,不手动清理就会一直挂着。

  • ThreadLocal 不是“线程私有堆”,它只是提供了一种访问线程关联数据的机制,底层仍是堆对象 + 线程对象内的引用链
  • 每次 set() 都会往当前线程的 ThreadLocalMap 里塞一个 Entry,Key是当前 ThreadLocal 实例(弱引用),Value是你传进去的对象(强引用)
  • 在可能线程复用的环境(如Servlet容器、RPC线程池)中,必须配对使用 set()remove(),不能只靠 initialValue()get() 自动初始化来掩盖泄漏
事情说清了就结束。真正难的不是记住哪块内存放什么,而是当 OutOfMemoryError 报出来时,你能一眼看出它属于哪个区域、对应哪种使用模式——这需要结合日志、参数、代码上下文一起判断,而不是背概念。

热门AI工具

更多
DeepSeek
DeepSeek

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

豆包大模型
豆包大模型

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

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

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

文心一言
文心一言

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

讯飞写作
讯飞写作

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

即梦AI
即梦AI

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

ChatGPT
ChatGPT

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

相关专题

更多
如何配置Tomcat环境变量
如何配置Tomcat环境变量

配置Tomcat环境变量需要在系统中添加CATALINA_HOME变量,并将Tomcat的安装路径添加到PATH变量中。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

115

2023.10.26

idea如何集成Tomcat
idea如何集成Tomcat

idea集成Tomcat的步骤:1、添加Tomcat服务器配置;2、配置项目部署;3、运行Tomcat服务器;4、访问项目;5、注意事项;6、关闭Tomcat服务器。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

170

2024.02.23

怎么查看Tomcat源代码
怎么查看Tomcat源代码

查看Tomcat源代码的步骤:1、下载Tomcat源代码;2、在IDEA中导入Tomcat源代码;3、查看源代码;4、理解Tomcat的工作原理;5、参与社区和贡献;6、注意事项;7、持续学习和更新;8、使用工具和插件。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

98

2024.02.23

常见的tomcat漏洞有哪些
常见的tomcat漏洞有哪些

常见的tomcat漏洞有:1、跨站脚本攻击;2、跨站请求伪造;3、目录遍历漏洞;4、缓冲区溢出漏洞;5、配置漏洞;6、第三方组件漏洞。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

168

2024.02.23

tomcat日志乱码怎么解决
tomcat日志乱码怎么解决

tomcat日志乱码的解决办法:1、修改tomcat的日志编码设置;2、检查ide的编码设置;3、检查操作系统的编码设置;4、使用过滤器处理日志;5、检查外部系统的编码设置;6、检查文件编码方式等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

154

2024.02.23

weblogic和tomcat有哪些区别
weblogic和tomcat有哪些区别

weblogic和tomcat的区别:1、功能;2、性能;3、规模;4、价格;5、安全性;6、配置和管理;7、社区支持;8、集成能力;9、升级和更新;10、可靠性。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

200

2024.02.23

tomcat和nginx有哪些区别
tomcat和nginx有哪些区别

tomcat和nginx的区别:1、应用领域;2、性能;3、功能;4、配置;5、安全性;6、扩展性;7、部署复杂性;8、社区支持;9、成本;10、日志管理。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

237

2024.02.23

tomcat启动闪退怎么解决
tomcat启动闪退怎么解决

tomcat启动闪退的解决办法:1、检查java环境;2、检查环境变量配置;3、检查端口被占用;4、检查配置文件编码;5、检查启动时需要的配置文件;6、检查相关文件是否丢失;7、检查防火墙和杀毒软件设置。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

166

2024.02.23

2026春节习俗大全
2026春节习俗大全

本专题整合了2026春节习俗大全,阅读专题下面的文章了解更多详细内容。

189

2026.02.11

热门下载

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

精品课程

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

共23课时 | 3.5万人学习

C# 教程
C# 教程

共94课时 | 9.3万人学习

Java 教程
Java 教程

共578课时 | 64.1万人学习

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

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