|深入理解java垃圾回收

|深入理解java垃圾回收

文章图片


说到垃圾回收(Garbage Collection , GC) , 很多人就会自然而然地把它和Java联系起来 。 在Java中 , 程序员不需要去关心内存动态分配和垃圾回收的问题 , 这一切都交给了JVM来处理 。
1.为什么Java中需要垃圾收集?
在许多编程语言中 , 如C和C++ , 当程序不再需要对象时 , 开发人员必须采取编程步骤来回收对象在内存中分配的任何空间 。
如果实施得当 , 这种方法可能会非常有效 。 然而 , 历史已经表明 , 当这个过程做得不好时 , 可能会发生内存泄漏并导致应用程序崩溃 。
当Java语言被创建时 , Sun工程师决定开发人员不应该负责管理他们创建的对象所使用的内存 。 相反 , 垃圾收集例程将是JVM的一部分;此例程识别不再使用的对象 , 并将其从内存中删除 。
2.Java对象何时可用于垃圾收集?
当对象被标记为null、超出范围或不再被应用程序中的任何非null对象引用时 , 它就可以进行垃圾收集 。 简单来说 , 当应用程序不再使用Java对象时 , 它就可以进行垃圾收集 。
3.标记和扫描是什么意思?
可以将Java中的垃圾收集分为两个主要阶段 。 第一个阶段是标记阶段 , JVM查看内存中的每个对象 , 并确定是否仍然需要它 。 如果不需要该对象 , 则将其标记为垃圾收集 。
扫描是第二阶段 , JVM在该阶段执行垃圾收集和内存回收 。
采用这种事件序列的垃圾收集算法称为标记和扫描垃圾收集器 。

 4.什么是分代垃圾回收?
JVM将分配的内存拆分为四个独立的空间:eden、survivor、tenured、metaspace 。
底层JVM组件(如字符串缓冲区和编译类)在元空间中分配内存 。 随着时间的推移 , 这个空间相对不变 。 当人们谈论垃圾收集时 , 重点通常是eden、survivor和tenured 。
第一次创建对象时 , 它会被放置在eden空间中 。 如果垃圾回收发生 , 并且对象仍然被引用 , 它将被移动到survivor空间 。 如果发生了足够多的垃圾收集 , 并且survivor空间中的某个对象从未被收集 , 那么它将被移动到tenured空间 。
eden、survivor和tenured空间都是单独收集垃圾的 , 其中eden收集最多 , tenured空间收集最少 。 这有助于提高性能 , 因为弱世代假设告诉我们 , 长寿命对象可能会保持活动状态 , 因此检查其垃圾收集资格是浪费时间 。
此外 , eden空间中的对象更有可能是短暂的 , 并且有资格被移除 , 因此扫描eden空间更有可能释放出大量内存 。
将垃圾收集器划分为eden、survivor、Tentered和metaspace区域 , 可以极大地提高JVM性能 。
5.Java内存泄漏如何影响垃圾收集?
内存泄漏会增加内存消耗 , JVM被迫更频繁地运行 , 以便为新对象清理空间 。 垃圾收集例程将更频繁地运行 , 每次运行时释放的内存会更少 , 直到最终没有剩余的堆空间 。

 6.什么时候会选择并行垃圾收集器(GC)而不是并发标记扫描(CMS)或G1垃圾收集器?
G1垃圾收集器在系统可以向堆分配大量内存时工作得最好 。
在不影响应用程序性能的情况下 , 使用CMS处理和垃圾收集例程 。 对于大小小于32GB的堆 , 它也最有效 。
如果一个系统没有大量专用于堆的内存或多余的处理能力来分配给CMS , 那么简单的并行GC是正确的选择 。
此外 , 与其他算法相比 , 并行GC通常会在给定的时间段内收集更多的垃圾 。 如果暂停时间不是问题 , 那么并行垃圾收集可能是最佳选择 。