GlassFish Nucleus のお話

もはや誰も把握できていないであろう GlassFish Nucleus の内部動作に関するツイートのまとめ(作成中)
0

Introduction - GlassFish Nucleus における HK2 と Weld の関係について

HASUNUMA Kenji @khasunuma_

1/25 雑に言うと、Payara は Nucleus (カーネルの下層) で HK2 (DI) と Weld (CDI) をブリッジしている「アキレス腱」のような場所があり、そこに MP Config の実装を引っ掛けている。 副次的効果として、Payara は domain.xml とか Hazelcast クラスタとかあちこちを Config ソースとして使える。 twitter.com/khasunuma/stat…

2020-02-12 01:32:10
HASUNUMA Kenji @khasunuma_

2/25 HK2 と Weld をブリッジしているところを Nucleus の「アキレス腱」と言ったが、Payara の CDI 関係のトラブルは (アプリ側の不具合を除けば) だいたいここに集中している。これは GlassFish v3 からずっと引きずっていて、GlassFish や Interstage などにも共通していること。

2020-02-12 01:32:10
HASUNUMA Kenji @khasunuma_

3/25 Nucleus は CDI (WebBeans) 登場以前の GlassFish v3 Prelude からあり、HK2 + OSGi によるモジュール・アーキテクチャになっている。HK2 は DI も持っていたので、それとブリッジするような形で Weld をぶっ込んだ。そうしないと黒魔術の塊である CDI が動作しなかった。

2020-02-12 01:32:11

HK2 はそもそも Java のモジュール・システムとして出発した

HASUNUMA Kenji @khasunuma_

4/25 もっと言うと、HK2 は当初 JSR 277 をベースとしたモジュール・システムとして開発され、Nucleus の屋台骨となるはずだった。JSR 277 は、JPMS (Project Jigsaw; JSR 376) の古い祖先にあたる仕様で、当初の JDK 7 に入れようとしていたもの。

2020-02-12 01:32:11
HASUNUMA Kenji @khasunuma_

5/25 JSR 277 は端的に言うと、JAR の代わりに Java Application Module (JAM) という新しいモジュールと JAM を支援する仕組みを導入しようという試み。JAM には JAR が持っていなかったバージョンや依存関係のメタ情報等を保持することになっていた。

2020-02-12 01:32:11
HASUNUMA Kenji @khasunuma_

6/25 実は JSR 277 とは別に JSR 294 という、モジュールの動的管理を行う仕組みもあって、この辺を組み合わせたものが当初の HK2 となるはずだった…らしい。ところが、そこに JSR 291 という、OSGi を Java でサポートするという提案が現れて、JSR 277/294 は「保留」になってしまった。

2020-02-12 01:32:12
HASUNUMA Kenji @khasunuma_

7/25 JSR 277/294 を保留に追い込んだ JSR 291 自体が、提出から承認まで終始一貫して当時の Sun に反対され続けた異例の JSR で、RI の一般公開さえないといういわくつきの仕様だった。それでも一応、仕様としてリリースされたけれど。

2020-02-12 01:32:12
HASUNUMA Kenji @khasunuma_

8/25 JSR 277/294 が保留になった後、HK2 が本来受け持つ予定だったバージョンや依存関係などの管理、動的ロードなどは OSGi に任せて、それ以外の DI や XML バインディング機能などを実装し、HK2 + OSGi をベースに Nucleus を開発することになった。

2020-02-12 01:32:13
HASUNUMA Kenji @khasunuma_

9/25 HK2 の DI は、その後 JSR 330 準拠の実装になり現在に至る。当然だが、JSR 330 の部分は CDI 実装すなわち Weld と被る。

2020-02-12 01:32:13

HK2 Config の話 (GlassFish の domain.xml を司るもの)

HASUNUMA Kenji @khasunuma_

10/25 HK2 の XML バインディング機能 HK2 Config は JAXB に似ているが、クラスでなくインタフェースにアノテーションを付け、実装クラスを動的に生成する点が大きく異なる。この辺の黒魔術は GraalVM の Truffle とそっくりで、以前 @jyukutyo のプレゼンを聴講した時まさにデジャブに陥った。

2020-02-12 01:32:13
HASUNUMA Kenji @khasunuma_

11/25 HK2 Config ver.1 では JAXB と全く異なるアノテーションを使用していたが、ver.2 から JAXB のアノテーションにも対応するようになった。 実は HK2 Config の名が示す通り、これの本来の目的は GlassFish の domain.xml の読み書き。でも GlassFish が使っているのは HK2 Config ver.1

2020-02-12 01:32:14
HASUNUMA Kenji @khasunuma_

12/25 HK2 Config ver.1 は XML 要素の順序を保持しないので、domain.xml の要素は読み書きされるたびに変わってしまうという、とても人間に優しくない仕様になっている。 仕事柄、domain.xml は嫌というほど見ているが、本当に順序がコロコロ変わる。

2020-02-12 01:32:14
HASUNUMA Kenji @khasunuma_

13/25 HK2 は現在 EE4J プロジェクトの配下にあって、github.com/eclipse-ee4j/g… でメンテされている。現在は JSR 330 準拠の DI フレームワークという建前になっていて、GlassFish/Payara では使わない機能もいろいろ入っている。

2020-02-12 01:32:14
HASUNUMA Kenji @khasunuma_

14/25 計画中の Payara 6 では、HK2 を拡張して CDI に準拠させ、Weld を置き換えるような話になっている。これが実現すれば CDI 周りのトラブルはかなり減るはず。Eclipse GlassFish がこの辺を将来どうするかは今のところ何も聞いていない。

2020-02-12 01:32:15
HASUNUMA Kenji @khasunuma_

15/25 先ほどギョッとしたのだが、実は Helidon でも HK2 を部分的に使っているらしい。Jersey が HK2 と密接に連携するのも影響しているのだろうが、ネイティブ・イメージ生成周りでも見かけたので、結構使っているのかもしれない。 github.com/oracle/helidon…

2020-02-12 01:32:15

GlassFish のブートストラップ

HASUNUMA Kenji @khasunuma_

16/25 話は一気に戻るが、Nucleus は HK2 + OSGi で構成されていて、ブートストラップは glassfish.jar というモジュール。 実は GlassFish 4.x までは java -jar glassfish.jar だけでも GlassFish が起動するようになっていた。Payara 5 では多数のオプションをつけないと起動しないが。

2020-02-12 01:32:16
HASUNUMA Kenji @khasunuma_

17/25 glassfish.jar など主要なモジュールは、glassfish-jar という特殊な JAR になっていて、OSGi による動的ロードに対応している。そのため、glassfish.jar を実行すると、依存関係にあるモジュールが次々と芋づる式にロードされ、Nucleus が起動する。

2020-02-12 01:32:16
HASUNUMA Kenji @khasunuma_

18/25 ディレクトリ構成がデフォルト通りであれば、Nucleus が domain.xml を読み込み、各種コンテナを起動してとりあえず Java EE / Jakarta EE のアプリがデプロイできる状態になる。一連の流れは遅延ロードなので、Nucleus の起動そのものは結構速い。

2020-02-12 01:32:16
HASUNUMA Kenji @khasunuma_

19/25 実は Payara 5 の起動はかなり遅いのだが、これは後から実装した管理・監視系モジュールを全部即時ロードしているため。しかもそれらは遅延ロードを考慮していないし、そもそも遅延ロードが許されない重要なモジュールだったりする。

2020-02-12 01:32:17
HASUNUMA Kenji @khasunuma_

20/25 実際、glassfish.jar にどのようなパラメータが渡されるかは、asadmin start-domain --verbose --dry-run domain1 とか実行すると出てくる。直接的には asadmin の正体である appserver-cli.jar (これは普通の実行可能JAR) が呼び出され、それが glassfish.jar にごっそりパラメータを渡す。

2020-02-12 01:32:17
HASUNUMA Kenji @khasunuma_

21/25 GlassFish 5.x と Payara 5 では Grizzly NPN bootstrap の呼び出し方が違っていて、それに伴い glassfish.jar に渡されるパラメータにも差異がある。Payara 5をJDK 11上で起動した場合はその差がさらに大きくなる。 (GlassFish 4.x と Payara 4.x の場合はほぼ同じ)

2020-02-12 01:32:17