yamadamn’s blog

IT関連技術で経験したこと・気になったことをたまに書きます

WebLogic Server 12.2.1に密かに追加されたクラスデータ共有機能 #jpoug

はじめに

この記事はJPOUG Advent Calendarの10日目です。
先日10/19にWebLogic Server(以下、WLS)勉強会で、WLS 12.2.1.0/12.2.1.1のマイナーな新機能などを取り上げました。

その際、メジャーな新機能であるマルチテナントに関連しそうな内容はあえて扱わなかった*1のですが、本記事では、おそらく関連するであろうクラスデータ共有機能について取り上げます。
"おそらく"と言うのは、WLSのクラスデータ共有機能については、今のところ公式ドキュメントに記載がないためです。
そのため正式にはサポートされておらず、本記事で記載する内容は、将来的に予告なく変更されたり廃止される可能性もありますので、念のためご注意・ご了承ください。

確認した環境は次の通りです。

クラスデータ共有とは

クラスデータ共有(CDS)は、HotSpot JDKの機能*4として、実はJ2SE 5.0の頃からあります。
詳細はドキュメントを確認いただきたいのですが、アプリケーションの起動時間やメモリフットプリントを短縮するために、複数のJVMでクラスデータを利用できるよう共有アーカイブを作成・利用します。
ただ、通常のCDSは、HotSpot Client VMかつシリアルガベージコレクタ環境でのみのサポートされるもので、今の時代となっては実質的に使われないでしょう。

Oracle JDK 8u40ではこのCDSを拡張して、多くのアプリケーション環境で利用できるように、商用機能*5の一つとして、アプリケーションクラスデータ共有(AppCDS)が導入されました。ツールドキュメントには実験的と記載があるのですが、実際はそんなことはないようです。
今回紹介するWLSのクラスデータ共有は、実際にはこちらのAppCDSを利用することになります。

WLSでのAppCDSの利用方法

それでは、WLSでAppCDSを利用してみましょう。
まずはWLSをインストールし、ドメインを作成してください。
インストール手順やドメイン作成手順は割愛します。

クラスリストの作成

ターミナルからドメインディレクトリに移動し、WLSを起動するためのスクリプト(startWebLogic.sh)に、引数「generateClassList」を加えて実行します。

$ cd ~/weblogic/wls12212_dev/user_projects/domains/base_domain
$ ./bin/startWebLogic.sh generateClassList

すると、通常のWLS起動オプションに次のJVMオプションが加わって実行されます。(改行を入れています)

-XX:+UnlockCommercialFeatures
-XX:+IgnoreEmptyClassPaths
-XX:DumpLoadedClassList=/Users/takahiro/weblogic/wls12212_dev/user_projects/domains/base_domain/WebLogic.classlist
-XX:+UseAppCDS

WLSがRUNNINGで起動したことを確認したら、一旦Ctrl+Cなどで止めてみましょう。
ドメインディレクトリ直下にWebLogic.classlistが作成されていることが確認できます。

$ ls -l
total 1352
-rw-r-----   1 takahiro  staff  671492 12 10 20:24 WebLogic.classlist
drwxr-x---   3 takahiro  staff     102 12  7 01:01 autodeploy
drwxr-x---  20 takahiro  staff     680 12  7 01:01 bin
drwxr-x---   3 takahiro  staff     102 12  7 01:01 common
drwxr-x---  11 takahiro  staff     374 12  7 01:01 config
drwxr-x---   3 takahiro  staff     102 12  7 01:01 console-ext
-rw-r-----   1 takahiro  staff     438 12 10 20:24 derby.log
-rw-r-----   1 takahiro  staff     104 12 10 20:24 derbyShutdown.log
-rw-r-----   1 takahiro  staff     139 12 10 20:24 edit.lok
-rw-r-----   1 takahiro  staff     327  6 13 07:29 fileRealm.properties
drwxr-x---  14 takahiro  staff     476 12  7 01:01 init-info
drwxr-x---   3 takahiro  staff     102 12  7 01:01 lib
drwxr-x---   4 takahiro  staff     136 12  7 01:01 nodemanager
drwxr-x---   3 takahiro  staff     102 12  7 01:01 orchestration
drwxr-x---   7 takahiro  staff     238 12  7 01:01 security
drwxr-x---   3 takahiro  staff     102 12  7 01:01 servers
-rwxr-x---   1 takahiro  staff     287 12  7 01:01 startWebLogic.sh

中身はテキスト形式で、ロードされたクラスが記録されています。
大きいので、最初と最後の10行だけ見てみましょう。

$ head WebLogic.classlist 
java/lang/Object
java/lang/String
java/io/Serializable
java/lang/Comparable
java/lang/CharSequence
java/lang/Class
java/lang/reflect/GenericDeclaration
java/lang/reflect/AnnotatedElement
java/lang/reflect/Type
java/lang/Cloneable
$ tail WebLogic.classlist 
weblogic/messaging/common/PrivilegedActionUtilities$4
weblogic/rmi/server/UnicastRemoteObject
weblogic/rmi/server/RemoteServer
weblogic/rmi/server/RemoteObject
weblogic/messaging/dispatcher/DispatcherWrapperState
weblogic/work/concurrent/services/PartitionConcurrrentManagedObjectFactory$1
weblogic/store/admin/JMXUtils$2
weblogic/store/io/file/StoreFile$1CloseChannels
weblogic/store/admin/JMXUtils$4
weblogic/ldap/LDAPExecuteRequest

Java SEの標準APIやWLSのクラスがリストされているのが分かりますね。

共有アーカイブの作成

次に前項で作成されたWebLogic.classlistを使って、共有アーカイブを作成するためにgenerateArchive.shを実行します。

$ ./bin/generateArchive.sh

実際には、次のようなjavaコマンドが実行されます。(改行を入れておきます)

/Library/Java/JavaVirtualMachines/jdk1.8.0_112.jdk/Contents/Home/bin/java
-XX:+UnlockCommercialFeatures
-XX:+UnlockDiagnosticVMOptions
-Xshare:dump
-XX:+UseAppCDS
-XX:+IgnoreEmptyClassPaths
-XX:+TraceClassPaths
-XX:+IgnoreUnverifiableClassesDuringDump
-XX:SharedArchiveFile=/Users/takahiro/weblogic/wls12212_dev/user_projects/domains/base_domain/WebLogic.jsa
-XX:SharedClassListFile=/Users/takahiro/weblogic/wls12212_dev/user_projects/domains/base_domain/WebLogic.classlist

このコマンドの出力は非常に多くなるため、最後の部分のみ記載します。

Rewriting and linking classes: done
Number of classes 15293
    instance classes   = 15279
    obj array classes  =     6
    type array classes =     8
Calculating fingerprints ... done. 
Removing unshareable information ... done. 
Shared Lookup Cache Table Buckets = 8216 bytes
Shared Lookup Cache Table Body = 617592 bytes
ro space:  48183744 [ 40.5% of total] out of 122683392 bytes [39.3% used] at 0x0000000800000000
rw space:  62089888 [ 52.2% of total] out of 157286400 bytes [39.5% used] at 0x0000000807500000
md space:   8538968 [  7.2% of total] out of  28311552 bytes [30.2% used] at 0x0000000810b00000
mc space:     34053 [  0.0% of total] out of   6291456 bytes [ 0.5% used] at 0x0000000812600000
total   : 118846653 [100.0% of total] out of 314572800 bytes [37.8% used]

そして、共有アーカイブとしてWebLogic.jsaが作成されたことが確認できます。

$ ls -l
total 233512
-rw-r-----   1 takahiro  staff     671492 12 10 20:24 WebLogic.classlist
-r--r-----   1 takahiro  staff  118865920 12 10 20:24 WebLogic.jsa
drwxr-x---   3 takahiro  staff        102 12  7 01:01 autodeploy
drwxr-x---  20 takahiro  staff        680 12  7 01:01 bin
drwxr-x---   3 takahiro  staff        102 12  7 01:01 common
drwxr-x---  11 takahiro  staff        374 12  7 01:01 config
drwxr-x---   3 takahiro  staff        102 12  7 01:01 console-ext
-rw-r-----   1 takahiro  staff        438 12 10 20:24 derby.log
-rw-r-----   1 takahiro  staff        104 12 10 20:24 derbyShutdown.log
-rw-r-----   1 takahiro  staff        139 12 10 20:24 edit.lok
-rw-r-----   1 takahiro  staff        327  6 13 07:29 fileRealm.properties
drwxr-x---  14 takahiro  staff        476 12  7 01:01 init-info
drwxr-x---   3 takahiro  staff        102 12  7 01:01 lib
drwxr-x---   4 takahiro  staff        136 12  7 01:01 nodemanager
drwxr-x---   3 takahiro  staff        102 12  7 01:01 orchestration
drwxr-x---   7 takahiro  staff        238 12  7 01:01 security
drwxr-x---   3 takahiro  staff        102 12  7 01:01 servers
-rwxr-x---   1 takahiro  staff        287 12  7 01:01 startWebLogic.sh
共有アーカイブを利用してWLSを起動

では、仕上げに前項で作成されたWebLogic.jsaを利用してWLSを起動しましょう。
startWebLogic.shの引数に「useArchive」を加えます。

$ ./bin/startWebLogic.sh useArchive

今度は、通常のWLS起動オプションに次のJVMオプションが加わって実行されます*6。(改行を入れています)

-XX:+UnlockCommercialFeatures
-Xshare:auto
-XX:+UseAppCDS
-XX:+IgnoreEmptyClassPaths
-XX:SharedArchiveFile=/Users/takahiro/weblogic/wls12212_dev/user_projects/domains/base_domain/WebLogic.jsa
-showversion

これで共有アーカイブを利用できるようになったはずです。

…と思ったのですが「-verbose:class」を付加して確認すると、共有アーカイブではなく、通常のjarファイルからロードされています。
何かがおかしいはずなので、上記の「-Xshare:auto」を「-Xshare:on」になるようstartWebLogic.shを修正してから実行すると、次のエラーで異常終了しました。

An error has occurred while processing the shared archive file.
Tool agent requires sharing to be disabled.
Error occurred during initialization of VM
Unable to use shared archive.

エージェント利用時は共有アーカイブを無効にする必要があるようですね。ここで思い出しました。
WLS 12.2.1には動的デバッグパッチ機能が追加されており、デフォルトで起動オプションに「-javaagent:$WL_HOME/server/lib/debugpatch-agent.jar」が追加されます。
最初のスライドのP18に記載していますが、これを無効にすべくstartWebLogic.shの引数に「disableDebugPatches」を追加して実行してみましょう。

$ ./bin/startWebLogic.sh useArchive disableDebugPatches

「-verbose:class」の出力を確認すると、次のようにWLS関連のクラスも共有アーカイブから読み込まれるようになりました!*7

[Loaded weblogic.Server from shared objects file by sun/misc/Launcher$AppClassLoader]

それで、パフォーマンスは良くなったの?

マシンスペックなどにも大きく依存するでしょうし、オラクル製品はベンチマークを公開してはいけないポリシーだったはずなので、詳細は記載しませんが、今回の私の環境では、WLS起動時のパフォーマンスはかなり向上しました。
また、今回はWLS管理サーバだけで確認しましたが、1つのホスト・ドメイン内で複数のWLSインスタンスを起動する際には、メモリフットプリントも改善されることが期待できます。

まとめ

それではまとめです。

  • WLS 12.2.1にはドキュメント未記載ですが、アプリケーションクラスデータ共有(AppCDS)を利用する機能が組み込まれています。
  • AppCDSを利用すると、WLSの起動パフォーマンスの改善や、メモリフットプリントの向上が期待できます。
  • 正式にリリースされた際には、ライセンスに注意しつつ検証して利用しましょう。

*1:マルチテナントなどは商用で使うにはWLS Enterprise Editionやオプションライセンスが必要となり、個人的には勉強会では取り上げにくいので省きました。

*2:10/19勉強会の夜間にちょうどリリースされたため、先のスライドには含められませんでしたが、このパッチセットは基本的にBug修正がメインのようなので、それほど目立った新機能は見当たりません。

*3:開発環境用としてのみ動作保証されているようです。

*4:同様のクラス共有機能はIBM JDKでも実装されています。

*5:つまり本番環境などで利用するにはライセンスが必要です。

*6:直接は関係ない「-showversion」も入ってます。

*7:もちろんJava SEの標準APIも共有アーカイブから読み込まれるようになります。