Testing the JDK
因为好奇心,想看下 jdk 的 test 怎么写的,然后就有了这篇游记。
下载 jdk 源码,哦,是OpenJDK。呃,网络不好,那git clone --depth=1
吧,然后git fetch--depth=N
,可以将 N 一直加大到无穷。
开箱一看,但是里面怎么感觉有点乱呀。。。
$ ls test/jdk/java/util/ArrayList/ AddAll.java ArrayManagement.java Bug6533203.java Bug8146568.java EnsureCapacity.java IteratorMicroBenchmark.java RangeCheckMicroBenchmark.java
好吧,我先去邮件列表看看是否有人也如我懵懂无知,看完Unit tests for OpenJDK?,哦,原来是 OpenJDK 自从 SUN 2006 年放出代码之前高司令们就已经开发了了将近 10 年(1.0 是 1995 年 5 月释出的),很多测试依赖 JCK 2,单元测试,和功能测试,而这些不在 OpenJDK 当中(或许 Sun 发布时出于某些原因删除了?),所以老的代码很多没有测试,但是新的代码测试覆盖就很全了。 邮件列表中还建议去 Youtube 搜索相关视频。(Alan Bateman OR Stuart Marks) openjdk test ,我找到了这个Meet the OpenJDK Tests。 视频里介绍了 quality discuss 邮件列表。可以围观下最新的测试结果OpenJDK 13 Early Access Build Test Results。
以 JDK-8196207 Inefficient ArrayList.subList().toArray()为例,之前代码是调用 AbstractColleciton 的 toArray 方法
public Object[] toArray() { // Estimate size of array; be prepared to see more or fewer elements Object[] r = new Object[size()]; Iterator<E> it = iterator(); for (int i = 0; i < r.length; i++) { if (! it.hasNext()) // fewer elements than expected return Arrays.copyOf(r, i); r[i] = it.next(); } return it.hasNext() ? finishToArray(r, it) : r; }
一个个元素来。。。所以可以改进,e3dcdd73a549 就直接调用 Arrays.copyOfRange 或者 System.arraycopy
+ public Object[] toArray() { + checkForComodification(); + return Arrays.copyOfRange(root.elementData, offset, offset + size); + } + + @SuppressWarnings("unchecked") + public <T> T[] toArray(T[] a) { + checkForComodification(); + if (a.length < size) + return (T[]) Arrays.copyOfRange( + root.elementData, offset, offset + size, a.getClass()); + System.arraycopy(root.elementData, offset, a, 0, size); + if (a.length > size) + a[size] = null; + return a; + }
至于这两个 copy 的区别就是,copyOfRange 会调用 arraycopy。 1 2 而这个改动的测试就在两个不同的 IteratorMicroBenchmark.java 里,嗯,你没看错,两个,一个是 ArrayList 目录下,另一个是 Collection 目录下。
另一个实例就是 寒泉子 提的这个小修正 GC Metaspace printing after full gc, commit。而这次测试文件路径为 test/hotspot/jtreg/gc/logging/TestMetaSpaceLog.java ,还提交了个 jar 文件到 test/hotspot/jtreg/gc/logging/testcases.jar。
jtreg¶
好,主角上场了,Regression Test Harness for the JDK: jtreg,我估计全称就是 java test regression。 An Introduction to jtreg里介绍了支持的几种测试,API 测试,编译测试,Applet 测试,以及 Shell 测试,三种 JVM 模式 othervm, samevm, agentvm。而一个 jtreg 测试就是简单用退出状态来判定是否达到预期(当然 negative 测试就是要异常退出)。
$ find . -name TEST.ROOT ./test/jdk/TEST.ROOT ./test/langtools/TEST.ROOT ./test/hotspot/jtreg/TEST.ROOT ./test/nashorn/TEST.ROOT ./test/failure_handler/test/TEST.ROOT ./test/jaxp/TEST.ROOT ./make/langtools/test/TEST.ROOT
Build¶
磁盘大概 8G(编译后大概 6G),普通 2G1CPU 大约半个小时,8G8CPU 大约 4 分钟。 Building OpenJDK
sudo apt-get install libx11-dev libxext-dev libxrender-dev libxrandr-dev libxtst-dev libxt-dev libcups2-dev libfontconfig1-dev libasound2-dev libelf-dev # 需要先准备版本为N-1的boot JDK,我是sdkman安装的`sdk install java 12.0.1-open` # build and install jtreg first, https://openjdk.java.net/jtreg/ bash configure --with-jtreg=$HOME/jtreg make images # Build the JRE and JDK images ./build/*/images/jdk/bin/java -version openjdk version "13-internal" 2019-09-17
Test¶
run-test-tier1 可能需要跑一两个小时,还需要大约 20G 的硬盘。。。
sudo apt install jtreg # 不要选择带有@ignore 标签或者在ProblemList.txt的测试 make test TEST="jtreg:test/jdk/java/util/AbstractList" # test-only will ignore source file change
参考¶
- 面对 JDK 的 BUG 该如何是好?, 深入理解 Java 虚拟机 #01# 自己编译 JDK
- Differences Between Oracle JDK and OpenJDK
- Android's Java 9, 10, 11, and 12 Support
- JEP proposed to drop from JDK 12: 326: Raw String Literals (Preview)
- JDK 9 学习笔记 - (1)开发环境准备
-
Why is Arrays.copyOf 2 times faster than System.arraycopy for small arrays? What is more efficient: System.arraycopy or Arrays.copyOf? ↩
-
JCK(Java Compatibility Kit ),这个是兼容性测试,需要单独获取,可以先阅读 azul 的这篇Why would you risk your apps on an uncertified JVM?。获取方式参考Gaining Access to the JCK,现在已经签署的名单在OCTLA Signatories List,看到了阿里和华为。 ↩↩