垃圾回收——GC20+连问,帮你彻底搞懂GC

1 篇文章 0 订阅
1 篇文章 0 订阅

写在前面:

最近在整理基础知识,在理清思路的同时也会配合现实面试或增或减的假想了部分关于GC的问题,用以帮助自己很好的梳理这一模块的知识点,希望能够帮助有需要的朋友。

 

什么是GC?

Java语言特有的垃圾收集机制

GC能干什么?

作为一个垃圾收集机制,作用显然就是收集垃圾对象,它主要做的事儿有三件:

1.判断哪些对象需要被回收

2.何时回收垃圾对象

3.怎样回收垃圾对象

那么GC是怎样判断哪些对象需要被回收呢?

常见方法有两种分别为:引用计数法和可达性分析法

除了这两中方法,你还了解其他的方法吗?

逃逸分析

说一下逃逸分析?

逃逸分析的原理:就是分析对象动态的作用域,来判断该对象是否因为外部引用而逃逸出原来的区域

例子:

某一方法被以调用参数的形式被传递到其他方法中去,这称为方法逃逸

如果能证明某一对象不会逃逸到原方法或原线程之外,即其他方法无法通过任何途径访问到该对象,那么我们就可以对该对象进行一些高效的优化,比如栈上分配,此时该对象所占有的内存空间可以随着栈帧的出栈而被销毁。如果能够分析出大量的非逃逸对象,那么只要栈帧一出栈其所占内存就会被释放,这显然会分担GC的回收压力

了解GC Roots对象吗?说一下可达性分析

可达性分析是通过以某一堆外引用对象来作为引用链的根节点,向下搜索,直至所需分析的对象为一条引用链。如果一个对象的引用链为0,即所有堆外引用对象都无法搜索到这一对象,那么该对象就属于不可达,则表明该对象可以被GC回收

GC Roots对象包括:JVM栈中栈帧里局部变量表引用的对象、本地方法栈中JNI引用的对象、方法区中常量和静态属性变量引用的对象

顺便说一下引用计数法?

对象在初始化赋值的同时维护了一个计数器,每当该对象被其他地方引用时,计数器就会做+1操作,表示当前该对象被引用数,如果计数器的值在某一时刻为0时,就表示该对象可以被GC回收

你了解引用计数法有什么不足吗?

1.首先每个对象都需要维护一个计数器,如果对象较多,那么用来维护计数器的开销就会变大,显然不合理

2.该算法无法处理对象间循环引用的问题

GC在哪工作?什么时候工作?

GC在堆内存中工作,主要作用于堆内存中的年轻代(相对频繁),也可以作用在老年代(相对较少),每当内存中存储量触发设置的阈值时,GC就会被触发,进行回收工作

你知道的有几种GC?说一下他们都在哪工作,做些什么?

Minor GC:作用于年轻代,主要是利用复制算法将垃圾对象进行回收,存活对象进行复制保留,并进入下一空间

Major GC:作用于老年代,主要是利用标记清除或标记整理算法来清楚死掉的对象

Full GC:作用于整个堆内存,当Minor GC多次触发后仍旧没有足够的空间提供给即将被创建的对象分配时,就会触发

 * [GC (Allocation Failure) [PSYoungGen: 1956K->501K(2560K)] 1956K->781K(9728K), 0.0024008 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
 * [GC (Allocation Failure) [PSYoungGen: 2329K->504K(2560K)] 2609K->1327K(9728K), 0.0017602 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
 * [GC (Allocation Failure) [PSYoungGen: 2217K->400K(2560K)] 4129K->2855K(9728K), 0.0008253 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
 * [Full GC (Ergonomics) [PSYoungGen: 2154K->0K(2560K)] [ParOldGen: 6807K->2775K(7168K)] 8961K->2775K(9728K), [Metaspace: 3218K->3218K(1056768K)], 0.0066449 secs] [Times: user=0.02 sys=0.00, real=0.01 secs]
 * [GC (Allocation Failure) [PSYoungGen: 87K->32K(2560K)] 5038K->4983K(9728K), 0.0004724 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
 * [GC (Allocation Failure) [PSYoungGen: 32K->32K(2560K)] 4983K->4983K(9728K), 0.0004280 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
 * [Full GC (Allocation Failure) [PSYoungGen: 32K->0K(2560K)] [ParOldGen: 4951K->3863K(7168K)] 4983K->3863K(9728K), [Metaspace: 3222K->3222K(1056768K)], 0.0053085 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
 * [GC (Allocation Failure) [PSYoungGen: 0K->0K(1536K)] 3863K->3863K(8704K), 0.0004326 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
 * [Full GC (Allocation Failure) [PSYoungGen: 0K->0K(1536K)] [ParOldGen: 3863K->3843K(7168K)] 3863K->3843K(8704K), [Metaspace: 3222K->3222K(1056768K)], 0.0089908 secs] [Times: user=0.02 sys=0.00, real=0.01 secs]

你说了复制算法,说一下它的原理和JVM中它是怎样实现的

复制算法的原理:

将内存分为两块区域(是否均分不做要求,推荐不要均分),一个用来生产(new)对象,一个暂时空置等待,之后通过判断是否存活算法(HotSpot JVM用的是可达性分析)将经过GC后仍旧存活的对象复制到等待空间中去

复制算法在JVM中的实现:

存在两次复制算法,首先在Eden(8/10)区生产对象,GC后将仍旧存活的对象复制到Survivor(2/10)中,其次再将Survivor分为两块区域From(1/10)和To(1/10),这里的To区域和From是随机的,谁空谁就是To,另一个就是From

标记清除和标记整理有什么区别?推荐使用哪一个?

两者的区别主要是标记清除算法会因为存活对象的分布不均而导致清除垃圾对象后会产生内存碎片,浪费资源,而标记整理算法则不会,它会将存活对象整理在内存区域的另一端,只清除有垃圾的一端,通常推荐使用标记整理算法

你了解引用吗?都知道哪些引用?

引用分为强引用、软引用、弱引用、和虚引用等四种

软引用可以用在哪些地方?

可以做缓存和关联一些有用但是并非必需的对象

你了解GC调优吗?说一下它的原理?自己有没有调过,怎么调的?

原理:

通过工具或者GC日志查看GC执行情况,最主要的是查看GC停顿点和GC的持续时长,通过对这些数据的分析判断,针对性的进行参数调优或者配置调优,调整之后再次通过工具或日志验证调整后GC执行情况

我使用的是GC日志的形式对GC进行调优,在允许的范围内(1/4)设置最大堆内存和初始化堆相等,为了测试分析GC自己设计了一个OOM的场景,来对GC日志进行查看和分析

* 堆内存调优——测试发生OOM
 *
 * [GC (Allocation Failure) [PSYoungGen: 1956K->501K(2560K)] 1956K->781K(9728K), 0.0024008 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
 * [GC (Allocation Failure) [PSYoungGen: 2329K->504K(2560K)] 2609K->1327K(9728K), 0.0017602 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
 * [GC (Allocation Failure) [PSYoungGen: 2217K->400K(2560K)] 4129K->2855K(9728K), 0.0008253 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
 * [Full GC (Ergonomics) [PSYoungGen: 2154K->0K(2560K)] [ParOldGen: 6807K->2775K(7168K)] 8961K->2775K(9728K), [Metaspace: 3218K->3218K(1056768K)], 0.0066449 secs] [Times: user=0.02 sys=0.00, real=0.01 secs]
 * [GC (Allocation Failure) [PSYoungGen: 87K->32K(2560K)] 5038K->4983K(9728K), 0.0004724 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
 * [GC (Allocation Failure) [PSYoungGen: 32K->32K(2560K)] 4983K->4983K(9728K), 0.0004280 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
 * [Full GC (Allocation Failure) [PSYoungGen: 32K->0K(2560K)] [ParOldGen: 4951K->3863K(7168K)] 4983K->3863K(9728K), [Metaspace: 3222K->3222K(1056768K)], 0.0053085 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
 * [GC (Allocation Failure) [PSYoungGen: 0K->0K(1536K)] 3863K->3863K(8704K), 0.0004326 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
 * [Full GC (Allocation Failure) [PSYoungGen: 0K->0K(1536K)] [ParOldGen: 3863K->3843K(7168K)] 3863K->3843K(8704K), [Metaspace: 3222K->3222K(1056768K)], 0.0089908 secs] [Times: user=0.02 sys=0.00, real=0.01 secs]
 * Heap
 *  PSYoungGen      total 1536K, used 90K [0x00000000ffd00000, 0x0000000100000000, 0x0000000100000000)
 *   eden space 1024K, 8% used [0x00000000ffd00000,0x00000000ffd168a8,0x00000000ffe00000)
 *   from space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000)
 *   to   space 1024K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000)
 *  ParOldGen       total 7168K, used 3843K [0x00000000ff600000, 0x00000000ffd00000, 0x00000000ffd00000)
 *   object space 7168K, 53% used [0x00000000ff600000,0x00000000ff9c0dc8,0x00000000ffd00000)
 *  Metaspace       used 3274K, capacity 4500K, committed 4864K, reserved 1056768K
 *   class space    used 354K, capacity 388K, committed 512K, reserved 1048576K
 * Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
 * 	at java.util.Arrays.copyOf(Arrays.java:3332)
 * 	at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:124)
 * 	at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:674)
 * 	at java.lang.StringBuilder.append(StringBuilder.java:208)
 * 	at com.xiaozhao.juc.JVMDemo.main(JVMDemo.java:36)
 *
 * Process finished with exit code 1

听说过垃圾收集器吗?能说一两个他们的实现吗?

CMS、G1、Serial GC、ParNew GC、Parrallel GC。。。

先这么多吧,关于Java知识的整理和学习一直持续中,也一直菜鸟中,但也一直坚持中,希望看到的朋友能共同学习,其中若是存在不足,欢迎指正!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值