JavaでJDK(Java Developmet Kit)、JRE(Java Runtime Enviroment)の構成がOS(Operation System)で異なってるらしい

f:id:ts0818:20201226134957j:plain

ジャワコーヒーインドネシアジャワ島を産地とするコーヒー豆。または、そのコーヒー豆でいれたコーヒー

ジャワコーヒー - Wikipedia

アメリカでJavaプログラマーしてる場合、言葉に行き違いとか起こることがないのか気になる、どうもボクです。

ということで、今回もJavaについてです。(coffeeの話じゃないですよ)

レッツトライ~。 

 

JDKJava Developmet Kit)、JREJava Runtime Enviroment)の構成がOS(Operation System)で異なるって

意識したことなかったんだけど、OS(Operation System)毎にJDKJava Developmet Kit)、JREJava Runtime Enviroment)の構成が異なってたらしいね。

docs.oracle.com

/jdk-interim.update.patch.jdk/lib

ランタイム・システムのプライベート実装の詳細。これらのファイルは外部使用を意図していないので、編集しないでください。

macOS上のlibディレクトリまたはLinuxSolaris上のlib/$ARCHディレクトリには、ランタイム・システムの動的リンク型のネイティブ・ライブラリが含まれています。

https://docs.oracle.com/javase/jp/11/install/installed-directory-structure-jdk.html#GUID-F7178F2F-DC92-47E9-8062-CA6B2612D350

⇧ はい、まさかのJavaの世界でもWindowsは除け者にされるというね...

って言うか、インストールされた段階ですでに選別されてるという、哀しき宿命、でも仕方ないようね、OS(Operation System)によってファイルシステムとか異なるんだし。

というわけで、確認してみました。

  

まずは、ザックリと全体の構成。

Linux版(RPMパッケージ)のJDK

/usr/java/jdk-15.0.1/
  -.java
  -bin
  -conf
  -include  
  -jmods  
  -legal  
  -lib  
  -man  
  release

f:id:ts0818:20201225192210p:plain

Windows版(アーカイブ)のJDK

C:\Program Files\Java\jdk-15.0.1\
  -bin
  -conf
  -include
  -jmods
  -legal
  -lib
  release

f:id:ts0818:20201225192321p:plain

⇧ ってな感じで、この時点で既に構成が変わってはいるんだけど、ここでOracleさんの説明でも最も差異があるであろう、「lib」ディレクトリの中身を確認してみました。

Linux版(RPMパッケージ)のJDKの「lib」ディレクトリの中身

drwxr-xr-x  6 root root      4096 Dec  8 04:32 .
drwxr-xr-x 10 root root      4096 Dec  8 04:32 ..
-rw-r--r--  1 root root     40100 Sep 15 13:56 classlist
-rw-r--r--  1 root root   8046622 Sep 15 13:56 ct.sym
drwxr-xr-x  5 root root      4096 Dec  8 04:31 desktop
-rwxr-xr-x  1 root root     13128 Sep 15 13:56 jexec
drwxr-xr-x  2 root root      4096 Dec  8 04:31 jfr
-rw-r--r--  1 root root    107179 Sep 15 13:56 jrt-fs.jar
-rwxr-xr-x  1 root root     18320 Sep 15 13:56 jspawnhelper
-rw-r--r--  1 root root        29 Sep 15 13:56 jvm.cfg
-rw-r--r--  1 root root     13464 Sep 15 13:56 libattach.so
-rw-r--r--  1 root root    794984 Sep 15 13:56 libawt.so
-rw-r--r--  1 root root     43936 Sep 15 13:56 libawt_headless.so
-rw-r--r--  1 root root    472056 Sep 15 13:56 libawt_xawt.so
-rw-r--r--  1 root root     28216 Sep 15 13:56 libdt_socket.so
-rw-r--r--  1 root root     13448 Sep 15 13:56 libextnet.so
-rw-r--r--  1 root root   1455240 Sep 15 13:56 libfontmanager.so
-rw-r--r--  1 root root     51016 Sep 15 13:56 libinstrument.so
-rw-r--r--  1 root root     47648 Sep 15 13:56 libj2gss.so
-rw-r--r--  1 root root     18240 Sep 15 13:56 libj2pcsc.so
-rw-r--r--  1 root root     88688 Sep 15 13:56 libj2pkcs11.so
-rw-r--r--  1 root root      8368 Sep 15 13:56 libjaas.so
-rw-r--r--  1 root root    189752 Sep 15 13:56 libjava.so
-rw-r--r--  1 root root    240640 Sep 15 13:56 libjavajpeg.so
-rw-r--r--  1 root root      8368 Sep 15 13:56 libjawt.so
-rw-r--r--  1 root root    287016 Sep 15 13:56 libjdwp.so
-rw-r--r--  1 root root    146504 Sep 15 13:56 libjimage.so
-rw-r--r--  1 root root     73704 Sep 15 13:56 libjli.so
-rw-r--r--  1 root root     13472 Sep 15 13:56 libjsig.so
-rw-r--r--  1 root root     81104 Sep 15 13:56 libjsound.so
-rw-r--r--  1 root root    518496 Sep 15 13:56 liblcms.so
-rw-r--r--  1 root root     26112 Sep 15 13:56 libmanagement.so
-rw-r--r--  1 root root      8408 Sep 15 13:56 libmanagement_agent.so
-rw-r--r--  1 root root     29432 Sep 15 13:56 libmanagement_ext.so
-rw-r--r--  1 root root    620128 Sep 15 13:56 libmlib_image.so
-rw-r--r--  1 root root    105104 Sep 15 13:56 libnet.so
-rw-r--r--  1 root root     95432 Sep 15 13:56 libnio.so
-rw-r--r--  1 root root     12600 Sep 15 13:56 libprefs.so
-rw-r--r--  1 root root      8112 Sep 15 13:56 librmi.so
-rw-r--r--  1 root root     70768 Sep 15 13:56 libsaproc.so
-rw-r--r--  1 root root     28520 Sep 15 13:56 libsctp.so
-rw-r--r--  1 root root    367088 Sep 15 13:56 libsplashscreen.so
-rw-r--r--  1 root root    330376 Sep 15 13:56 libsunec.so
-rw-r--r--  1 root root     64832 Sep 15 13:56 libverify.so
-rw-r--r--  1 root root     41960 Sep 15 13:56 libzip.so
-rw-r--r--  1 root root 137288110 Sep 15 13:56 modules
-rw-r--r--  1 root root      2796 Sep 15 13:56 psfont.properties.ja
-rw-r--r--  1 root root     10393 Sep 15 13:56 psfontj2d.properties
drwxr-xr-x  2 root root      4096 Dec  8 04:32 security
drwxr-xr-x  2 root root      4096 Dec  8 04:32 server
-rw-r--r--  1 root root  47886912 Sep 15 13:56 src.zip
-rw-r--r--  1 root root    107773 Sep 15 13:56 tzdb.dat

Windows版(アーカイブ)のJDKの「lib」ディレクトリの中身

<DIR>          .
<DIR>          ..
        41,716 classlist
     8,046,626 ct.sym
         4,630 fontconfig.bfc
        11,348 fontconfig.properties.src
         1,682 jawt.lib
<DIR>          jfr
       107,503 jrt-fs.jar
            29 jvm.cfg
       898,786 jvm.lib
   135,635,613 modules
         2,796 psfont.properties.ja
        10,393 psfontj2d.properties
<DIR>          security
    47,338,641 src.zip
       107,773 tzdb.dat
        22,086 tzmappings
14 個のファイル          192,229,622 バイト
 4 個のディレクトリ  179,435,204,608 バイトの空き領域

⇧ お分かりいただけただろうか?

そう、「DLL(Dynamic Link Library)」 の数が段違いなんである。

Linux版のJDKの「lib」ディレクトリには、DLLファイルである「.so」ファイルが相当数あるというのに、Windows版のJDKの「lib」ディレクトリには、DLLファイルである「.dll」は僅かに2つ存在するばかりというね。

 

JDKJava Developmet Kit)のソースコードを取得してコンパイル前の状態を確認してみる

何か、JDKJava Developmet Kit)に限らないと思うけど、ソースコードの状態(コンパイル前)であれば、DLL(Dynamic Link Library)ファイルになる前の状態とかも確認できるみたい。

qiita.com

⇧ 上記サイト様が詳しいです。

 

ちなみに、JDK(ここでは、コンパイル後のもの。つまり自力でソースコードからコンパイルしない通常のインストールでのJDK)のDLL(Dynamic Link Library)を逆コンパイルして、C言語とかの内容を確認することもできるらしいんですが、

kaworu.jpn.org

Unix の objdump コマンドは、オブジェクトファイルの情報を表示するためのツールです。 objdump を利用すると ELF のファイルからアセンブラのソースを出力することができます。

ELF実行ファイルをobjdumpでCのソースコード付きで逆アセンブルする方法 - C言語入門

⇧ 上記サイト様が詳しいです。

コンパイルはどうしても完全にソースコードとして復元ってのは難しいみたいですね。

 

脱線しましたが、

hg.openjdk.java.net

If you are eager to try out building the JDK, these simple steps works most of the time. They assume that you have installed Mercurial (and Cygwin if running on Windows) and cloned the top-level JDK repository that you want to build.

  1. Get the complete source code:
    hg clone http://hg.openjdk.java.net/jdk/jdk

  2. Run configure:
    bash configure

    If configure fails due to missing dependencies (to either the toolchainbuild toolsexternal libraries or the boot JDK), most of the time it prints a suggestion on how to resolve the situation on your platform. Follow the instructions, and try running bash configure again.

  3. Run make:
    make images

  4. Verify your newly built JDK:
    ./build/*/images/jdk/bin/java -version

  5. Run basic tests:
    make run-test-tier1

If any of these steps failed, or if you want to know more about build requirements or build functionality, please continue reading this document.

http://hg.openjdk.java.net/jdk/jdk/raw-file/tip/doc/building.html

⇧ってな感じで、ソースコードの状態のJDKを取得することができるみたい。(ソースコードの状態のJDKをちゃんと機能するJDKにするには、ソースコードコンパイルまでする必要あり)

バージョンによって 

⇧ ってな感じで、JDK9以降だと、「http;//hg.openjdk.java.net/jdk-updates」にあるものを取得する感じですかね。

あとは、

⇧「tag」から詳細なバージョンとか選べるみたい。

確認できました。

f:id:ts0818:20201225210208p:plain

というわけで、ソースコードの状態のJDKを取得していこうと思いますが、ダウンロードする場所ですが、Docker ToolBoxで作成した仮想マシンに、Dockerコンテナを作成して、そのコンテナの中に配置する感じで。

Dockerコンテナの元となるDockerイメージについては、Docker Hubの公式のCentOS 8を使ってます。(CentOS 8は2021年で開発終了しちゃうみたいなので、他のLinuxディストリビューションを選んだほうが良いかも...)

f:id:ts0818:20201225210928p:plain

DockerイメージをDocker Hubから取得したらば、Dockerコンテナを作成・起動します。(Dockfileとかで自分で作成したDockerイメージを使ってDockerコンテナ作成・起動でもOK)

f:id:ts0818:20201225212331p:plain

で、「OpenJDK」のソースコードをダウンロードしようとしたら、はい、エラー。

f:id:ts0818:20201225212852p:plain

どうやら、

www.uramiraikan.net

 最近はバージョン管理システムにGitを使うことが多いですが、個人的にはMercurialを長年使ってきたこともあり、Gitへ移行していないプライベートレポジトリにアクセスするため個人の作業環境にはMercurialをインストールすることが多いです。

CentOS 7へのMercurialインストールについて | Works | URAMIRAIKAN

⇧「Mercurial」ってツールをインストールする必要があったみたいね...

確かに、公式の「http://hg.openjdk.java.net/jdk/jdk/raw-file/tip/doc/building.html」をよく見たら「you have installed Mercurial (and Cygwin if running on Windows)」って記載されてました...反省。

というわけで、いざ。

yum install epel-release   

f:id:ts0818:20201225213339p:plain

f:id:ts0818:20201225213404p:plain

f:id:ts0818:20201225213441p:plain

CentOS 8 からは

genchan.net

⇧ Python3 をインストールってことみたいね。

yum -y install python3

f:id:ts0818:20201225213823p:plain

f:id:ts0818:20201225214001p:plain

何か、pipが見つからんとか言われるし...

f:id:ts0818:20201225214348p:plain

⇧ 既にインストールされてるって言うけど、

エラーになるやん...

f:id:ts0818:20201225214548p:plain

まさかの、pipもpip3って付けないといけなかったみたい...

そして、python3-devel もインストールが必要だったみたい...

yum install -y python3-devel

f:id:ts0818:20201225215209p:plain

f:id:ts0818:20201225215236p:plain

gccもインストールが必要だった...

yum install -y gcc

f:id:ts0818:20201225215606p:plain

三度目の正直

pip3 install mercurial

f:id:ts0818:20201225215650p:plain

f:id:ts0818:20201225215940p:plain

改めて、OpenJDKのソースコードを取得で、エラー。

f:id:ts0818:20201225220225p:plain

細かいバージョンは指定できない?

パスを改めてソースコードが取得できたけど(hg cloneの完了にかなり時間かかります)、

f:id:ts0818:20201225224328p:plain

f:id:ts0818:20201225225145p:plain

⇧ なんか、この各ディレクトリの中を確認していくと、各OS用にディレクトリが分かれてるみたい。

試しに、「/jdk15u/src/java.base/」を見てみると、

f:id:ts0818:20201225230330p:plain

⇧ ってな感じで、コンパイル前だからC言語のファイルが確認できますね。
Linux用ってことで、

f:id:ts0818:20201225230713p:plain

⇧ cgroupとかもあるみたいね。

Windows用だと、

f:id:ts0818:20201225230904p:plain

⇧ cgroupは無いってことね。

ちなみに、「java.lang」パッケージとかに関連するファイル群は、「java.base/share」にいるみたいね。

f:id:ts0818:20201225231344p:plain

f:id:ts0818:20201225231724p:plain

というわけで、コンパイル前なら、「native修飾子」のメソッドなどの実装が確認できるっちゅうことですかね。C言語を勉強せねばですかね...


java.lang.Object#hashCode()メソッドとかも、「native修飾子」とか付いてるからコンパイルされた後のJDKからだと確認できなかったですが、ソースコードの状態であれば確認できそうですね。

stackoverflow.com

The Values are set using Native code in runtime. Its set inside the System.c, and a function called Java_java_lang_System_initProperties

https://stackoverflow.com/questions/18396535/where-which-properties-file-does-system-getpropertykey-reads-from

⇧ ってな感じで、System.getProperty("os.name")とかでどれだけのOSが定義されてるかの全量とかも確認できるんですかね?

時間のある時に、ソースコードJDKの中にあるC言語のファイルを確認してみますかね。

まぁ、JVMJava Virtual Machine)とかが、OS(Operation System)なんかのプラットフォームの差異を可能な限り減らしてくれるとはいえ、どうしても完全に同じってわけにはいかないってことですね。

そう言った意味では、

"Write once, run anywhere" (WORA、「一度(プログラムを)書けば、どこでも実行できる」)とは、Javaプログラムオペレーティングシステム (OS) などのプラットフォームに依存しないという意味の、サン・マイクロシステムズJavaスローガンである。Write once, run everywhere (WORE) ともいう。 

Write once, run anywhere - Wikipedia

⇧ まだ道半ばということでしょうかね。

 

今回はこのへんで。