java list clear 垃圾回收_java垃圾回收机制

1、什么是垃圾回收?

程序的运行必然需要申请内存资源,无效的对象资源如果不及时处理就会一直占有内存资源,最终将导数内存溢出,所以内存资源的管是非常重要了。

1.1、C/C++语言的垃圾回收

在C/C++语言中,没有自动垃圾回收机制,是通过new关键字申请内存资源,通过 delete关键字释放内存资源。

如果,程序员在某些位置没有写 delete进行释放,那么申请的对象将一直占用内存资源,最终可能会导数内存溢出

1.2、Java语言的垃圾回收

为了让程序员更专注于代码的实现,而不用过多的考虑内存释放的问題,所以,在java语言中,有了自动的垃圾回收机制,也就是我们熟悉的GC。

有了垃圾回收机制后,程序员只需要关心内存的申请即可,内存的释放由系统自动识别完成。

换句话说,自动的垃圾回收的算法就会变得非常重要了,如果因为算法的不合理,导致内存资源一直没有释放,同样也可能会导致内存溢出的。

当然,除了Java语言,C#、 Python等语言也都有自动的垃圾回收机制

2、垃圾回收的常见算法

自动化的管理内存资源,垃圾回收机制必须要有一套算法来进行计算,哪些是有效的对象,哪些是无效的对象,对于无效的对象就要进行回收处理

常见的垃极回收算法有:引用计数法、标记清除法、标记压缩法、复制算法、分代算法等。

2.1、引用计数法

引用计数是历史最悠久的种算法,最早 George E. Collins在1960的时候首次提出,50年后的今天,该算法依然被很多编程语言使用。

2.1.1、原理

假设有一个对象A,任何一个对象对A的引用,那么对象A的引用计数器+1,当引用失败时,对象A的引用计数器

就-1,如果对象A的计数器的值为0,就说明对象A没有引用,可以被回收

2.1.2、优缺点

优点:

实时性较高,无需等到内存不够的时候,才开始回收,运行时根据对象的计数是否为0,就可以直接回收。

在垃圾回收过程中,应用无挂起。如果申请内存时,内存不足,则立刻报 outofmember错误。

区域性,更新对象的计数时,只是影响到该对象,不会担描全部对象

缺点:

每次对象被引用时,都需要去更新计数器,有一点时间开销。

浪费CPU资源,即使内存够用,仍然在运行时进行计数器的统计。

无法解决循环引用回题。(最大的缺点)

ps:什么是循环引用?

public class CycleIndex { public static void main(String[] args) { TestA a = new TestA(); TestB b = new TestB(); a.b = b; b.a = a; a = null; b = null; } } class TestA{ public TestB b; } class TestB{ public TestA a; }

虽然a 和 b 都设置为了null,但是由于a 和 b都存在循环引用,这样a和b永远不会被回收

2.2、标记清除法

标记清除法是将垃圾回收分为两个阶段,分别是标记和清除

标记:从根节点开始标记引用的对象

清除:未被标记引用的对象就是垃圾对象

2.2.1、原理

11284569.html

这张图代表的是程序运行期间所有对象的状恋,它们的标志位全部是0(也就是未标记,以下默认0就是末标记,1为已标记),假设这会儿有效内存空间耗尽了,JVM将会停止应用程序的运行并开启GC线程,然后开始进行标记工作,按照根搜索算法,标记完以后,对象的状态如下图。

11284569.html

可以看到,根据搜索算法,所有从root对象可到达的对象被标记为了存活对象,此时已经完成了第一阶段的标记,那么清除完成以后剩下的对象以及对象的状态如下图所示

11284569.html

可以看到被标记的对象将会被回收清楚掉,而被标记的对象会被留下,而且会将标记为重新归零,然后唤醒沉睡的线程程序,让程序继续运行

2.2.2、优缺点

可以看到,标记清除算法解决了引用计数算法中的循环引用的问题,没有从root节点引用的对象都会被回收

同样,标记清除法也是有缺点的:

效率较低,标记和清除两个动作都需要遍历所有的对象,并且在GC时,需要停止应用程序,对于交互性要求比较高的应用而言这个体验是非常的差的。

通过标记清除法清理出来的内存,碎片化较为严重,因为被回收的对象可能存在于内存的各个角落,所以清理出来的内存是不连贯的。

2.3、标记压缩算法

标记压缩法是在标记清除算法的基础之上,做了优化改进的算法。和标记清除算法一样,也是从根节点开始,对对象的引用进行标记,在清理阶段,并不是简单的清理未标记的对象,而是将存活的对象压缩到内存的一端,然后清理边界以外的垃极,从而解决了碎片化的问题。

2.3.1、原理

回收前的状态

11284569.html

回收后的状态

11284569.html

11284569.html

2.3.2、优缺点

优缺点同标记清除算法,解决了标记清除算法的问题,同时标记压缩算法多了一部,对象移动内存的步骤,其效率也有一定的影响

2.4、复制算法

复制算法的核心就是,将原有的内存空间一分为二,每次只使用其中的一块,在垃圾回收的时候,将正在使用的对象复制到另一个内存空间中,然后将该满状态的空间清空,交换两个内存的角色,完成垃圾的回收

如果内存中的垃圾对象较多,需要复制的对象较少,这种情况下适合使用该算法并且小懒虫比较高,反之则不适用

回收前的状态

form to

11284569.html

回收后的状态

to from

11284569.html

11284569.html

2.4.1、JVM中的年轻代的内存空间

11284569.html

1. 在GC开始的时候,对家只会存在于Eden区和名为"From"的 Survivor区, Survivor区"To"是空的。

2. 紧接着进行GC,Eden区中所有存活的对象都会被复制到"To",而在"From"区中,仍存活的对象会根据他们的

年龄信来决定去向。年龄达到一定值(年龄阈值,可以通过 -XX: MaxTenuringThreshold:来设置的对象会被移动

到移动到老年代中,没有达到阈值的对象会复制"To"区域

3. 经过这GC后,Eden区和From区已清空,这个时候,"From"和"To"会交换他们的角色,也就是新的"To"就是上次GC前的"From",新的"From"就是上次GC的"To"。不管怎样,都会保证名为To的Survivor区域是空

4.GC会一自重复这样的过程,直到"To"区被填满,"To"区被填满之后,会将所有对象移动到年老代中。

2.4.2、优缺点

优点:

在垃圾对象夺得情况下,效率较高

清理后,内存无碎片

缺点:

在垃圾对象少的情况下,不适用,如老年代内存

分配的两块内存空间,在同一时刻,只能使用一半,内存的使用率较低

2.5、分代算法

前面介绍了多种回收算法,每一种都有自己的优点缺点,所以可以根据回收对象来选择垃圾回收策略

分代算法就是这样,根据回收对象的特点进行选择,在jvm中,年轻代适合用复制算法,老年代适合用标记清除或者标记压缩算法

3、垃圾收集以及内存分配

前面我们讲了垃圾回收的算法,还需要有具体的实现,在jvm中,实现了多种拉圾收集器,包括:串行垃圾收集器、并行垃圾收集器、CMS(并发)垃圾收集、G1垃圾收集器

3.1、串行垃圾收集器

串行垃圾收集器,是指使用单线程进行垃圾回收,垃圾回收时,只有一个线程在工作,井且java应用中的所有线程

都要暂停,等待垃圾回收的完成。这种现象称之为STW( Stop-the- World)。

对于交互性较的应用而言,这种拉圾收集器是不能够接受的。

一般在javaweb应用中是不会采用该收集器的。

模拟垃圾回收

public class TestGC { public static void main(String[] args) throws InterruptedException { ArrayList list = new ArrayList(); while(true){ int sleep = new Random().nextInt(100); if(System.currentTimeMillis()%2==0){ list.clear(); }else{ for (int i = 0; i < 10000; i++) { Properties properties = new Properties(); properties.put("ket"+i,"value"+i+System.currentTimeMillis()); list.add(properties); } } Thread.sleep(sleep); } } }

3.1.2、设置垃圾回收为串行收集器

在程序运行参数中添加以下两个参数

-XX:+UseSerialGC

指定年轻代和老年代都使用串行垃圾收集器

-XX:+PrintGCDetails

打印垃圾回收的详细信息

#测试GC,将堆的初始和最大内存都设置为16m -XX:+UseSerialGC -XX:+PrintGCDetails -Xms16m -Xmx16m

可以看到以下信息

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一些与 Java 垃圾回收相关的面试题及答案: 1. 什么是 Java垃圾回收机制Java垃圾回收机制是指在 Java 应用程序运行过程中,当一些对象不再被引用,也就是不再被程序使用时,JVM 会自动回收这些对象所占用的内存空间,从而保证程序的正常运行。 2. 为什么需要垃圾回收垃圾回收的主要目的是帮助程序员减少手动内存管理的负担。在使用垃圾回收机制后,程序员不需要再手动释放内存,而是由 JVM 自动回收不再使用的对象。这可以提高开发效率,减少内存泄漏和内存溢出的风险。 3. 如何手动触发垃圾回收? 可以通过调用 System.gc() 方法手动触发垃圾回收。但是,这个方法只是向 JVM 发送一个垃圾回收请求,JVM 不一定会立即回收内存,因为垃圾回收是一个比较耗费资源的操作,JVM 会根据当前内存的使用情况和垃圾回收策略来决定是否回收内存。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [java垃圾回收机制及其面试题](https://blog.csdn.net/lonely_baby/article/details/129133683)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值