JVM——垃圾回收相关概念

JVM——垃圾回收相关概念

System.gc()的理解

在默认情况下,通过system.gc ()或者Runtime. getRuntime ( ) .gc ()的调用 ,会显式触发Full
GC,同时对老年代和新生代进行回收
,尝试释放被丢弃对象占用的内存。

内存的溢出与内存的泄漏

内存的溢出(OOM)
JVM——垃圾回收相关概念_第1张图片
当然,也不是在任何情况下垃圾收集器都会被触发的

比如,我们去分配一个超大对象,类似一个超大数组超过堆的最大值,JVM可以判
断出垃圾收集并不能解决这个问题,所以直接抛出OutOfMemoryError。

内存泄漏

也称作“存储渗漏”。严格来说,只有对象不会再被程序用到了,但是GC又不能回收他们的情况,才叫内存泄漏
但实际情况很多时候一些不太好的实践(或疏忽)会导致对象的生命周期变得很长甚至导OOM,也可以叫做宽泛意义上的“内存泄漏”。
JVM——垃圾回收相关概念_第2张图片
举例:
1、单例模式
单例的生命周期和应用程序是一样长的,所以单例程序中,如果持有对外部对象的引用的话,那么这个外部对象是不能被回收的,则会导致内存泄漏的产生。|
2、一些提供close的资源未关闭导致内存泄漏
数据库连接(dataSourse.getconnection( )),网络连接(socket)和io连接必须手动close,否则是不能被回收的。

安全点与安全区域

安全点(Safepoint)

程序执行时并非在所有地方都能停顿下来开始GC,只有在特定的位置才能停顿下来开始GC,,这些位置称为“安全点(Safepoint) ”
Safe Point的选择很重要,如果太少可能导致GC等待的时间太长,如果太频繁可能导致运行时的性能问题。大部分指令的执行时间都非常短暂,通常会根据==“是否具有让程序长时间执行的特征”为标准==。比如:选择一些执行时间较长的指令作为Safe Point,如方法调用、循环跳转和异常跳转等。

如何在cc发生时,检查所有线程都跑到最近的安全点停顿下来呢?
主动式中断

主动式中断的思想是当GC需要中断线程的时候,不直接对线程操作,仅仅简单地设置一个标志,各个线程执行时主动去轮询这个标志,发现中断标志为真时就自己中断挂起

安全区域(SafeRegion)
安全区域是指在一段代码片段中,对象的引用关系不会发生变化,在这个区域中的任何位置开始GC都是安全的。我们也可以把 safe Region看做是被扩展了的safepoint。

1、当线程运行到safe Region的代码时,首先标识已经进入了safe Region,如果这段时间内发生GC,JVM会忽略标识为Safe Region状态的线程;
2、当线程即将离开Safe Region时,会检查JVM是否已经完成GC,如果完成了,则继续运行,否则线程必须等待直到收到可以安全离开Safe Region的信号为止;

引用

JVM——垃圾回收相关概念_第3张图片
强引用(不回收)

  • 强引用指向的对象,除非引用关系不存在了,否则永远不会被垃圾回收。
  • 强引用所指向的对象在任何时候都不会被系统回收,虚拟机宁愿抛出OOM异常,也不会回收强引用所指向对象。
  • 强引用可能导致内存泄漏。

软引用(内存不足即回收)

软引用是用来描述一些还有用,但非必需的对象。只被软引用关联着的对象在系统将要发生内存溢出异常前,会把这些对象列进回收范围之中进行第二次回收,如果这次回收还没有足够的内存,才会抛出内存溢出异常。
在这里插入图片描述

弱引用(第一次GC即回收)
弱引用也是用来描述那些非必需对象,只被弱引用关联的对象只能生存到下一次垃圾收集发生为止。在系统GC时,只要发现弱引用,不管系统堆空间使用是否充足,都会回收掉只被弱引用关联的对象。

软引用与软引用的作用:

软引用、弱引用都非常适合来保存那些可有可无的缓存数据。如果这么做,当系统内存不足时,这些缓存数据会被回收,不会导致内存溢出。而当内存资源充足时,这些缓存数据又可以存在相当长的时间,从而起到加速系统的作用

虚引用(对象回收跟踪)

  • 如果一个对象仅持有虚引用,那么它和没有引用几乎是一样的,随时都可能被垃圾回收器回收
  • 为一个对象设置虚引用关联的唯一目的在于跟踪垃圾回收过程。比如:能在这个对象被收集器回收时收到一个系统通知
    JVM——垃圾回收相关概念_第4张图片

你可能感兴趣的:(JVM,java,开发语言)