### 阅读 JDK 源码环境搭建
**使用IDEA搭建环境**
- **推荐文章: https://blog.csdn.net/IT_Migrant_worker/article/details/104743218 **
- **挂机了**
#### 为什么需要阅读JDK源码
- **面试跑不掉**。现在只要面试Java相关的岗位,肯定或多或少会会涉及JDK源码相关的问题。
- **弄懂原理才不慌**。我们作为JDK的使用者,虽然说天天用得很开心,但是有时候遇到问题还是得跟到底层源码去看看,才能帮助我们更好的弄懂原理,
- **学习优秀的代码、思想和模式**。JDK毕竟是一个优秀的代码库,我们天天用,源码也就在里面,作为一个有志向的程序员,读一读源码也能让我们吸取到更多优秀的思想和模式。
- **睡前催眠**。额 …… 不过的确有效(滑稽)。
像JDK这种源码,和我们平常练手写小例子、写业务代码不一样,人家毕竟是 **类库**,为了**性能**、**稳定性**、**通用性**,**扩展性**等因素考虑,加入了很多**辅助代码**、**泛型**、以及一些**设计模式**上的考量,所以看起来肯定没有那么轻松,**没办法一眼看穿它**。
所以这玩意儿肯定是一个长期的过程,我个人建议(包括我自己也是这样),有时候遇到一些问题,可以针对性地把某些组件或者某个部分的源码,跟到底层去看看,然后做点笔记,写点注释啥的,这样慢慢就能渗透到很多的内容了。
但是我们一定要有足够的信心,我坚信代码人家都写出来了,我就不信我看不懂!
#### **源码该怎么看**
- **方法一:按需阅读**。如果对某个组件、语法或者特性感兴趣,或者遇到什么问题疑惑,可以有针对性地跟到底层源码按需查看,这也是一种比较高效,能快速树立信心的阅读方式。
- **方法二:系统化阅读**。具体阅读内容和顺序建议下文详述。
- **多调试**:如果仅仅靠眼睛看,然后脑补画面调试还是比较吃力的,最好还是借助IDE动手调试起来,走两步就知道了。
- **别光读,记得读完留下点什么**。我觉得看了多少不重要,重要的是能输出多少,多总结、归纳,写注释,记笔记
#### 搭建源码阅读调试环境
我个人觉得看源码这个事情还是应该单独搞一个Java工程,源码放里面,测试代码也放里面,**集中调试**,**集中看代码**,**集中写注释**比较方便一些。
##### 创建源码阅读项目
选择最普通的Java基础项目即可:
![1595035224653](../运维篇/images/1595035224653.png)
![1595035304696](../运维篇/images/1595035304696.png)
##### 创建1个目录
为:
- `cn.icanci.test`:放置测试代码,里面还可以按需要建立层级子目录
- 然后将源码复制到`src`即可
##### 导入JDK源码
有很多小伙伴问**JDK的源码在哪里呢?**
远在天边,仅在眼前,其实在的**JDK安装目录**下就能找到。
JDK安装目录下有一个名为`src.zip`压缩包,这正是JDK源码!
![1595035420962](../运维篇/images/1595035420962.png)
将其解压后拷贝到上面项目的`src`目录下,这样JDK源码就导入好了。
有些小伙伴会有疑问,**为什么要将JDK源码导一份放到这个项目里**?其实主要原因还是方便我们在源码里阅读、调试、以及做笔记和注释。
##### 调试并运行
我们可以在`test`目录里去随意编写一段测试代码。
比如我这里就以`HashMap`为例,在`test`目录下创建一个子目录`hashmap`,然后在里面创建一个测试主入口文件`Test.java`,随意放上一段测试代码:
```java
public class Test {
public static void main(String[] args) {
Map hashMap = new HashMap<>();
hashMap.put("k1", 0.1);
hashMap.put("k2", 0.2);
hashMap.put("k3", 0.3);
hashMap.put("k4", 0.4);
for (Map.Entry entry : hashMap.entrySet()) {
System.out.println(entry.getKey() + ":" + entry.getValue());
}
}
}
```
然后启动调试即可。
不过接下来会有几个问题需要一一去解决。
**问题一:启动调试时Build报错,提示系统资源不足**
**解决方法:** 加大`Build process heap size`。
设置方法:`Preferences --> Build,Execution,Deployment --> Compiler`,将默认`700`的数值加大,比如我这里设置为`1700`
![1595036763419](../运维篇/images/1595036763419.png)
**问题二:缺少类**
- 程序包com.sun.tools.javac.api不存在
- 找不到sun.awt.UNIXToolkit
- 找不到sun.font.FontConfigManager
![1595036686316](../运维篇/images/1595036686316.png)
![1595037184469](../运维篇/images/1595037184469.png)
![1595037088581](../运维篇/images/1595037088581.png)
###### 程序包com.sun.tools.javac.api不存在
手动将jdk安装目录下lib包中tools.jar添加到项目中
File ->Project Structure->Project Settings ->Libraries
![1595037312327](../运维篇/images/1595037312327.png)
###### 找不到sun.awt.UNIXToolkit、找不到sun.font.FontConfigManager
解决缺少的这两个类,可以去[OpenJDK(传送门)](http://openjdk.java.net/)拷贝
此处代码太长就不在贴出
找到[FontConfigManager](http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/beb15266ba1a/src/solaris/classes/sun/font)类,将FontConfigManager类中的内容( [传送门](http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/beb15266ba1a/src/solaris/classes/sun/font/FontConfigManager.java))拷贝到项目的src\main\java\下,新建“sun\font”包中的新建“FontConfigManager.java”中
###### 然后发现还有依赖
**那就把丢失依赖的方法注释掉**
因为不是核心方法,可以暂时先不看
另外有的时候可能会点进class文件
![1595039060061](../运维篇/images/1595039060061.png)
可以把这里的jar包全部去掉
##### 查看源码的顺序
![1595039209005](../运维篇/images/1595039209005.png)
具体的内容简介如下:
**1、`java.lang`**
这里面其实就是Java的基本语法,比如各种基本包装类型(`Integer`、`Long`、`Double`等)、基本类(`Object`,`Class`,`Enum`,`Exception`,`Thread`)等等...
**2、`java.lang.annotation`**
包含Java注解基本元素相关的源码
**3、`java.lang.reflect`**
包含Java反射基本元素相关的代码
**4、`java.util`**
这里面放的都是Java的基本工具,最典型和常用的就是各种容器和集合(`List`、`Map`、`Set`)
**5、`java.util.concurrent`**
大名鼎鼎的JUC包,里面包含了Java并发和多线程编程相关的代码
**6、`java.util.function` +`java.util.stream`**
包含Java函数式编程的常见接口和代码
**7、`java.io`**
包含Java传统I/O相关的源码,主要是面向字节和流的I/O
**8、`java.nio`**
包含Java非阻塞I/O相关的源码,主要是面向缓冲、通道以及选择器的I/O
**9、`java.time`**
包含Java新日期和期间相关的代码,最典型的当属`LocalDateTime`、`DateTimeFormatter`等
**10、`java.math`**
主要包含一些高精度运算的支持数据类
**11、`java.math`**
主要包含一些高精度运算的支持数据类
**12、`java.net`**
主要包含Java网络通信(典型的如:`Socket`通信)相关的源代码。
一键复制
编辑
Web IDE
原始数据
按行查看
历史