オープンソースJ2EE APサーバ JBossの可能性 3

ユニファイドクラスローダ

ユニファイドクラスローダ

JBossの特徴的な機能として、ユニファイドクラスローダというしくみがあります。普段J2EEのアプリケーションを構築する場合は、あまりクラスローダを意識することがないと思いますので、まず簡単にJavaのクラスローダについて説明します。

クラスローダとは、Java VMがファイルやURLなどからクラスをメモリ上にロードするためのクラスで、あるクラスのインスタンスをはじめて作成するときなどにJava VMが自動的に処理を行います。

クラスローダには親子関係があり、親クラスローダが既にロードしたクラスは、子クラスローダがそれを再利用します。つまり、子クラスローダがあるクラス(ClassA)をロードするときに、親クラスローダに対して「ClassAは既にロード済か?」を問い合わせ、既にロード済であれば親クラスローダがロードしたものをそのまま使い、まだロードしていなければ新規にClassAをロードします。

しかし、クラスローダの関係が兄弟の場合、このような問い合わせは行われません。つまり、まったく同じ名前で実装も同じクラスであっても、別々にロードされてしまいます。そして、この別々にロードされたクラスは、クラス名や実装がまったく同一であるにも関わらず、別のクラスとして扱われます(クラ スの識別は「クラスローダ+クラス名」で行われます)。

クラスローダに対して馴染みのない方はあまりピンと来ないかもしれませんが、ここでは「別々のクラスローダからロードされたクラスのインスタンスは、それぞれ別クラスのインスタンスとして扱われる」ということだけを押さえていただければいいと思います。

ClassA{
……
}

ClassLoader clA = new ClassLoader(); //クラスローダAを作成
Class classA1 = clA.classLoad("ClassA"); //ClassAをロード
Object a = classA1.newInstance(); //インスタンスの作成
ClassLoader clB = new ClassLoader(); //クラスローダBを作成
Class classA2 = clA.classLoad("ClassA"); //ClassAをロード
Object b = classA2.newInstance(); //インスタンスの作成

// a と b は別のクラスのインスタンスとして認識される

それに対してユニファイドクラスローダは、兄弟クラスローダがロードしたクラスを含めて、既にロードされている同名クラスをすべて使い回します。つまり、パッケージ名まで含めたクラス名が一致すれば、重複してそのクラスがロードされることはありません。

なぜユニファイドクラスローダのようなしくみが導入されたのかというと、複数のEARやWAR間でクラスを共有して利用することを可能とするためです。JBossではJAR、WAR、EARなどの最上位ファイルごとにクラスローダを割り当てます。通常のクラスローダを使用すると、クラスローダが異なるためにクラスの共有ができない場合があります。この場合でもユニファイドクラスローダであれば問題なく利用できます。

そして、ユニファイドクラスローダのしくみを応用することによって、ホットデプロイが可能となっています。ホットデプロイを行うと、再デプロイ用に別のクラスローダが割り当てられます。この結果、同一のクラス名でありながら、中身が違うという状態が発生します。この状態のままでは、新しくデプロイされたクラスが使われない(ユニファイドクラスローダは、先にロードされたクラスの情報が優先されます)ので、今まで使われていたクラスの情報がユニファイ ドクラスローダから切り離されます。

例えば、あるEJBのバグを修正したEARファイル上書きコピーすることでホットデプロイを行った場合は、旧EARファイル内に含まれていたクラスファイルの情報が切り離され、それ以降同一クラスが使用されるときは、新しくデプロイされたクラスが利用されるようになります。旧クラスはすべての参照が無くなった時点で、ガーベッジコレクションの対象となってメモリから除去されます。

ユニファイドクラスローダによって便利な機能が提供されているのですが、完全な解決策というわけではありません。デプロイの仕方(EARやWARなどのパッケージの仕方)によってはClassCastExceptionなどが発生する場合があります。ある程度、アプリケーション開発者がEARなどの パッケージの際に注意を払う必要があります。

こういった問題を避ける一番手っ取り早い方法は、デプロイする要素をすべてひとつのEARファイルにまとめてしまうという方法です。特別な理由がない限り、ひとつのアプリケーションが利用するクラスはすべてのひとつのEARにまとめてしまって、デプロイ/再デプロイ(ホットデプロイ)することをお奨めします。無用なトラブルを回避することができます。

他にもJBossを特徴づけるしくみはいくつかありますが、JBoss内部構造のうちの代表的な2つのしくみについて説明しました。次回は、JBossで適用可能なパフォーマンスチューニングのための設定について説明しようと思います。

この記事をシェアしてください

人気記事トップ10

人気記事ランキングをもっと見る