[WLS] Sharing a Class With a WebLogic Classloader Without Modifying Scripts

社内メーリングリストで質問があったのですが、この質問はクラスローダに関する疑問を持ってらっしゃる方にも関心があることだと思います。WebLogicのクラスローディングのオプションについて簡単に復習するために、右のイメージをクリックして拡大するか、このエントリの最下部に記載したSlideShareのURLを参照してください。このシナリオの鍵は、<Domain_Home>/libディレクトリにあります。

シナリオ
製品スイート内のすべての各Webアプリケーションに組み込まれて出荷されているJavaコンポーネントがあります。この組み込みJavaコンポーネントはキャッシュオブジェクトを持っていて、これはコンポーネントがWebアプリケーションにより初期化されるたびにロードされます。このキャッシュオブジェクトはシングルトンであり、すべてのWebアプリケーションで同じコンテンツを持ちます。多くのearファイルがデプロイされている管理対象サーバがあるとし、各々のearファイルは起動時にこの組み込みJavaコンポーネントを初期化します。

問題
これらのWebアプリケーションの各々でロードされるオブジェクトを(クラスローダ解析ツールを使って)プロファイルすると、このシングルトンのキャッシュオブジェクトがWebアプリケーションのクラスローダのそれぞれでロードされていることがわかっています。これらのシングルトンオブジェクトの一つだけをロードし、同じオブジェクトをすべてのearファイルで参照すれば、ヒープサイズを節約し、各earファイルで生成されるこのキャッシュオブジェクトに必要なすべての呼び出しを節約できると考えています。シングルトンであるにもかかわらず、クラスローダは新しいキャッシュオブジェクトを生成する各earファイルによって異なっているのです。WebLogicのクラスローダの階層(ブートストラップ、システム、Webアプリケーションなど)は理解しています。組み込みJavaコンポーネントならびにその依存関係のあるコンポーネントを、スクリプトや環境変数の変更によりシステムクラスローダに移動したくないのです。何かよい方法はありますか?

回答
<Domain_Home>/lib ディレクトリを参照してください。

Adding JARs to the Domain /lib Directory
http://download.oracle.com/docs/cd/E21764_01/web.1111/e13706/classloading.htm#i1096881

<Domain_Home>/ libディレクトリに、共有させたいjarファイルを配置します。以下に例を挙げます。
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package test;

import java.util.Map;

/**
*
* @author jbayer
*/
public class SharedCache
{
   public static final Map<String,String> mapCache = new java.util.HashMap<String, String> ();
 
    static  
    {
        System.out.println( SharedCache.class.toString() + " loaded into a classloader" + SharedCache.class.getClassLoader().toString() );
    }

    public SharedCache()
    {
    }
}
同一のindex.jspでSharedCacheクラスを参照する2個のWebアプリケーション(WebApplication1とWebApplication2)でこのクラスを使用します。
<%@page contentType="text/html" pageEncoding="UTF-8" import="test.*"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>JSP Page</title>
    </head>
    <body>
        <h1>Hello World! Cache size:
           
<%
    SharedCache myCache = new SharedCache();
    out.print( myCache.mapCache.size() );                   
%>
       
        </h1>
    </body>
</html>
test.SharedCacheクラスが各Webアプリケーションのそれぞれからロードされるときに、2つのバージョンが各Webモジュール向けに別々のクラスローダでロードされていることが以下のSystems.outの出力でわかるはずです。
class test.SharedCache loaded into a classloaderweblogic.utils.classloaders.ChangeAwareClassLoader@bde4ac finder: weblogic.utils.classloaders.CodeGenClassFinder@1ff9980 annotation: WebApplication1@web
class test.SharedCache loaded into a classloaderweblogic.utils.classloaders.ChangeAwareClassLoader@4a4acd finder: weblogic.utils.classloaders.CodeGenClassFinder@3f08e3 annotation: WebApplication2@web
SharedCacheを含むjarファイルを<Domain_Home>/libディレクトリに配置してサーバを再起動、両方のWebアプリケーションにアクセスすると、一つのシステムクラスローダからクラスを共有していることがわかります。
class test.SharedCache loaded into a classloaderjava.net.URLClassLoader@88e2dd
CAT(クラスローダ解析ツール)を使っても、両方のアプリケーションが同じシステムクラスローダを使っていることがわかります。ハッシュコードからも、同一クラスローダが両アプリケーションから使われていることがわかります(下図)。

WebLogic ServerクラスローダとCATについてJeff Westが説明およびデモをしている動画がありますので、ご確認ください。



スライドだけをご覧になりたいならこちらをどうぞ。

WebLogic's ClassLoaders, Filtering ClassLoader and ClassLoader Analysis Tool
http://www.slideshare.net/jeffreyawest/weblogic-filtering-classloader-and-classloader-analysis-tool-demo


[訳注]
Javaエバンジェリストの寺田さんのスライドやデモもあります。
詳細はこちらのエントリをご覧下さい。

WebLogic 10.3.4 が正式リリース
http://yoshio3.com/2011/01/16/weblogic-10-3-4-%E3%81%8C%E6%AD%A3%E5%BC%8F%E3%83%AA%E3%83%AA%E3%83%BC%E3%82%B9/


原文はこちら。
http://blogs.oracle.com/jamesbayer/entry/sharing_a_class_with_a

0 件のコメント:

コメントを投稿