- 🍅文章发布日期:2021.12.29
- 👋java学习之路!
- 欢迎各位🔎点赞👍评论收藏⭐️
- 🎄新年快乐朋友们🎄
- 👋jvm学习之路!
文章笔记参考黑马程序员
文章目录
-
⭐️1.如何判断对象可以回收
-
⭐️1.1引用计数法
-
⭐️1.2可达性分析算法
-
⭐️2.五种引用
-
⭐️2.1强引用
-
⭐️2.2 软引用
-
⭐️2.3 弱引用
-
⭐️引用队列
-
⭐️2.4虚引用
-
⭐️2.5终结器引用
-
⭐️2.6引用总结
-
⭐️3.垃圾回收算法
-
⭐️3.1标记清除
-
⭐️3.2标记整理
-
⭐️3.3复制
-
⭐️4分代垃圾回收
-
大对象处理策略
-
⭐️4.1分代垃圾回收总结
============================================================================
========================================================================
一个对象收到引用时计数+1
,一个对象失去引用时计数-1
,一个对象的引用计数为0时,该对象被当作垃圾进行回收
但是这样会有一个问题
循环引用
当A对象和B对象相互引用时,他们的引用计数都是1,但是他们却没有被其他对象所使用,这样因为他们的引用计数不能归0导致两个对象不能作为垃圾被回收,导致内存泄漏
==========================================================================
此算法为java虚拟机采用的一种垃圾回收算法,首先要确定一个肯定不会被当成垃圾回收的对象GC Root(根对象)
-
java虚拟机中的垃圾回收器采用
可达性分析
来探索所有存活的对象 -
扫描堆中的对象,看是否能够
沿着GC Root对象为起点的引用链找到该对象
,找不到,表示可以回收
可以作为GC Root的对象
-
虚拟机栈(栈帧中的本地变量表)中引用的对象
-
方法区中类静态变量引用的对象
-
方法区中常量引用的对象
-
本地方法栈中JNI(即一般说的Native方法)引用的对象
======================================================================
-
强引用
-
软引用
-
弱引用
-
虚引用
-
终结器引用
下面我们分别进行描述
======================================================================
我们平时所使用的引用便是强引用,比如我们new一个对象A,把这个对象通过等号(赋值运算符)赋值给一个变量m,那么就称这个变量m强引用了刚刚的对象A
强引用的特点:
只要沿着GC root的引用链能够找到该对象,他就不会被垃圾回收,就比如上图中的C对象能找到A1对象,那么A1对象就不能被回收,当B对象和C对象对A1对象的引用都断开时,A1对象才能被垃圾回收
=======================================================================
如图,A2对象使用过软引用对象被C对象间接引用到,只要满足垃圾回收时,并且回收完内存也不够时,那么软引用所引用的A2对象就会被释放掉
所以软引用引用对象被释放
的条件是
-
没有强引用对象引用它
-
发生垃圾回收
-
垃圾回收之后内存不够
软引用的应用案例
public static void soft(){
ArrayList<SoftReference<byte[]>> list = new ArrayList<>();
for (int i = 0; i < 5; i++) {
SoftReference<byte[]> ref = new SoftReference<>(new byte[_4MB]);
System.out.println(ref.get());
list.add(ref);
System.out.println(list.size());
}
System.out.println(“循环结束:”+list.size());
for (SoftReference<byte[]> ref : list) {
System.out.println(ref.get());
}
}
list先引用软引用对象,软引用对象间接的引用byte数组
list和SoftReference之间是强引用,SoftReference和byte数组之间是软引用
内存充足的时候软引用引用的对象保留,但是当内存不足的时候,软引用引用的对象就会被清除
=======================================================================
和软引用的区别是,当弱引用引用该对象时,发生垃圾回收不管内存是否充足,弱引用所引用的对象都会被回收
public class Demo03 {
private static final int _4MB = 410241024;
public static void main(String[] args) throws IOException {
List<WeakReference<byte[]>> list = new ArrayList<>();
for (int i = 0; i < 10; i++) {
//关联了软引用对象和引用队列,当软引用所关联的byte[]被回收时,软引用自己会加入到引用队列queue中去
WeakReference<byte[]> ref = new WeakReference<>(new byte[_4MB]);
list.add(ref);
for (WeakReference<byte[]> w: list){
System.out.println(w.get()+“”);
}
System.out.println();
}
System.out.println(“循环结束:”+list.size());
}
}
通过list集合引用WeakReference,通过WeakReference间接的引用byte[]数组,这样进行垃圾回收,就会尝试把WeakReference运用的byte数组所占用的内存做释放
====================================================================
当软引用所引用的对象或弱引用引用的对象被清除之后,软引用和弱引用本身并不会消失,软引用和弱引用本身也是一个对象,此时软引用和弱引用会进入引用队列
软引用和弱引用自身也要占用一定内存,如果想释放软引用和弱引用的内存,需要使用引用队列找到它们,对其做进一步的处理
引用队列操作代码
public class Demo02 {
private static final int _4MB = 410241024;
public static void main(String[] args) throws IOException {
ArrayList<SoftReference<byte[]>> list = new ArrayList<>();
//引用队列
ReferenceQueue<byte[]> queue = new ReferenceQueue<>();
for (int i = 0; i < 5; i++) {
//关联了软引用对象和引用队列,当软引用所关联的byte[]被回收时,软引用自己会加入到引用队列queue中去
SoftReference<byte[]> ref = new SoftReference<>(new byte[_4MB],queue);
System.out.println(ref.get());
list.add(ref);
System.out.println(list.size());
}
Reference<? extends byte[]> poll = queue.poll();
while (poll != null){
list.remove(poll);
poll = queue.poll();
}
for (SoftReference<byte[]> ref : list) {
System.out.println(ref.get());
}
}
}
关联软引用对象和引用队列,当软引用所关联的byte[]被回收时,软引用自己会加入到引用队列queue中去,之后查看引用队列中是否有软引用,有就将其移出
======================================================================
在ByteBuffer
被回收的时候,他分配的直接内存并不能被java的垃圾回收管理,所以我们将虚引用对象Cleaner进入引用队列
,虚引用所在队列会有一个叫RefrenceHandlel
的线程,来定时到这个引用队列中找新入队的Cleaner,如果有就调用Cleaner中的clean
方法,根据记录的直接内存的地址调用Unsafe.freeMemary
方法来清理直接内存
========================================================================
所有的java对象都继承自Object
类,Object类有finallize()
终结方法,当对象重写了终结方法并且没有强引用,他就可以被当成垃圾回收,终结方法的调用依靠终结器引用
如上图当A4对象被垃圾回收时,在A4对象被真正清除
之前,终结期引用进入引用队列,再由一个优先级很低的线程(finallizeHandler)
查看引用队列中的终结器引用,通过终结器引用找到将要垃圾回收的对象,调用对象的finallize
方法,调用之后,该对象就可以被垃圾回收了
=======================================================================
========================================================================
=======================================================================
第一个阶段:标记
顺着GC Root查找没有引用的对象,将其进行标记
第二个阶段:清除
将垃圾对象所占用的空间释放
释放不意味着将每一个字节进行清理操作,清除只是把对象所占用内存的起始与结束地址记录下来,放在一个较空闲的地址链表里,下次分配内存的时候会直接覆盖这部分内存
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)
![img](https://i-blog.csdnimg.cn/blog_migrate/57eaff7d2f996678ed10f693c37e83f4.jpeg)
最后
2020年在匆匆忙忙慌慌乱乱中就这么度过了,我们迎来了新一年,互联网的发展如此之快,技术日新月异,更新迭代成为了这个时代的代名词,坚持下来的技术体系会越来越健壮,JVM作为如今是跳槽大厂必备的技能,如果你还没掌握,更别提之后更新的新技术了。
更多JVM面试整理:
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
以扫码获取!!(备注Java获取)**
![img](https://i-blog.csdnimg.cn/blog_migrate/57eaff7d2f996678ed10f693c37e83f4.jpeg)
最后
2020年在匆匆忙忙慌慌乱乱中就这么度过了,我们迎来了新一年,互联网的发展如此之快,技术日新月异,更新迭代成为了这个时代的代名词,坚持下来的技术体系会越来越健壮,JVM作为如今是跳槽大厂必备的技能,如果你还没掌握,更别提之后更新的新技术了。
[外链图片转存中…(img-Xp7u8SZI-1713529100829)]
更多JVM面试整理:
[外链图片转存中…(img-DZN4Lpf4-1713529100832)]
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!