如何解决: 使用OpenJDK11后, AS中无法查看Java标准类库的源代码

环境:
操作系统: macOS 11.6
shell: zsh 5.8 (x86_64-apple-darwin20.1.0)
Android Studio 版本: Android Studio Bumblebee | 2021.1.1
JDK: openjdk version "11.0.14" 2022-01-18

\color{red}{说明: 下面内容是在上面的环境下产生的! 如果是其他环境,做下相应的变通就好了。}

一、起因

2021年4月分左右 Android Studio 4.2 (Android Studio 以下简称AS)发布了。AS 4.2 对其绑定的JDK进行了升级,开始使用OpenJDK11,之前使用的是OpenJDK8,这些信息在安卓开发者网站上可以看到,如下:
AS2.2.1+ 绑定 OpenJDK8
https://developer.android.google.cn/studio/releases#new_1
AS4.2+ 绑定 OpenJDK11
https://developer.android.google.cn/studio/releases#ki-key-keystore-warning

tips: AS是在 Jetbrains 的 IntelliJ (IntelliJ社区版是开源的) 的基础上二次开发而来的。IntelliJ 是用java开发,因此要运行它,机器上就必须有一个java运行时环境,为了方便使用者,IntelliJ 就绑定了一个 JRE(Java Runtime Environment)。位于 /Applications/Android Studio.app/Contents/jre 目录。

为了跟上谷哥的步伐,我升级了JDK。从Oracle的JDK8 升级到了OpenJDK11。
这一升级,就导致了在AS中无法查看Java标准库的源代码。之前 Command+Click 可以跳转到类的源代码,现在Command+Click虽然可以跳转到源代码处,但是源代码是反编译出来的 —— 没有注释说明,格式混乱,根本没法阅读!


二、导致问题的具体原因

简单来说就是,AS到不到标准库中的类所对应的源代码文件 (源代码缺失)。

具体原因:

OpenJDK11发布的时候将源代码 和 二进制文件 进行了拆分,即OpenJDK11的二进制包中是不包含源代码的。说的更具体一点就是:OpenJDK_HOME 目录下是没有src.zip文件的。AS会加载JAVA_HOME/src.zip,并建立索引,当我们在代码中点击 (Command+Click) 标准库中的某个类(如HashMap)时,就会寻找src.zip中相应的类的源文件,然后展示。当JAVA_HOME目录下没有src.zip文件时,AS无法找到类对应的源文件,于是AS会反编译字节码文件然后展示。

说明:

  • JAVA_HOME 我们配置的环境变量,其实就是JDK的HOME目录。如,我的机器上的JAVA_HOME配置的就是 /Users/stone/my_program/AdoptOpenJDK-11/Contents/Home
  • OpenJDK_HOME 是 JDK的安装目录。例如我的机器上这个目录是/Users/stone/my_program/AdoptOpenJDK-11/Contents/Home
  • src.zip 是JDK源代码(更准确的说 src.zip压缩文件是Java标准库的源代码,后面还会说到,就不展开了)

Oracle的JDK8的Home目录下有源代码文件,即 有src.zip。
OpenJDK8的Home目录下也是有src.zip文件的。

$ cd $JAVA8_HOME
$ ls
COPYRIGHT               include
LICENSE                 javafx-src.zip
README.html             jre
THIRDPARTYLICENSEREADME-JAVAFX.txt  lib
THIRDPARTYLICENSEREADME.txt     man
bin                 release
db                  src.zip

# JAVA8_HOME 是我设置的环境变量, 值为: 
# /Library/Java/JavaVirtualMachines/jdk1.8.0_77.jdk/Contents/Home

OpenJDK 11的Home目录下没有src.zip文件

$ cd $JAVA11_HOME
$ ls
NOTICE  bin bundle  conf    include jmods   legal   lib man release

# JAVA11_HOME 是我设置的环境变量,值为: 
# /Users/stone/my_program/AdoptOpenJDK-11/Contents/Home

AS 默认的 jre 中也是没有源代码的,即jre目录下没有 src.zip

$ cd $AS_JRE_HOME
$ ls
bin conf    legal   lib release

# AS_JRE_HOME 表示AS所绑定的jre的目录,例如,我的机器上其值为:
# /Applications/Android Studio.app/Contents/jre


三、解决

解决:

下载JDK对应版本的源代码 并 放入到 JDK_HOME 目录下,即可!

具体操作:

0x01、下载JDK对应的源代码
下载地址:https://adoptium.net/releases.html?variant=openjdk11&jvmVariant=hotspot

选择版 OpenJDK11 (如果要下载JDK的二进制包,需要选择对应的操作系统 和 相应的CPU架构)


openjdk11-src.png



如果你之前安装的是比较老旧的JDK二进制包,那么你可以重新下新的二进制包 (推荐下载.tar.gz格式的二进制包,.tar.gz就是个压缩文件,解压就可以使用了,而.pkg格式的二进制包需要安装,安装时会在文件系统的不同目录写入文件,这是侵入式的,卸载的时后还得找到安装时写入的文件逐个删除,太麻烦了),如下:

openjdk11-binary.png

Mac系统中,网络上下载的OpenJDK解压后,命令行工具是无法执行的, 需要进行授权:

$ sudo xattr -r -d com.apple.quarantine /Users/stone/my_program/AdoptOpenJDK-11

# 最后一个参数指定到JDK解压后的根目录即可,当然也可以指定到Home目录
# 不授权执行JDK中的命令行工具
$ java     # 或者 javac, javah, jstat, ...

不授权执行命令行工具,会出现下面的提示框 (偷下懒,用了之前安装GraalVM时截的图):


not-execute.png



注意: 源代码和JDK的版本必须一致,否则查看标准库的源代码时,跳转到源代码的所在行可能是错误的!!
因为不同版本的JDK的源代码之间存在一定的差异!
例如,你编写的程序中使用的JDK的版本是11.0.13,而源代码的版本是11.1.72,当你在自己编写的Java源文件中 Command+Click 查看某个标准库中的类的源码时,会打开一个11.1.72版本的Java源文件,如果你 Command+Click 点击的是一个方法,那么跳转到源文件的行数可能就是错误的,因为两个内容存在差异的文件的同一个方法所在的行就有可能不在同一行 (当然也有可能在同一行)!!


0x02、解压前一步所下载的JDK源代码压缩文件 并 制作Java标准类库的源代码压缩包src.zip

前一步下载下来的源代码并不能直接使用,因为这个压缩文件中不仅包含Java标准库的源代码,还包括hotspot、java命令行工具 ... 等等一系列东西的源代码。
因此,我们需要解压这个压缩包,然后只打包Java标准库的那部分源代码。
例如: 我下载的是JDK源代码文件是 OpenJDK11U-sources_11.0.14_9.tar.gz,在finder中双击解压 (默认是调用的系统归档试用工具.app 应用解压)即可,当然,你也可以使用tar/gzip/gunzip 等命令来解压。

解压后的目录结构如下:


openjdk11-zip.png

<JDK-unpack-directory>/src/java.base/share/classes 这个目录下的源文件就是Java标准库的源文件,因此我们进入到此目录下,让后制作src.zip文件。

# 我们是如何确定src.zip文件的内部结构的??
# Oracle的JDK8不是有src.zip源文件嘛,我们直接查看一下不就可以确认了

# 进入到Oracle JDK8中确认src.zip文件的内部结构。
$ cd $JAVA8_HOME
$ unzip -l src.zip # 输出了其他无用信息, 我们换一种方式来查看zip包中的结构
# 查看src.zip包中的结构
$ tar -tf src.zip
$ tar -tf src.zip | head -n 20 # 输出太多,限制一下,只显示前20条

# 经过上面的操作,可以确认,src.zip中就是java类的源文件 (按package对应的目录结构存放),没有其他目录路结构。

# 这样就可以确认 <JDK-unpack-directory>/src/java.base/share/classes 目录下的内容,就是我们要打包的内容
# 那么接下来就制作一个src.zip
$ cd <JDK-unpack-directory>/src/java.base/share/classes # 进入到目标目录,<JDK-unpack-directory> 这个是JDK的解压目录,可以按自己的具体情况进行替换
$ zip -r src.zip ./*  # 打包当前目录下的所有内容



# 也许你会有一个疑问,zip打包当前目录下的所有内容,而生成内容也在当前目录下,那么生成内容会不会也被打包呢??
# 答案是否定的。

# 我们可以对生成的src.zip进行验证,验证方法如下:
$ tar -tf src.zip > ~/temp/dir-list.txt  # 列出刚刚生成的src.zip中的内容并输入到一个filelist.txt的文件中
# 接下来打开filelist.txt文件查看一下其中有没有src.zip。
# 当然,filelist.txt文件中并没有出现src.zip


0x03 将前一步制作的 src.zip 文件复制到缺少源代码的JDK的HOME目录中。

然后重启一下AS (其实也不用重启,我复制完src.zip后,发现AS马上就在重建索引了 —— AS底部可以看到)。

至此,我们就可以愉快的阅读OpenJDK的源代码啦 !!



前面说过,下载JDK源代码和二进制包的时候,二者版本必须相同,否则就不能准确的查看源代码了!这个需要特别注意!

JDK版本和源代码版本必须一致



tips: AS是是如何使用指定版本的JDK来编译我们的java代码的呢?
编译我们自己写的Java源文件所使用的JDK,是可以动态配置,操作如下:
在AS中, 按 Command+, 打开 Preferences 界面, 然后设置JAVA_HOME 即可!! AS就是使用JAVA_HOME所指定的JDK的 。

设置JAVA_HOME环境变量

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 196,763评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,728评论 2 374
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,834评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,707评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,576评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,429评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,826评论 3 388
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,474评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,762评论 1 293
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,792评论 2 314
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,582评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,424评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,845评论 3 300
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,059评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,361评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,826评论 2 343
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,038评论 2 338