JVM学习笔记-堆(Heap)

本文详细介绍了Java堆内存的管理方式及其在Java虚拟机中的角色。包括堆内存的分配、垃圾回收机制以及如何处理多线程访问堆内存的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

     对于大多数应用来说,Java堆(Java Heap)是Java虚拟机所管理的内存中最大的一块。Java堆是被所有线程共享的一块内存区域,在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。这一点在Java虚拟机规范中的描述是:所有的对象实例以及数组都要在堆上分配①,但是随着JIT编译器的发展与逃逸分析技术的逐渐成熟,栈上分配、标量替换②优化技术将会导致一些微妙的变化发生,所有的对象都分配在堆上也渐渐变得不是那么“绝对”了。 

 

      Java堆是垃圾收集器管理的主要区域,因此很多时候也被称做“GC堆”(Garbage Collected Heap,幸好国内没翻译成“垃圾堆”)。如果从内存回收的角度看,由于现在收集器基本都是采用的分代收集算法,所以Java堆中还可以细分为:新生代和老年代;再细致一点的有Eden空间、From Survivor空间、To Survivor空间等。如果从内存分配的角度看,线程共享的Java堆中可能划分出多个线程私有的分配缓冲区(Thread Local Allocation Buffer,TLAB)。不过,无论如何划分,都与存放内容无关,无论哪个区域,存储的都仍然是对象实例,进一步划分的目的是为了更好地回收内存,或者更快地分配内存。在本章中,我们仅仅针对内存区域的作用进行讨论,Java堆中的上述各个区域的分配和回收等细节将会是下一章的主题。 

根据Java虚拟机规范的规定,Java堆可以处于物理上不连续的内存空间中,只要逻辑上是连续的即可,就像我们的磁盘空间一样。在实现时,既可以实现成固定大小的,也可以是可扩展的,不过当前主流的虚拟机都是按照可扩展来实现的(通过-Xmx和-Xms控制)。如果在堆中没有内存完成实例分配,并且堆也无法再扩展时,将会抛出OutOfMemoryError异常。

 

以上描述截取自: 

《深入理解Java虚拟机:JVM高级特性与最佳实践》 作者: 周志明 

----------------------------------------------------------------------------------------------------------------------------------

 

 

 

Whenever a class instance or array is created in a running Java application, the memory for the new object is allocated from a single heap. As there is only one heap inside a Java Virtual Machine instance, all threads share it. Because a Java application runs inside its "own" exclusive Java Virtual Machine instance, there is a separate heap for every individual running application. There is no way two different Java applications could trample on each otherís heap data. Two different threads of the same application, however, could trample on each otherís heap data. This is why you must be concerned about proper synchronization of multi-threaded access to objects (heap data) in your Java programs.

The Java Virtual Machine has an instruction that allocates memory on the heap for a new object, but has no instruction for freeing that memory. Just as you canít explicitly free an object in Java source code, you canít explicitly free an object in Java bytecodes. The virtual machine itself is responsible for deciding whether and when to free memory occupied by objects that are no longer referenced by the running application. Usually, a Java Virtual Machine implementation uses a garbage collector to manage the heap.

 

java 程序在运行时创建的 所有类实例或数组都放在同一个堆中 。而 一个Java 虚拟机实例 只存在一个堆内存空间 ,因此所有的线程均 共享这个堆 。又由于一个java 程序独占一个Java 虚拟机实例,因而每个java 程序都有他自己的堆内存---- 他们之间不会相互影响。但是同 一个Java 程序的多线程却共享着同一个堆空间 ,在这种情况下,就得考虑多线程访问对象(堆数据)的同步问题了。

 

Java虚拟机有一条在堆中分配新对象的指令,但是没有释放内存的指令。java虚拟机的垃圾回收机制负责回收没有被使用的内存。

只要有一个对象引用,虚拟机就必须能够快速定位对象类型的数据。另外它也必须通过该对象引用访问相应的类数据(存储于方法区中的类型信息)。因此在对象中通常会有一个指向方法区的指针。

 

 

以上描述截取自: 

《Inside the Java Virtual Machine 2nd Edition》 作者:Bill Venners   

 

 

 

### 关于JVM学习笔记 #### 使用元空间替代永久代 在 JDK 1.8 中,Java虚拟机(JVM)引入了一项重要改进:采用元空间(Metaspace)[^1]来代替原有的永久代(PermGen Space),这一改动显著影响了类数据存储的方式。尽管从逻辑上看,元空间依然属于方法区的一部分,但在实际实现上却有了本质区别——它不再依赖于JVM内部管理的特定内存区域而是利用本地内存。 #### 配置参数详解 为了更好地理解和优化基于新架构下的应用程序性能表现,在启动程序时可以通过一系列配置选项调整JVM行为模式[^2]: -XX:+PrintGCDateStamps`: 打印详细的垃圾收集日志信息以及时间戳; - `-XX:MetaspaceSize=<size>` 及 `- `-Xss<size>` :指定线程栈大小; - `-XX:+HeapDumpOnOutOfMemoryError` 加 `-XX:HeapDumpPath=<path>` : 当遇到OOM错误时自动导出转储文件至指定路径; - `-Xms<size>` 和 `-Xmx<size>` : 设定最小与最大的尺寸; - `-XX:SurvivorRatio=<ratio>` : 控制新生代中Eden区与其他两个survivor分区的比例关系; - `-XX:+TraceClassLoading` 和 `-XX:+TraceClassUnloading` : 开启加载卸载类跟踪功能; - `-Xloggc:<file_path>` : 将GC记录写入给定的日志文件; 这些设置有助于开发者深入理解并解决潜在的应用问题,比如通过分析GC活动识别可能存在的内存泄漏风险点或是评估不同场景下最优资源配置方案。 #### 对象回收机制中的软引用特性 针对可能出现的内存压力情况,JVM提供了一个灵活的对象生命周期管理模式—即软引用(Soft Reference)[^3]。当系统面临即将触发Out-of-Memory(OOM)异常之前会优先尝试释放那些仅存在弱连接的目标实例,从而有效缓解短期内的资源紧张状况而不至于立即终止进程运行。下面是一个简单的例子展示了如何创建一个带有软引用来关联对象的方法: ```java public class TestSoftReference { public static void main(String[] args){ // 创建强引用 Object obj = new byte[10 * 1024 * 1024]; // 占用大约10MB的空间 // 建立软引用指向该对象 SoftReference<Object> sfRefObj = new SoftReference<>(obj); // 销毁原始强引用 obj = null; System.gc(); // 请求执行一次完整的垃圾回收操作 } } ``` 此代码片段说明了即使原生的强引用被移除后,只要当前可用物理内存量充足,则对应的实体仍可通过其持有的软引用来访问直到必要时刻才真正清除它们。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值