如何阅读jdk源码?
简介
这篇文章主要讲述jdk本身的源码该如何阅读,关于各种框架的源码阅读我们后面再一起探讨。
笔者认为阅读源码主要包括下面几个步骤。
设定目标
凡事皆有目的,阅读源码也是一样。
从大的方面来说,我们阅读源码的目的是为了提升自己的技术能力,运用到工作中,遇到问题快速定位,升职加薪等等。
从小的方面来说,阅读某一段源码的目的就是要搞清楚它的原理,就是死磕,就是那种探索真相的固执。
目的是抽象的,目标是具体的,我们阅读源码之前一定要给自己设定一个目标。
比如,下一章我们将要一起学习的ConcurrentHashMap,我们可以设定以下目标:
(1)熟悉ConcurrentHashMap的存储结构;
(2)熟悉ConcurrentHashMap中主要方法的实现过程;
(3)探索ConcurrentHashMap中出现的新技术;
提出问题
有了目标之后,我们要试着提出一些问题。
还是以ConcurrentHashMap为例,笔者提出了以下这些问题:
(1)ConcurrentHashMap与HashMap的数据结构是否一样?
(2)HashMap在多线程环境下何时会出现并发安全问题?
(3)ConcurrentHashMap是怎么解决并发安全问题的?
(4)ConcurrentHashMap使用了哪些锁?
(5)ConcurrentHashMap的扩容是怎么进行的?
(6)ConcurrentHashMap是否是强一致性的?
(7)ConcurrentHashMap不能解决哪些问题?
(8)ConcurrentHashMap除了并发安全,还有哪些与HashMap不同的地方,为什么要那么实现?
(8)ConcurrentHashMap中有哪些不常见的技术值得学习?
如何提出问题
很多人会说,我也知道要提出问题,但是该怎么提出问题呢?
这确实是很困难的一件事,笔者认为主要是三点:
(1)问自己
把自己当成面试官问自己,往死里问的那种。
如果问自己问不出几个问题,也不要紧,请看下面。
(2)问互联网
很多问题可能自己也想不到,那就需要上网大概查一下相关的博客,看人家有没有提出什么问题。
或者,查询相关面试题。
比如,笔者学习ConcurrentHashMap这个类时,上网一查很多都是基于jdk7的,那这时候就可以提出一个问题,jdk8与jdk7中ConcurrentHashMap这个类的实现方式有何不同?jdk8对jdk7作了哪些优化?
(3)不断发现问题
在源码阅读的过程中,可能看着看着就遇到个问题,这是非常常见的,这种问题也应该保留下来研究研究。
比如,ConcurrentHashMap中size()方法是怎么实现的?@sun.misc.Contended
这玩意是什么鬼东西?然后上网一查,与是为了避免伪共享,我X,伪共享
又是啥?然后你再查一下伪共享
,又出来了CPU多级缓存?学完CPU多级缓存,是不是觉得跟jvm的内存模型很像?问完这一连串问题,是不是感觉世界都清晰了?_
看吧,问题是源源不断地被发现的。
所以,一开始提不出几个问题也不要紧,关键是要看,看了才能发现更多的问题。
带着问题阅读源码,忽略不必要的细节,死磕重要的细节
首先,一定要带着问题阅读源码。
其次,一定要忽略不必要的细节。
再次,一定要死磕重要的细节。
乍一看,后面两步似乎有所矛盾,其实不然,忽略不必要的细节是为了不迷失在源码的世界中,死磕重要的细节是为了弄清楚源码的真相。
这里的细节是忽略还是死磕,主要是看跟问题的相关性。
jdk源码还是比较好阅读的,如果后面看spring的源码,做不到忽略不必要的细节,真的是会迷失的,先埋个伏笔哈~~
举个例子,之前阅读过ArrayList的序列化相关的代码中的readObject()方法。
s.readInt();
这行是干嘛的?省略行不行?这时候就要去了解序列化相关的知识,然后看看writeObject()里面的实现,这就是要死磕的代码。
SharedSecrets.getJavaOISAccess().checkArray(s, Object[].class, capacity);
这行又是干嘛的?乍一看,好像是跟权限相关的代码,跟我们的问题“序列化”无关,忽略之,如果实在想知道,先打个标记,等把序列化的问题解决了再来研究这个东西。
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
// 声明为空数组
elementData = EMPTY_ELEMENTDATA;
// 读入非transient非static属性(会读取size属性)
s.defaultReadObject();
// 读入元素个数,没什么用,只是因为写出的时候写了size属性,读的时候也要按顺序来读
s.readInt();
if (size > 0) {
// 计算容量
int capacity = calculateCapacity(elementData, size);
SharedSecrets.getJavaOISAccess().checkArray(s, Object[].class, capacity);
// 检查是否需要扩容
ensureCapacityInternal(size);
Object[] a = elementData;
// 依次读取元素到数组中
for (int i=0; i<size; i++) {
a[i] = s.readObject();
}
}
}
多做比较
在阅读jdk源码的时候,还有很重要的一点,就是要多做比较,比较也可以分为横向比较和纵向比较。
(1)横向比较
就是与相似的类做比较。比如,集合模块中,基本都是各种插入、查询、删除元素,那这时候可以从数据结构、时间复杂度等维度进行比较,这就是横向比较。
(2)纵向比较
可以从集合发展的历史进行比较。比如,HashMap的发展史,从(单个数组)实现(没错,可以直接用一个数组实现HashMap),到(多数组+链表)实现,再到jdk8中的(多数组+链表+红黑树)实现,这就是纵向比较。
多做实验
最后一步,最最最最重要的就是要多做实验。
比如,ConcurrentHashMap是不是强一致性的?
可以启动多个线程去不断调用get()、put()、size()方法,看看是不是强一致性的。
耐心&坚持
这一点我不多说,大家都懂得。
不管是什么领域,耐心&坚持都是最难能可贵的品质。
阅读源码也是一样,只要耐心地坚持下去,终将有所收获。
彩蛋
哎呀,一不小心透露了下一章ConcurrentHashMap的内容。
大家可以用本篇所说的方法试着阅读一下ConcurrentHashMap的源码,下一章我们再一起学习哈哈~~
如何阅读jdk源码?的更多相关文章
- 如何阅读JDK源码
JDK源码阅读笔记: https://github.com/kangjianwei/LearningJDK 如何阅读源码,是每个程序员需要面临的一项挑战. 为什么需要阅读源码?从实用性的角度来看,主要 ...
- 《大牛到底是如何阅读JDK源码的?》一起来学习一下
前言: 如何阅读源码,是每个程序员需要面临的一项挑战,为什么需要阅读源码?从实用性的角度来看,主要有三个目的: 第一,解决手头的新问题或者新需求; 第二,真正理解一部分理论的落地实现; 第三,应对面试 ...
- 如何有效的阅读JDK源码
阅读Java源码的前提条件: 1.技术基础 在阅读源码之前,我们要有一定程度的技术基础的支持. 假如你从来都没有学过Java,也没有其它编程语言的基础,上来就啃<Core Java>,那样 ...
- 使用NetBeans、Eclipse阅读JDK源码
下面说明在Netbeans.Eclipse环境下怎么查看JDK源码: Netbeans: 在"工具->java平台->源"里添加下路径,如果你安装jdk的时候选择安装了 ...
- 关于阅读JDK源码的准备
说明:本篇是给自己看的. 笑 最近突然有冲动 想研究下JDK的源码,搜索了一番,基本上推荐从集合开始,精华部分包括:集合.IO.多线程.网络编程. 虚拟机部分先放一放吧,感觉现在不适合我这种半路出家的 ...
- 阅读jdk源码的流程(从今天开始要阅读jdk源码)
1.java.lang 2.java.util 3.java.util.concurrent 4.java.util.concurrent.atomic 5.java.lang.reflect 6.j ...
- JDK源码阅读顺序
很多java开发的小伙伴都会阅读jdk源码,然而确不知道应该从哪读起.以下为小编整理的通常所需阅读的源码范围. 标题为包名,后面序号为优先级1-4,优先级递减 1.java.lang 1) Obj ...
- JDK源码学习--String篇(二) 关于String采用final修饰的思考
JDK源码学习String篇中,有一处错误,String类用final[不能被改变的]修饰,而我却写成静态的,感谢CTO-淼淼的指正. 风一样的码农提出的String为何采用final的设计,阅读JD ...
- Eclipse用法和技巧二十三:查看JDK源码
使用java开发,如果能阅读JDK的经典代码,对自己的水平提高是很有帮助的.笔者在实际工作中总结了两种阅读JDK源码的方式.第一种下载android源代码,直接在android源码代码中,这里的代码虽 ...
随机推荐
- SQL反模式学习笔记5 外键约束【不用钥匙的入口】
目标:简化数据库架构 一些开发人员不推荐使用引用完整性约束,可能不使用外键的原因有一下几点: 1.数据更新有可能和约束冲突: 2.当前的数据库设计如此灵活,以至于不支持引用完整性约束: 3.数据库为外 ...
- 在SOUI中使用窗口自適應大小
SOUI 2.5.0.3開始支持窗口大小自適應. 2.5.0.3以前,宿主窗口要適應顯示內容大小比較麻煩,因爲一般都是佈局內容適應宿主. SOUI 2.5.+開始支持線性佈局,線性佈局是借鑑的Andr ...
- pwn易忘操作原理笔记
堆溢出漏洞: 一.null-byte-off-by-one 漏洞原理:由于输入操作失误,导致可以把size最低字节修改为\x00,overlapchunk利用. 构造 1.freeB,此时C的pres ...
- hibernate-release-5.2.9.Final
链接:https://pan.baidu.com/s/1UaoaaXb5C9gJp3Yu7sjUVQ 提取码:orgx
- 2018年多校第四场第二题 B. Harvest of Apples hdu6333
题意:给定10^5以内的n,m求∑组合数(n,i),共10^5组数据. 题解: 定义 S(n, m) = \sum_{i = 0} ^ {m} {n \choose i}S(n,m)=∑i=0m ...
- net view ERROR 6118
如上图,使用net view命令出现错误6118(server2012),谷歌百度油管解决了. 尝试1: 把Computer Browser服务打开.https://blog.csdn.net/qq_ ...
- java简单框架设计
设计框架包可以作为一个工具给大家用,需要有完全不同设计思路给出来,不同于我们去做一个web服务.网站. 或者一个业务微服务,需要从原来使用视角转换成一个构建者视角. 框架或者工具,更多是框架来管理或者 ...
- H5如何解监听页面退出需求???
事发背景(时间较久): 在一个阳光明媚的一天,这天lz正在工位上悠闲的敲着代码:说时迟那时快,运营小姐姐箭步过来,让lz做一个挽留弹窗:我当时一听这TM不是流氓么.于是便有了以下的故事... 如何实现 ...
- CSS、常用标签属性
div的样式:[width:宽度 :100像素.height:高度100px.background:背景颜色红色] 内嵌的形式:用<style type="text/css>&l ...
- RabbitMQRPC 官方demo
public class RPCServer { public static void Test() { var factory = new ConnectionFactory() { HostNam ...