先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7
深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
如果你需要这些资料,可以添加V获取:vip1024b (备注Java)
正文
俗话说的好:“世界上没有免费的午餐”,是需要成本滴~
-
首先资源付出的成本(CPU,内存……)支持垃圾回收机制能进行工作
-
GC对于内存的回收即时性没有那么高(虽然能在一定的时间内进行回收,但也不是不用了立刻就回收,有一定的延迟)
-
GC中存在一个致命的问题:STW问题(stop the word)
什么是STW问题?
就是当GC工作的时候,正常的业务代码可能无法执行,必须要等到GC工作完毕。对于服务器来讲,一旦服务器出发了GC,就可能导致正常代码无法执行(会出现卡顿),因为服务器可能会不断接收到请求,那么就会造成请求的积压,可能导致请求到一半就停止,或者是刚刚接收到请求而无法处理请求,直接造成用户体验的影响。
②. C/C++不是调用free/dalete函数就释放了吗?为什么还会出现“内存泄漏“问题?
答:上面提到需要在合适的时机进行释放,虽然内存内存的申请时机一般都是明确的,但是这个合适的释放时机是比较模糊的
1.2.对于 Java 而言
有GC机制,只管申请内存,无需关注内存的释放,而且可以很大程度上规避内存泄漏的问题(也不是完全没有)
2.GC要回收哪些内存?
============
1.PC程序计数器 / 栈 :都不要 GC 回收,因为他的释放时机很明确,随着线程的创建而申请内存,随着线程的销毁而释放。
2.常量池 / 方法区 :GC也不需要太关心,因为它占用的空间比较小,数据也很少会失去作用,如果对其进行GC,回收内存的性价比也不高(比如:打扫一个干净的小房间,即便你在怎么去打扫,也扫不出多少灰尘)
3.堆:GC主要回收的区域,堆的内存区域也很大,申请又很频繁(因为每次new对象都会在堆上申请内存)
2.1.堆上的内存分布
所谓的 “回收内存” => “回收对象”
GC工作的本质其实就是回收对象,以对象为基本单位(更方便),把不需要使用的对象找出来,回收掉即可,回收对象就会释放内存。
3.如何标记垃圾?
=========
所有的垃圾回收大体都是遵循以下两个步骤:
1.标记:找出哪个对象是垃圾
2.回收:把标记的垃圾对象释放
标记的方式有很多种,这里讲述两种:引用计数 和 可达性分析
一般来说像python PHP 语言会用到”引用计数“,而Java一般使用第二种”可达性分析“。
3.1.引用计数
引用 的方法很简单,判定的效率也比较高,大部分情况都是一个不错的算法,即给对象增加一个引用计数器,每当有一个地方引用它时,计数器就+1;当引用失效时,就-1;任何时刻计数器为0的对象就是不能再被使用的,即对象已”死“
引用计数的缺陷——”循环引用“
主流的JVM中没有选用引用计数法来管理内存,主要是因为引用计数法无法解决对象的循环引用问题
如:
class A{
A ret = null;
}
public class Demo2 {
public static void main(String[] args) {
A a1 = new A();
A a2 = new A();
a1.ret = a2;
a2.ret = a1;
}
}
分析:
3.2.可达性分析
Java不采用”引用计数法"来判断对象是否已”死“,而是采用"可达性分析"来判断对象是否存活。
算法核心:通过一些列成为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索走过的路径称之为“引用链”,当一个对象到GC Roots没有任何的引用链相连时(从GC Roots到这个对象不可达),证明此对象时不可用的。
上图如果看不太懂,可以看下图,如:
**总结:**可达性分析,就是从GC Roots开始进行遍历,看到哪些对象是能够被访问到的(某个对象在遍历过程中只要被访问一次,也可以被访问多次),那么剩下的就是垃圾。实际对象之间的相互引用关系不是简单的树形结构,而是“图”结构
可达性分析可视为GC Roots的对象包括以下几种
-
栈上的局部变量表中的引用(每个程序有多个线程,每个线程有自己的栈,每个栈又有很多层栈帧,每层栈帧又有很多局部变量,这些内容试试GC Roots的一部分)
-
常量池中引用指向的对象
-
方法区中静态引用指向的对象
Java对引用的概念做了扩充,将引用分为强引用(Strong Reference)、软引用(Soft Reference)、弱引用(Weak Reference)和虚引用(Phantom Reference)四种,这四种引用的强度依次递减。
-
强引用:既能用于找到对象,也能决定对象的生死
-
软引用:能用于找到对象,能够一定程度上的决定对象的生死(能保对象一时,内存如果充裕,不会回收软引用指向的对象,但是如果内存紧缺了,就会回收该对象)
-
弱引用:只能用于找对象,不能决定对象的生死
-
虚引用:不能用于找对象,也不能够决定对象的生死,只能在对象消亡之前,收到通知做一些善后工作
3.3.回收方法区垃圾
目前很多框架大量使用到反射,方法去会被加载很多类,那么此时也是需要回收的
方法区(永久代)的垃圾回收主要内容:废弃常量和无用的类(类对象(类的卸载)=>(和类的加载对应))
判定一个类是否是"无用类"则相对复杂很多。类需要同时满足下面三个条件才会被算是"无用的类" :
-
1.该类的所有实例已经被报备回收了
-
2.加载该类的类加载器也已经被回收了
-
3.该类的类对象没有在任何地方使用(其他的代码也没有在通过反射来使用这个类对象)
JVM可以对同时满足上述3个条件的无用类进行回收,也仅仅是"可以"而不是必然。在大量使用反射、动
态代理等场景都需要JVM具备类卸载的功能来防止永久代的溢出。
讲完了垃圾是如何标记的,下面我们谈谈垃圾又是如何回收的呢
4.如何回收垃圾
========
4.1.标记 - 清除算法
将需要回收的对象全部标记出来,标记完成后将所有已标记的对象统一回收
标记 - 清除算法的缺陷
-
空间问题:我们不难发现上图清除垃圾之后,可分配的内存空间并不是连续的,这就是产生了“内存碎片问题”,空间碎片太多可能会导致以后在程序运行中需要分配较大对象时,无法找到足够连续内存而不得不提前触发另一次垃圾收集
-
效率问题:标记和清除这两个过程的效率都不高
4.2.标记 - 复制算法
能够解决内存碎片问题
"复制"算法是为了解决"标记-清理"的效率问题。它将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这块内存需要进行垃圾回收时,会将此区域还存活着的对象复制到另一块上面,然后再把已经使用过的内存区域一次清理掉。这样做的好处是每次都是对整个半区进行内存回收,内存分配时也就不需要考虑内存碎片等复杂情况,只需要移动堆顶指针,按顺序分配即可。此算法实现简单,运行高效
总结
三个工作日收到了offer,头条面试体验还是很棒的,这次的头条面试好像每面技术都问了我算法,然后就是中间件、MySQL、Redis、Kafka、网络等等。
- 第一个是算法
关于算法,我觉得最好的是刷题,作死的刷的,多做多练习,加上自己的理解,还是比较容易拿下的。
而且,我貌似是将《算法刷题LeetCode中文版》、《算法的乐趣》大概都过了一遍,尤其是这本
《算法刷题LeetCode中文版》总共有15个章节:编程技巧、线性表、字符串、栈和队列、树、排序、查找、暴力枚举法、广度优先搜索、深度优先搜索、分治法、贪心法、动态规划、图、细节实现题
《算法的乐趣》共有23个章节:
- 第二个是Redis、MySQL、kafka(给大家看下我都有哪些复习笔记)
基本上都是面试真题解析、笔记和学习大纲图,感觉复习也就需要这些吧(个人意见)
- 第三个是网络(给大家看一本我之前得到的《JAVA核心知识整理》包括30个章节分类,这本283页的JAVA核心知识整理还是很不错的,一次性总结了30个分享的大知识点)
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注Java)
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
总结了30个分享的大知识点)**
[外链图片转存中…(img-mXIGZqki-1713185373535)]
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注Java)
[外链图片转存中…(img-479WF6ye-1713185373536)]
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!