JVM由浅入深系列 |
---|
一、关于Java性能的误解 |
二、Java性能概述 |
三、了解JVM概述 |
四、探索JVM架构 |
五、垃圾收集基础 |
六、HotSpot中的垃圾收集 |
七、垃圾收集中级 |
八、垃圾收集高级 |
👋HotSpot中的垃圾收集
⚽️1. HotSpot中的垃圾收集
回顾一下,与 C/C++ 和类似环境不同, Java 不使用操作系统来管理动态内存。相反,当JVM 进程启动时, JVM 预先分配(或保留)内存,并在用户空间管理单一连续的内存池。
正如我们所看到的,这个内存池是由多个具有特定用途的不同区域组成的,而且对象的地址会经常发生变化。这是因为垃圾收集器会重新安置(relocate)通常在 Eden 区创建的对象。执行重新安置的收集器被称为“疏散”收集器。
⚾️1.1 线程本地分配
JVM 使用了一个性能增强来管理 Eden 区。这是一个需要进行高效管理的关键区域,因为大多数对象是在这里创建的,而且寿命非常短的对象(生命周期小于下一个垃圾收集周期剩余时间的那些)永远不会再出现在其他地方。
为了提高效率, JVM 将 Eden 区划分成若干个缓冲区,并将这些缓冲区交给应用程序线程使用,用于新对象的分配。这种方法的好处是,每个线程都知道自己不需要考虑其他线程在该缓冲区内分配的可能性。这些区域叫作线程本地分配缓冲区(thread-local allocationbuffer, TLAB)。
应用程序线程对其 TLAB 的这种排他性控制,意味着对 JVM 线程来说,分配操作的时间复杂度是 O(1)。这是因为当一个线程创建一个新对象时,将为该对象分配存储空间,并且将线程本地指针更新为指向下一个空闲的内存地址。从 C 运行时角度看,这是一个简单的指针碰撞,也就是多了一条指令,将“next free”指针向前移动了一下。
这种行为如下图所示,其中每个应用程序线程都持有一个用来分配新对象的缓冲区。如果应用程序线程填满了其缓冲区,那么 JVM 会提供一个指向 Eden 区中的新区域的指针。