Java内存管理¶
约 682 个字 预计阅读时间 2 分钟
- Java虚拟机(JVM)在运行时,会把内存划分为几个不同的逻辑区域,主要的内存区域可以分为三大块:栈(Stack)、堆(Heap) 和 方法区/元空间(Method Area/Metaspace)。
栈¶
- 与C++类似,存放局部变量,以及引用数据类型(不是对象本身,而是它的引用地址)
堆¶
-
堆是JVM管理的最大的一块内存区域,它的主要目的是存放对象实例。
-
堆的特点是:所有线程共享同一个堆,因此在多线程访问堆中对象时需要考虑线程安全问题。堆也是垃圾回收器(Garbage Collector, GC) 主要工作的区域。
存储在堆里的变量:
-
所有通过
new关键字创建的对象实例: -
成员变量 / 实例变量 (Instance Variables):定义在类中、但在方法之外、没有 static 修饰的变量。这些变量是对象的一部分,所以它们跟随着其所属的对象一起存储在堆中。
-
数组 (Arrays):数组在Java中也被视为对象,因此数组本身(包括其存储空间)也是在堆上分配的。
方法区/元空间¶
- 方法区/元空间的核心设计目的,就是为了存放这些与具体实例无关的、描述“类”本身信息的“蓝图”和“模板”。
-
存放类的“元信息” (Store Metadata)
- 这是最根本的目的。JVM需要一个地方来存储从
.class文件中加载出来的所有结构化信息。这个地方就是方法区。通过将这份“蓝图”只存一份在方法区,所有根据这个蓝图创建出来的对象实例(都在堆中)都可以共享这份定义,极大地节约了内存。
- 这是最根本的目的。JVM需要一个地方来存储从
-
实现数据共享与效率 (Enable Sharing and Efficiency)
-
静态成员:
static变量和static方法是属于类的,而不是属于任何一个对象的。将它们存放在方法区,可以保证它们只有一份,被所有对象实例共享。 -
常量池:通过运行时常量池(包括字符串常量池),可以复用大量的字面量(如字符串"Hello"),避免在堆中创建成千上万个内容相同的对象。
-
-
支持Java的动态特性(反射)(Support Dynamic Features like Reflection)
- Java强大的反射机制,允许程序在运行时检查和操作类本身。例如,您可以通过
Car.class获取到Car类的所有方法和字段。这些信息是从哪里来的呢?正是从方法区中存储的类元信息里读取的。没有方法区这样一个集中的“档案馆”,Java的反射就无从谈起。
- Java强大的反射机制,允许程序在运行时检查和操作类本身。例如,您可以通过