OpenJDKをソースからビルドする

自分用メモ

## ビルド依存の準備
* Boot JDK
  * ビルド対象の1つ古い奴以上新しくないといけない。
  * Java 11とかをインストールしておく (`export PATH="${PATH}:/opt/jdk-11/bin"`, `export JAVA_HOME="/opt/jdk-11"`)
     * Ubuntu bionicだと 8~11 あたりはビルドに失敗するので12をビルドする…
* ccache
  * ビルドが速くなるらしい? それでも割と遅いけど…

他にもいろいろあるけど大体 `bash configure` すると指示されるので従うとビルドできる。

## リポジトリとタグ
[公式リポジトリ](https://hg.openjdk.java.net/jdk/jdk)はmercurialだけど面倒なのでGitHubのミラーを使う。

https://github.com/openjdk/jdk

* タグはJDK 12の中だと `jdk-12-ga` が一番新しそうなのでこれをcheckoutする。

## ビルド手順

doc/building.md に書いてある: https://github.com/openjdk/jdk/blob/master/doc/building.md

### 1. bash configure
何故か実行可能属性がついてないので、 

```
bash configure
```

ところで古い奴をビルドしたければ `--disable-warnings-as-errors` も使えそう。

### 2. make images
-j がサポートされてないので、

```
make images JOBS=4
```

### 3. build/linux-x86_64-server-release/images/jdk/bin/java
```
build/linux-x86_64-server-release/images/jdk/bin/java --version
```

とかで走らせられる。

## デバッグビルド
https://github.com/openjdk/jdk/blob/jdk-12-ga/make/autoconf/jdk-options.m4#L40-L45

```bash
# Set the debug level
#    release: no debug information, all optimizations, no asserts.
#    optimized: no debug information, all optimizations, no asserts, HotSpot target is 'optimized'.
#    fastdebug: debug information (-g), all optimizations, all asserts
#    slowdebug: debug information (-g), no optimizations, all asserts
```

ステップ実行などが目的であればslowdebugにしておくとよさそう。
なお、これに加えて `--with-native-debug-symbols` もないとlauncherのデバッグシンボルが出てこない。

### 1. bash configure --with-debug-level=slowdebug --with-native-debug-symbols=internal
release用のconfigをcleanしなくても別途ビルドできる。

```
bash configure --with-debug-level=slowdebug --with-native-debug-symbols=internal
```

### 2. make images JOBS=4 CONF=linux-x86_64-server-slowdebug
別のdebug-levelでconfigureしたらCONFを明示的に指定してビルドする必要がある。

```
make images JOBS=4 CONF=linux-x86_64-server-slowdebug
```

### 3. build/linux-x86_64-server-slowdebug/images/jdk/bin/java
```
gdb build/linux-x86_64-server-slowdebug/images/jdk/bin/java
```

mainでbreakしてrunしてもソースは見れない。
https://openjdk.java.net/groups/hotspot/docs/RuntimeOverview.html とかにある `JNI_CreateJavaVM` みたいなAPIでbreakする必要がある。

## C++インタプリタを有効化してビルド
[DEMYSTIFYING THE JVM: JVM VARIANTS, CPPINTERPRETER AND TEMPLATEINTERPRETER](https://metebalci.com/blog/demystifying-the-jvm-jvm-variants-cppinterpreter-and-templateinterpreter/) によると、

* zero: Zero-Assembler port of JDK

というfeatureを有効にするとC++インタプリタが有効になる。

```
bash configure --with-jvm-variants="zero" --with-jvm-features="zero"
```

とやるとC++インタプリタでビルドできる。

## hsdis (Hotspot Disassembly) のビルド

```bash
# https://ftp.gnu.org/gnu/binutils/ からbinutilsを持ってくる (2.29.1, 2.30, 2.31.1で動作確認済らしい)
cd /tmp
wget https://ftp.gnu.org/gnu/binutils/binutils-2.31.1.tar.gz

# hsdis のディレクトリに移動
cd /path/to/openjdk
cd /src/utils/hsdis

# デフォルトで探される場所にbinutilsを配置
mkdir build
mv /tmp/binutils-2.31.1/ build/binutils

# make (32bit向けを除外)
make all64
```

/jdk/lib に置いても何故か認識されないので、`LD_LIBRARY_PATH` で直接場所を渡して使うのが吉

```bash
LD_LIBRARY_PATH="openjdk/jdk/src/utils/hsdis/build/linux-amd64:$LD_LIBRARY_PATH" \
  java -XX:+UnlockDiagnosticVMOptions -XX:+PrintInterpreter Main
```

# デバッグ用関数
デバッグシンボルがあってもJavaのフレームはbtでシンボルが出てこないが、`call pns($sp, $rbp, $pc)`とかやるといいらしい:
http://progdoc.de/papers/Joker2014/joker2014.html#(5)