为什么
JVM
在
Java
中如此重要?
首先你应该知道,运行一个 Java 应用程序,我们必须要先安装 JDK 或者 JRE 包。这是因为 Java 应用在编译后会变成字节码,然后通过字节码运行在 JVM 中,而 JVM 是 JRE 的核心组成部分。
JVM 不仅承担了 Java 字节码的分析(JIT compiler)和执行(Runtime),同时也内置了自动内存分配管理机制。
这个机制可以大大降低手动分配回收机制可能带来的内存泄露和内存溢出风险,使 Java 开发人员不需要关注每个对象的内存分配以及回收,从而更专注于业务本身。
从了解内存模型开始
JVM 自动内存分配管理机制的好处很多,但实则是把双刃剑。这个机制在提升 Java 开发效率的同时,也容易使 Java 开发人员过度依赖于自动化,弱化对内存的管理能力,这样系统就很容易发生 JVM 的堆内存异常,垃圾回收(GC)的方式不合适以及 GC 次数过于频繁等问题,这些都将直接影响到应用服务的性能。
因此,要进行 JVM 层面的调优,就需要深入了解 JVM 内存分配和回收原理,这样在遇到问题时,我们才能通过日志分析快速地定位问题;也能在系统遇到性能瓶颈时,通过分析 JVM 调优来优化系统性能。这也是整个模块四的重点内容,今天我们就从 JVM 的内存模型学起,为后续的学习打下一个坚实的基础。
JVM
内存模型的具体设计
我们先通过一张 JVM 内存模型图,来熟悉下其具体设计。
在 Java 中,JVM 内存模型主要分为堆、程序计数器、方法区、虚拟机栈和本地方法栈。
JVM 的 5 个分区具体是怎么实现的呢?我们一一分析。
1.
堆(
Heap
)
堆是 JVM 内存中最大的一块内存空间,该内存被所有线程共享,几乎所有对象和数组都被分配到了堆内存中。堆被划分为新生代和老年代,新生代又被进一步划分为 Eden 和 Survivor 区,最后 Survivor 由 From Survivor 和 To Survivor 组成。
在 Java6 版本中,永久代在非堆内存区;到了 Java7 版本,永久代的静态变量和运行时常量池被合并到了堆中;而到了 Java8,永久代被元空间取代了。 结构如下图所示: