Java 虚拟机JVM 总结(精简版) [上] |
学过 Java 的同学都知道,JVM 是 Java Virtual Machine(Java 虚拟机)的缩写, JVM 是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。
一、线程私有 💅🌧🍏🆘🦠 1. 程序计数器 当前线程所执行的字节码的行号指示器。 对于 Java方法,记录正在执行的虚拟机字节码指令的地址;对于native方法,记录值为空(Undefined)。 唯一一个Java 虚拟机规范中没有规定任何 OutOfMemoryError 的内存区域。 👆🗺🦀♀🐶 2. Java 虚拟机栈 每个线程都有独自的虚拟机栈,并且在栈中的结构是栈帧,当调用一个方法时,会为这个方法创建一个栈帧,每个方法对应的是入栈、出栈的过程。 栈帧中包括局部变量表、操作数栈、动态链接、方法出口等信息。 线程请求的栈深度大于虚拟机规定的栈深度,会抛出 StackOverflowError,当栈空间动态扩展,但无法申请足够的内存,将抛出 OutOfMemoryError 👮♂️👠💿🙄👃 3. 本地方法栈 与虚拟机栈类似,区别在于虚拟机栈执行Java方法,本地方法栈执行 Native 方法。 二、线程共享 👴🪖🔑🙂🤝 1. 堆 堆是垃圾回收的主要区域,很多时候被称为 GC堆。 堆被分为新生代、老年代:Eden Space(伊甸园)、Survivor Space(幸存者区)、Tenured Gen(老年代)。 几乎所有的对象实例及数组都在堆上分配。 当内存空间不足时,无法完成实例分配,将抛出 OutOfMemoryError 🦴🏫🍊🈳🐋 2. 方法区 方法区在 HotSpot 中又被称为永久代。 存储虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。 该区域的回收目标主要是对常量池的回收以及类的卸载。👨⚕️🧢🔭🤔👍 当内存空间不足时,无法为方法区开辟新空间时,将抛出 OutOfMemoryError 运行时常量池,存储类加载后的常量池信息。 三、垃圾回收 💪🎢🥩🆎🐴 1. why - 为什么要了解垃圾回收: 提高系统性能,突破应用性能瓶颈。 排查各种内存溢出,内存泄漏的问题。 👍🗺🍒🈳🐖 2. what1 - 哪些内存区域需要回收: Java 堆和方法区。 Java 堆是对无用的对象的回收,方法区是对废弃的常量以及无用的类进行回收。 3. what2 - 哪些对象需要回收(对象存活判定方法): 👂🗺🎂🈷🦉 3.1 引用计数法 原理:给对象添加引用计数器,每当有地方引用它,引用计数器加1;引用失效,计数器减1;当计数器的值为 0,对象可被回收。 优点:实现简单,判定效率高。 缺点:存在循环引用的问题。 🧑💻🎒🪓🤖👃 3.2 可达性分析法(GC Roots): 原理:通过一系列的称为「GC Roots」的对象作为起始点,从起始点搜索的路径称为引用链,当一个对象没有与任何引用链相连时,则证明此对象是不可用的。 3.3 GC Roots 对象种类:🧑🌾🕶🩺😆🙏 Java 虚拟机栈中引用的对象。 本地方法栈 (Native方法) 中引用的对象。 方法区中类静态属性引用的对象。 方法区中常量引用的对象。 👍🚗🍖🆚🐡 4. when - 什么时候进行回收: 达到 Minor GC 或者 Full GC 的触发条件时。 Minor GC 触发条件: 当新生代(Eden区)空间不足时,发起一次 Minor GC🧑💻👗💶😚👍 Full GC 触发条件: 调用 System.gc(),系统建议执行 Full GC,但是不必然执行. 当老年代空间不足时. 方法区空间不足时. 🙌🚗🍽®🦟 历次通过 Minor GC 后进入老年代的平均大小大于老年代的可用内存时. 由Eden区、From Survior区向To Survior区复制时,对象大小大于ToSurvior区可用内存,则把该对象转存到老年代,且老年代的可用内存小于该对象大小时。 5. how - 如何回收(垃圾回收算法): 🧓🦺🪓😄🤛 5.1 标记 - 清除算法 原理: 该算法分为「标记」和「清除」两个阶段,首先标记出所有需要回收的对象,在标记完成后统一进行回收。 🧠🚐🥩🆎🐡 特点: 效率:标记和清除两个阶段的效率都不高。 空间:标记清除之后未进行碎片整理,产生大量不连续的内存碎片,分配大对象时空间不够会经常触发垃圾回收,最终影响的仍然是效率。 5.2 标记 - 整理算法 🧓🩴🎺🤤🦴 原理:该算法分为「标记」和「整理」两个阶段,标记如同标记清除中的标记,整理是指不直接对标记的对象进行清理,而是让所有存活的对象移动到一边,清除掉端边界以外的内存。 特点: 效率:标记和整理两个阶段的效率不高。 空间:优点是解决了内存碎片的问题。 🤳🍊🈴🐕 5.3 复制算法(新生代采用的算法) 原理:新生代分为 Eden、Survivor1(from)、Survivor2(to)三部分,每次使用Eden和其中一块Survivor,回收时,将存活对象复制到另一块Survivor,然后清理到刚使用的 Eden和Survivor 👵🧢📡😡🖕 特点: 效率:每次对整个半区进行回收,内存分配是不需要考虑内存碎片的情况;内存分配时只需要移动堆顶指针,效率高。 空间:未进行垃圾回收时,会有一部分空间未用上。 5.4 分代收集算法 🙌🌞🌰🆒🐺 原理: 将Java 堆分为新生代和老年代,根据各个年代的特点采用适当的收集算法。 特点:充分利用不同各个年代的特点采用最适当的收集算法。 新生代:次垃圾收集时都发现只有少量存活,选择使用复制算法,只需要付出少量存活对象的复制成本就可以完成收集。 老年代:因为对象存活率高、没有额外空间进行分配担保,使用「标记-清理」或者「标记-整理」算法进行回收。 👆🗼🍍🚭🐅
帖子热度 1万 ℃
|
|
|