1.System.gc()的理解
- 默认情况下,调用
System.gc()
或Runtime.getRuntime().gc()
会显示触发Full GC
(对新生代和老年代同时进行回收) - 该方法被调用后并不能确保对垃圾回收器的调用,只是提醒垃圾回收器执行GC
2.内存溢出和内存泄漏
3.Stop The World
- 指在GC时会产生程序的停顿(整个应用程序线程都会暂停)
- STW是JVM在后台自动发起和自动完成的
- 可达性分析中因为需要枚举
GC Roots
,也会产生STW(没停止程序则可能会产生新的根节点) - 所有的GC都会产生STW
- 开发中不要使用
System.gc
(会导致STW)
4.垃圾回收的并行和并发
-
操作系统中的并行和并发:
- 并发:在一个时间段中几个程序处于已启动和运行完毕间,且这些程序都运行在一个CPU上(即CPU把一个时间段划分为几个时间片段,并在这些片段间来回切换)
- 并行:系统有多个CPU,每个进程在一个CPU上运行,进程间不抢占资源,可同时进行
- 对比:
- 并发指多个任务在同一个时间段内同时发生;并行指多个任务在同一个时间点上同时发生
- 并发多个任务会抢占资源;并行多个任务不会抢占资源
- 并发发生在单CPU单核中;并行发生在多CPU或单CPU多核中
-
垃圾回收的并行核并发:
- 并行:指多条垃圾回收线程并行工作,但此时用户线程依旧处于等待状态;对应的另一个概念是串形(即单线程执行,如果内存不足则将当前程序暂停,启动JVM垃圾回收器进行GC,等回收完再启动程序)
- 并发:指用户线程和垃圾回收线程同时进行(即垃圾回收线程不会暂停用户线程),当然还是可能为交替执行的
5.安全点和安全区域
6.引用
如果希望描述某些对象(比如缓存):当内存空间足够时,可以将这些对象保留在内存中;如果空间在GC后还是不足,则将这些对象进行抛弃(之前的描述中是考虑没有引用就选择抛弃,不管内存是否足够)
注意:下面处理方式都是针对对象可达情况下的处理方式,对于不可达的即使是强引用也会被回收
6.1 强引用-不回收
- 最常见的普通对象引用(即
A a = new A()
),也是默认的引用类型 - 只要强引用(可达)还存在,JVM宁愿抛出OOM,垃圾回收器永远不会回收被引用的对象(当然如果没被引用或将引用赋值为null,对象还是要被回收的)
- 该引用是内存泄漏的主要原因之一
6.2 软引用-内存不足即回收
- 如果将不可达的对象进行回收后依旧内存不足,则会将软引用的对象(依旧可达)进行GC(回收完后还是内存不足就报OOM)
- 该引用不是内存泄漏的原因(内存不足时该引用的都被回收了,再造成OOM就不是软引用的问题了)
- 对于内存敏感的缓存会使用该引用,如高速缓存(有空闲空间就保留缓存;不足时会及时清理)
6.3 弱引用-发现即回收
- 只被弱引用关联的对象(依旧可达)只能生存到下一次GC前。GC时即使内存足够也会被回收(即使还存在弱引用导致对象还是可达的)
- 与软引用的区别:软引用在GC回收时还要判断内存是否足够;弱引用内存足够也回收,回收更快
6.4 虚引用-对象回收跟踪
- 无论虚引用是否存在都不会对对象的生命周期造成影响(相当于对象不存在该引用)
- 无法通过该引用获得对象实例,为对象设置该引用的主要目的是在该对象被GC时可以受到系统通知
- 该引用必须和引用队列联合使用