深入探讨Java程序运行时类、对象等在JVM内存中的存放位置

Java程序中经常用到的内存模块到底有哪些?

深入探讨Java程序运行时类、对象等在JVM内存中的存放位置

前言

写代码时 通常会关注代码与对象间的流转 但实际上 我们是否认真关注过 java程序运行时 类存放在哪里 对象存放在哪里 局部变量存放在哪里 方法调用链存放在哪里

JVM 内存

大家都知道,java程序在jvm虚拟机里执行。众多jvm虚拟机中,HotSpot VM是当前最热门、使用最多的jvm版本。HotSpot VM里,整个虚拟机内存被划分成几大模块。

本地方法栈

堆(Heap)

该区域是我们平常正常new出的对象所在之处。该区域也是我们平时接触最多的区域。这里细分为Young Generation(新生代)和Old Generation(老生代)。也就是我们平常经常关注的YGC和FGC的地方。而Young Generation中间又细分为三个区域。分别是Eden、From Survivor、To Survivor。YGC会有各种算法针对这三块区域做垃圾回收算法。这里先不展开讨论。有兴趣的可以参考面试官。不要再问我“JAVA GC垃圾回收机制”了 。

该区域为所有线程共享。它存放着主要业务对象。所以其空间相对较大。通常可利用 -Xms设置堆的最小空间大小。还能用 -Xmx设置堆的最大空间大小。

方法区(Method Area)

方法区跟刚提到的栈区域有诸多相似之处。它是线程共享的。其内存不连续。它具备可扩展的特性。它支持垃圾回收。当无法再扩展时会抛出OutOfMemoryError异常。方法区通常被称作非堆区域(non-heap)。要注意将其与堆外内存区分开来。

方法区存储着已被虚拟机加载的类信息。还存储着常量。也存储着静态变量。以及即时编译器编译后的代码等数据。它与运行时生成的对象不同。是一个固定存放物资的区域。

方法区内存回收目标主要针对常量池回收以及类型卸载。通常情况下这个区域回收“成绩”较难令人满意。特别是类型卸载,条件相当苛刻。但回收确实是有必要的。

(程序计数器寄存器)

程序计数器的作用可视为当前线程所执行字节码的行号指示器。字节码解释器工作时,通过改变计数器的值来选取下一条字节码指令。分支、循环、跳转、异常处理、线程恢复等基础功能,都需依赖计数器来完成。

Java虚拟机的多线程靠线程轮流切换以及分配处理器执行时间来实现。在任何确定时刻,一个处理器(多核处理器的一个内核)仅执行一条线程的指令。必须有地方存储每个线程具体执行到哪一步。该区域就负责此事。

虚拟机栈(JVM Stacks)

学习过汇编语言的同学可能较易理解它的作用。它是记录线程调用方法模型的栈。每一条线程都有一个私有的虚拟机栈。所以它与对应线程生死相依。

方法返回地址

只会存放值的引用

本地方法栈(Native Method Stacks)

还会抛出OutOfMemoryError异常

区别在于,虚拟机栈为虚拟机执行Java方法(字节码)提供服务。而本地方法栈,是为虚拟机所使用的Native方法提供服务。

以此帮助对比理解

堆外内存(Off-Heap Memory)

区别于 JVM 内存,java 常用的还有堆外内存。JVM内存具备十分完善的垃圾管理机制。这使得开发人员在开发时无需操心内存资源回收,能够随心所欲地开展工作。然而,正是由于存在一系列极为复杂精妙的垃圾管理算法。在高并发情形下,尤其是写内存较多时。可能会频繁出现YGC和FGC。每次GC都会致使程序卡顿。这反倒会成为性能瓶颈的帮凶。

针对这一类业务情况,我们通常用堆外内存提升性能水平。堆外内存是游离于JVM管理之外的物理机内存。它不属于JVM管理,所以没有JVM的那套GC算法。如此便能有更好的扩展性和IO速度。

在JAVA里 可借助Unsafe以及NIO包中的ByteBuffer来操控堆外内存 还能够运用第三方堆外缓存管理包 比如ohc(off-heap-cache)来进行操作

你可能想看:
« 上一篇
下一篇 »

相关推荐

java中什么是冒泡,冒泡算法

2026年09月06日

27阅读

java中冒号,java双冒号

2026年09月06日

24阅读

java中的->,java中的是什么意思

2026年09月06日

24阅读

java中的super用法,Java中super的说明

2026年09月06日

27阅读

java中反射的应用,java中反射的应用场景

2026年09月06日

23阅读

java中开关的定义,Java关键字有哪些

2026年09月06日

25阅读