第28章 マーシャリング

28.1. マーシャリング

マーシャリングとは、Java オブジェクトを回線上で転送可能な形式に変換するプロセスのことです。アンマーシャリングはこれとは逆のプロセスで、回線上で転送可能な形式から読み取られたデータを Java オブジェクトに変換することを言います。

Red Hat JBoss Data Grid はマーシャリングおよびアンマーシャリングを使用して以下を行います。

  • クラスター内の他の JBoss Data Grid ノードへリレーするためにデータを変換します。
  • 基盤のキャッシュストアに保存するためにデータを変換します。

28.2. JBoss Marshalling Framework

Red Hat JBoss Data Grid は JBoss Marshalling Framework を使用して Java POJO をマーシャリングおよびアンマーシャリングします。JBoss Marshalling Framework は優れたパフォーマンスを提供するため、Java のシリアライゼーションの代わりに使用されます。さらに、JBoss Marshalling Framework は Java クラスを含む Java POJO を効率的にマーシャリングできます。

Java Marshalling Framework は、標準の java.io.ObjectOutputStreamjava.io.ObjectInputStream よりも高パフォーマンスな java.io.ObjectOutput および java.io.ObjectInput 実装を使用します。

28.3. シリアライズ不可能なオブジェクトのサポート

Red Hat JBoss Data Grid がシリアライズ不可能なオブジェクトのストレージをサポートするかどうかはユーザーに共通する懸念事項です。JBoss Data Grid では、シリアライズ不可能なキーと値のオブジェクトに対してマーシャリングはサポートされます。ユーザーはシリアライズ不可能なオブジェクトにエクスタナライザー実装を提供できます。

Serializable または Externalizable サポートをクラスに導入できない場合、一例として XStream を使用してシリアライズ不可能なオブジェクトを JBoss Data Grid に格納できる文字列に変換し、対応することもできます。

注記
必要となる XML トランスフォーメーションが原因で、キーと値のオブジェクトを格納するプロセスが遅くなります。

28.4. Hot Rod およびマーシャリング

リモートクライアントサーバーモードでは、Red Hat JBoss Data Grid サーバーとクライアントの両方のレベルでマーシャリングが発生しますが、詳細は異なります。

  • JBoss Data Grid サーバーのクライアントによって保存されるすべてのデーターは、バイトアレイまたは JBoss Data Grid のマーシャリングに対応するプリミティブな形式のいずれかとして提供されます。

    JBoss Data Grid のサーバー側では、プリミティブな形式で保存されたデータがバイトアレイに変換され、クラスター周囲でのレプリケートまたはキャッシュストアへの保存が行われるとマーシャリングが発生します。JBoss Data Grid のサーバー側ではマーシャリングの設定は必要ありません。

  • POJO をシリアライズまたはデシリアライズするには、クライアントレベルでマーシャリングの Marshaller 設定要素が RemoteCacheManager 設定に指定されている必要があります。

    Hot Rod のバイナリーの性質により、マーシャリングに依存して POJO (キーまたは値) をバイトアレイに変換します。

28.5. RemoteCacheManager を使用したマーシャラーの設定

マーシャラーは RemoteCacheManager の marshaller 設定要素を使用して指定されます。その値は、Marshaller インターフェースを実装するクラスの名前である必要があります。このプロパティーのデフォルト値は org.infinispan.commons.marshall.jboss.GenericJBossMarshaller です。

以下の手順は、RemoteCacheManager と使用するマーシャラーの定義方法を示しています。

マーシャラーの定義

  1. 設定ビルダーの作成

    ConfigurationBuilder を作成し、必要な設定を指定します。

    ConfigurationBuilder builder = new ConfigurationBuilder();
    //... (other configuration)
  2. マーシャラークラスの追加

    Marshaller メソッド内に Marshaller クラス仕様を追加します。

    builder.marshaller(GenericJBossMarshaller.class);
    1. この代わりに、カスタム Marshaller インスタンスを指定することもできます。

      builder.marshaller(new GenericJBossMarshaller());
  3. RemoteCacheManager の起動

    Marshaller が含まれる設定を構築し、その設定で新しい RemoteCacheManager を起動します。

    Configuration configuration = builder.build();
    RemoteCacheManager manager = new RemoteCacheManager(configuration);

クライアントレベルでは、POJO は Serializable、Externalizable、またはプリマティブ型のいずれかである必要があります。

注記

Hot Rod Java クライアントは、Externalizer インスタンスの提供による POJO のシリアライズをサポートしません。これは、JBoss Data Grid のライブラリーモードでのみ使用できます。

28.6. トラブルシューティング

28.6.1. マーシャリングのトラブルシューティング

Red Hat JBoss Data Grid では、ユーザーオブジェクトをマーシャリングまたはアンマーシャリングする時にマーシャリングレイヤーと JBoss Marshalling によってエラーが発生することがあります。問題をデバッグできるようにするため、例外スタックトレースに詳細情報が含まれます。

例外スタックトレース

java.io.NotSerializableException: java.lang.Object
at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:857)
at org.jboss.marshalling.AbstractMarshaller.writeObject(AbstractMarshaller.java:407)
at org.infinispan.marshall.exts.ReplicableCommandExternalizer.writeObject(ReplicableCommandExternalizer.java:54)
at org.infinispan.marshall.jboss.ConstantObjectTable$ExternalizerAdapter.writeObject(ConstantObjectTable.java:267)
at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:143)
at org.jboss.marshalling.AbstractMarshaller.writeObject(AbstractMarshaller.java:407)
at org.infinispan.marshall.jboss.JBossMarshaller.objectToObjectStream(JBossMarshaller.java:167)
at org.infinispan.marshall.VersionAwareMarshaller.objectToBuffer(VersionAwareMarshaller.java:92)
at org.infinispan.marshall.VersionAwareMarshaller.objectToByteBuffer(VersionAwareMarshaller.java:170)
at org.infinispan.marshall.VersionAwareMarshallerTest.testNestedNonSerializable(VersionAwareMarshallerTest.java:415)
Caused by: an exception which occurred:
in object java.lang.Object@b40ec4
in object org.infinispan.commands.write.PutKeyValueCommand@df661da7
... Removed 22 stack frames

in object で始まるメッセージとスタックトレースは同様に読み取られます。一番上の in object メッセージは最も内側のもので、最も外側にある in object メッセージは一番下になります。

この例は、java.lang.Object@b40ec4 はシリアライズ可能でないため、org.infinispan.commands.write.PutKeyValueCommand インスタンス内の java.lang.Object はシリアライズできないことを示しています。

しかし、DEBUG または TRACE ロギングレベルが有効である場合、スタックトレースにあるオブジェクトの toString() 表現がマーシャリング例外に含まれます。このような状況を表す例は次のとおりです。

ロギングレベルが有効である場合の例外

java.io.NotSerializableException: java.lang.Object
...
Caused by: an exception which occurred:
in object java.lang.Object@b40ec4
-> toString = java.lang.Object@b40ec4
in object org.infinispan.commands.write.PutKeyValueCommand@df661da7
->  toString = PutKeyValueCommand{key=k, value=java.lang.Object@b40ec4,  putIfAbsent=false, lifespanMillis=0, maxIdleTimeMillis=0}

アンマーシャリング例外でこのレベルの情報を表示するとリソース的に高価になります。しかし、JBoss Data Grid は可能な場合はクラス型の情報を表示します。以下は、このようなレベルの情報が表示された例を示しています。

アンマーシャリングの例外

java.io.IOException: Injected failue!
at org.infinispan.marshall.VersionAwareMarshallerTest$1.readExternal(VersionAwareMarshallerTest.java:426)
at org.jboss.marshalling.river.RiverUnmarshaller.doReadNewObject(RiverUnmarshaller.java:1172)
at org.jboss.marshalling.river.RiverUnmarshaller.doReadObject(RiverUnmarshaller.java:273)
at org.jboss.marshalling.river.RiverUnmarshaller.doReadObject(RiverUnmarshaller.java:210)
at org.jboss.marshalling.AbstractUnmarshaller.readObject(AbstractUnmarshaller.java:85)
at org.infinispan.marshall.jboss.JBossMarshaller.objectFromObjectStream(JBossMarshaller.java:210)
at org.infinispan.marshall.VersionAwareMarshaller.objectFromByteBuffer(VersionAwareMarshaller.java:104)
at org.infinispan.marshall.VersionAwareMarshaller.objectFromByteBuffer(VersionAwareMarshaller.java:177)
at org.infinispan.marshall.VersionAwareMarshallerTest.testErrorUnmarshalling(VersionAwareMarshallerTest.java:431)
Caused by: an exception which occurred:
in object of type org.infinispan.marshall.VersionAwareMarshallerTest$1

上記の例では、内部クラス org.infinispan.marshall.VersionAwareMarshallerTest$1 のインスタンスがアンマーシャルされたときに IOException が発生しました。

DEBUG または TRACE ロギングレベルが有効な場合、マーシャリング例外と似た方法で、クラスタイプのクラスローダー情報が提供されます。このクラスローダー情報の例は次のとおりです。

クラスローダー情報

java.io.IOException: Injected failue!
...
Caused by: an exception which occurred:
in object of type org.infinispan.marshall.VersionAwareMarshallerTest$1
-> classloader hierarchy:
-> type classloader = sun.misc.Launcher$AppClassLoader@198dfaf
->...file:/opt/eclipse/configuration/org.eclipse.osgi/bundles/285/1/.cp/eclipse-testng.jar
->...file:/opt/eclipse/configuration/org.eclipse.osgi/bundles/285/1/.cp/lib/testng-jdk15.jar
->...file:/home/galder/jboss/infinispan/code/trunk/core/target/test-classes/
->...file:/home/galder/jboss/infinispan/code/trunk/core/target/classes/
->...file:/home/galder/.m2/repository/org/testng/testng/5.9/testng-5.9-jdk15.jar
->...file:/home/galder/.m2/repository/net/jcip/jcip-annotations/1.0/jcip-annotations-1.0.jar
->...file:/home/galder/.m2/repository/org/easymock/easymockclassextension/2.4/easymockclassextension-2.4.jar
->...file:/home/galder/.m2/repository/org/easymock/easymock/2.4/easymock-2.4.jar
->...file:/home/galder/.m2/repository/cglib/cglib-nodep/2.1_3/cglib-nodep-2.1_3.jar
->...file:/home/galder/.m2/repository/javax/xml/bind/jaxb-api/2.1/jaxb-api-2.1.jar
->...file:/home/galder/.m2/repository/javax/xml/stream/stax-api/1.0-2/stax-api-1.0-2.jar
->...file:/home/galder/.m2/repository/javax/activation/activation/1.1/activation-1.1.jar
->...file:/home/galder/.m2/repository/jgroups/jgroups/2.8.0.CR1/jgroups-2.8.0.CR1.jar
->...file:/home/galder/.m2/repository/org/jboss/javaee/jboss-transaction-api/1.0.1.GA/jboss-transaction-api-1.0.1.GA.jar
->...file:/home/galder/.m2/repository/org/jboss/marshalling/river/1.2.0.CR4-SNAPSHOT/river-1.2.0.CR4-SNAPSHOT.jar
->...file:/home/galder/.m2/repository/org/jboss/marshalling/marshalling-api/1.2.0.CR4-SNAPSHOT/marshalling-api-1.2.0.CR4-SNAPSHOT.jar
->...file:/home/galder/.m2/repository/org/jboss/jboss-common-core/2.2.14.GA/jboss-common-core-2.2.14.GA.jar
->...file:/home/galder/.m2/repository/org/jboss/logging/jboss-logging-spi/2.0.5.GA/jboss-logging-spi-2.0.5.GA.jar
->...file:/home/galder/.m2/repository/log4j/log4j/1.2.14/log4j-1.2.14.jar
->...file:/home/galder/.m2/repository/com/thoughtworks/xstream/xstream/1.2/xstream-1.2.jar
->...file:/home/galder/.m2/repository/xpp3/xpp3_min/1.1.3.4.O/xpp3_min-1.1.3.4.O.jar
->...file:/home/galder/.m2/repository/com/sun/xml/bind/jaxb-impl/2.1.3/jaxb-impl-2.1.3.jar
-> parent classloader = sun.misc.Launcher$ExtClassLoader@1858610
->...file:/usr/java/jdk1.5.0_19/jre/lib/ext/localedata.jar
->...file:/usr/java/jdk1.5.0_19/jre/lib/ext/sunpkcs11.jar
->...file:/usr/java/jdk1.5.0_19/jre/lib/ext/sunjce_provider.jar
->...file:/usr/java/jdk1.5.0_19/jre/lib/ext/dnsns.jar
... Removed 22 stack frames