Geronimoのマイクロカーネルアーキテクチャを斜めから理解する。

まずは正面から理解しておいてクダサイナ。


IBM developerWorksには、調度良い量のドキュメントがあるんで、そっちを。


んで、とりあえずは、Geronimoのバイナリリースを動作させてみる訳で。

%GERONIMO_HOME%/bin/startup.bat

あたりをポチっとな。
ビルドするよりも前に一度位は、動かしてる筈だけどさ。


まぁ、色々感じる事がある。
感覚の話だけど、JBossをブートする時よりもマシン負荷*1が低いんだな。
おー、やるじゃん。Geronimo。とか思ったり。
ま、コンソールにやたらログが出ないからかもしんないケドね。


そしてもう一つ。これが決定的なんだけど、XMLファイルが何か少ない。
Geronimoは、内部的な設定を永続化するのに、この2つのディレクトリを使ってるんよ。

前者に至っては、XMLファイルが全く見当たらない。
妙な数字のディレクトリがゴッソリと、index.propertiesなんて妙なpropetiesファイルがあるだけ。
config.serなんてバイナリファイルがあるけど、jarアーカイブじゃねぇし。
何となくどっかでみた様なフォーマットしてるケドネ。

後者は、まぁ何かどのJ2EEサーバでも自動生成される様なXMLファイルだなぁ…と。

Do not edit this file whilst Geronimo is running.

なんて書いてあるし。


で、plan.xmlはどこいったのさ?moduleの依存関係やら何やら色々書いてあってムヒョーなplan.xmlは。

  • 消えたplan.xml
  • ちょっと早めなブートストラップ。
  • 大量に散らかる謎のファイル、config.ser

と、言う訳で、Geronimoが、どんな風にmoduleを管理しているのか調べて見る事にするます。
これで、Gernimoのカーネルにmoduleがどの様にプラグインされるか分る筈。
ま、抽象的な話だけ聞くと、何か隠してる事があるんじゃねぇかと勘繰りたくなるってもんです。


まずは、注目するmoduleを決めるます。

  • Kernel
  • System
    • 意味的に、KernelとSystemの違いがよく分らないので、まとめて見る感じ。


ちょっとわき道にそれるけど、CoreってmoduleはGeronimoAOPエンジンと言うかプロキシエンジンというか、そんなリソースが格納されてたりします。
なので、ちょっと細工するだけで、GeronimoAOPエンジンを追加出来る様になってるみたい。
只、まぁなんと言うか、他にも何か色々入ってて、
他の所で上手く溶け込めなくてあぶれた連中がごった煮状態になってる感じ。
そう考えると、Coreのリソースがなんで、Utilに入ってないのか、よく分らない。
なんとなく…だけど、ビルド順の問題で、Utilに入れられなかったのがCoreなんじゃね?とか。
だってさ、Kernel - System - Core って、意味の違いがよう分らんもの。


まずは、module/kernelのソースコードをファイル名だけ俯瞰します。
おーー、素晴らしい。なんて分かり易いんだ!!*3

org.apache.geronimo.kernel.Kernel

なんてインターフェースがあるですよ。
結構すっきりしたインターフェースをしているなぁ。と1分位眺めてみる。
なんかGBean読み込むみたいなメソッドがあるじゃないですか。

    /**
     * Load a specific GBean into this kernel.
     * This is intended for applications that are embedding the kernel.
     *
     * @param gbeanData the GBean to load
     * @param classLoader the class loader to use to load the gbean
     * @throws org.apache.geronimo.kernel.GBeanAlreadyExistsException if the name is already used
     * @throws org.apache.geronimo.kernel.InternalKernelException if there is a problem during registration
     */
    void loadGBean(GBeanData gbeanData, ClassLoader classLoader) throws GBeanAlreadyExistsException, InternalKernelException;

つまりは、GeronimoのKernelにmoduleをプラグインするっつうのは、
このメソッドを呼ぶっつう事です。
javadocコメントが分るような分らない様な感じなのは、
結局日本語でも英語でも同じだなぁ…と思いながら、GBeanDataを開きマス。


開いた瞬間、ハイ、ガッテン。ってなもんです。
最初の方だけコピペすると、こんな感じ。

public class GBeanData implements Externalizable {
    private ObjectName name;
    private GBeanInfo gbeanInfo;
    private final Map attributes;
    private final Map references;
    private final Set dependencies;

こいつは、GBeanを作ったら、必要になるplan.xmlとGBeanInfoを抱え込んでる訳ですな。*4
気付かないといけないのは、implements Externalizable
をー、特殊なシリアライズプロセスを踏むんだ、コイツって。
そういや、config.serは、見た様な見た事無いようなフォーマットしてたなぁ…とか思い出すとグー。
まぁ、興味半分で、writeExternalメソッドを読む訳デス。
やってるのは、

  1. GBeanInfo(gbeanInfo)のシリアライズ
  2. ObjectName(name)のシリアライズ
  3. Map(attribute)のシリアライズ
  4. Map(references)のシリアライズ
  5. Set(dependencies)のシリアライズ

ビンゴぉぉ。
テキストエディタバイナリエディタでconfig.serを開くとまぁ、確かにそんな感じな訳デス。
細かいフォーマットは、理解出来ないにしても、javaはクラス名が文字列表現としてシリアライズされるから、良く分るのデス。
これで分ってしまいマスタ。

  • config.serは、GBeanData のシリアライズ後の姿。
  • GBeanDataは、plan.xmlとGBeanInfoを抱えてる。
  • つまり、デプロイ後のplan.xmlとGBeanInfoは、config.serとしてストアされる。
    • サーバ起動時に、毎回、moduleをXMLからオブジェクトをデシリアライズする訳ではないので、それなりに高速って事やね。


まぁ、これで殆ど分ってしまった訳なんだけどさ。
ちょっと気になるのは、loadGBeanでClassLoader指定するのって何かヤバくね?って事。
ほら、最近はCGLibやJavaasistでバイトコード弄るのが流行りな訳ですやん。
loadGBeanに動的に弄った後のGBeanなクラスを食わせて、config.serにシリアライズされちゃうと、
シリアライズする時はエエけど、デシリアライズする時に、元もとのClass参照が取れなくて、面倒な事になったり…とか。


実装がどうなってるのか興味は尽きない訳で、Kernelの実装を探します。
「Open Type Hierarchy」っとな。おお、居た居た。BasicKernel。
んで、loadGBeanはどうなっとるかと言うと…

    public void loadGBean(GBeanData gbeanData, ClassLoader classLoader) throws GBeanAlreadyExistsException, InternalKernelException {
        ObjectName objectName = gbeanData.getName();
        GBeanInstance gbeanInstance = new GBeanInstance(gbeanData, this, dependencyManager, lifecycleMonitor.createLifecycleBroadcaster(objectName), classLoader);
        registry.register(gbeanInstance);
    }

GeronimoのKernelが管理し易い様に、GBeanInstanceってクラスで、
GBeanなclassなのかインスタンスなのかをラッピングして、
後は、SetかMapか分らないけどregistryなんてトコに格納してる訳デスナ。


つまり、Geronimoマイクロカーネルアーキテクチャってのは、
Kernelに抱え込まれた、GBeanInstanceの塊。って事なんですなぁ…。
後は、依存性の管理と、moduleのストアとレストア、最後にJMXブリッジがついてきたりって感じ?
ちょっとぶっちゃけ過ぎか……。
若干、JMXなコードが奥底まで入りすぎてる様な気がしないでも無いけど、
そもそもJMX自体が、アーキテクチャを決めてる様なもんだからいいのかな。


loadGBeanの呼び出し元が、どんな感じなのか軽くみてみる。
結構、呼び出し元は居るなぁ……。

  • LocalConfigStore
  • Configuration
    • 不明。ダイナミックにmduleをデプロイする為の仕組み?
  • ConfigurationDump
  • Daemon
    • Geronimoのブートストラップの際に使用される。
  • CommandLine
    • 不明。mainメソッドがあるけど…。

やっぱ、だえもんさんを覗いてみますかね。
server.jar/META-INF/MANIFEST.MFにもMain-Class:としてエントリされてる事だし。


ほほぅ、Kernel#bootメソッドは、Kernel専用のスタートアップメソッドなのくぁ…。
お…?ちょっと面白そうなコード発見。

// create the kernel
final Kernel kernel = KernelFactory.newInstance().createKernel("geronimo");

ほほぅ…、-Dオプションやら、META-INF/services/にファイルを置いたりすると、
どうやらKernelFactoryの実装を置き換えられる様ですなぁ……。
KernelFactoryの実装を置き換えられると言う事は、Kernelもカスタム実装できますなぁ……。


続く……かもしれない。

*1:CPU使用率 ,メモリ使用量

*2:後、軍曹だから。

*3:ちょっと大げさに。

*4:plan.xmlの内容とGBeanInfoが必要だと言う事は、IBM dWの記事を読むとワカリマス。