Java RMIの拡張機能

JDK 8での拡張機能

非推奨になった機能: RMIからのHTTPプロキシ(8023862)
RMI/JRMPのHTTPプロキシ機能は非推奨となり、HTTPプロキシはデフォルトで無効になりました。
非推奨になった機能: 静的に生成されたスタブのサポート(8023863)
RMI (JRMP)から静的に生成されたスタブのサポートは、非推奨になりました。

JDK 7での拡張機能

JDK 7 Update 21から、RMIプロパティjava.rmi.server.useCodebaseOnlyのデフォルト値はtrueに設定されています。詳細は、「JDK 7での拡張機能」を参照してください。

JDK 6の拡張機能

java.rmi.MarshalledObjectがジェネリックになりました
クラスMarshalledObjectに、格納されている直列化されたオブジェクトの型を表す型パラメータが用意されました。
バグの修正: リモート・オブジェクトのアンエクスポート後に明示的なTCPポートが解放される(4457683)
以前のリリースでは、明示的な(匿名でない) TCPポートでリモート・オブジェクトがエクスポートされると、そのポートでエクスポートされたリモート・オブジェクトのライフ・サイクルとは関係なく、そのポートにバインドされたサーバー・ソケットは、仮想マシンの有効期間中開いたままになっていました。このバグが修正され、指定された非匿名ポートでエクスポートされたすべてのリモート・オブジェクトがアンエクスポートされると(明示的に、または分散ガベージ・コレクションによって)、関連するサーバー・ソケットが閉じるようになりました。匿名TCPポートの場合にも同様のバグ(6279965)があります。
バグの修正: クライアント・ソケット・ファクトリのガベージ・コレクション(4486732)
以前のリリースでは、指定された仮想マシンでnullでないRMIClientSocketFactoryを含むリモート・スタブでリモート呼出しが行われると、そのファクトリ・オブジェクトまたは等価なファクトリ・オブジェクトは仮想マシンで永久にアクセス可能なままとなっていました。そのため、そのオブジェクト(およびそのオブジェクトを定義するクラス・ローダー)はガベージ・コレクトされませんでした。このバグが修正されました。(リモート・オブジェクトのエクスポートに使用されるソケット・ファクトリの場合にも同様のバグ(6332603)があります。)
デフォルトのガベージ・コレクション間隔が1時間に延長された(6200091)
以前のリリースでは、ライブなリモート参照またはエクスポートされたリモート・オブジェクトが存在する間に、RMI実装によってローカル・ヒープのガベージ・コレクタが行われる最大間隔(システム・プロパティsun.rmi.dgc.client.gcIntervalおよびsun.rmi.dgc.server.gcIntervalによって制御される)は、デフォルトで1分でした。デフォルトの間隔は1時間になり、特別な構成がなくても、アプリケーションでサイズの大きいヒープを利用しやすくなりました。

以前のリリースでの拡張機能と変更

スタブ・クラスの動的な生成(Java SE 5.0以降)
このリリースでは、実行時にスタブ・クラスを動的に生成するためのサポートが追加されたので、リモート・オブジェクト用のスタブ・クラスを事前に生成するJava Remote Method Invocation (Java RMI)スタブ・コンパイラ(rmic)を使う必要がなくなりました。以前のバージョンで実行されるクライアントをサポートする必要があるリモート・オブジェクトに対しては、rmicを使用して事前にスタブ・クラスを生成する必要があることに注意してください。

コンストラクタ、あるいはjava.rmi.server.UnicastRemoteObjectクラスまたはjava.rmi.activation.ActivatableクラスのstaticメソッドexportObject1を使用してアプリケーションがリモート・オブジェクトをエクスポートしても、そのリモート・オブジェクトのクラスに対応する生成済みスタブ・クラスが読み込まれない場合、リモート・オブジェクトのスタブは、呼出しハンドラとしてjava.rmi.server.RemoteObjectInvocationHandler付きのjava.lang.reflect.Proxyインスタンスとなります。そのクラスは、動的に作成されます。

java.rmi.server.ignoreStubClassesシステム・プロパティを"true"に設定することで、動的に作成されたスタブ・クラスを既存のアプリケーションが無条件で使用するように配置できます。つまり、スタブ・クラスが事前に生成されていたかどうかにかかわらず使用できるということです。このプロパティが"true"に設定されていると、生成済みスタブ・クラスが使用されることはありません。

注:

  • リモート・オブジェクトがリリース5.0よりも前のクライアントを持っている場合、そのリモート・オブジェクトは、rmicで事前に生成されたスタブ・クラスを使う必要があります。または、クライアントがClassNotFoundExceptionを入手して、リモート・オブジェクトのスタブの直列化を復元します。リリース5.0より前のクライアントは、動的に生成されたスタブ・クラスのインスタンスを読み込むことができません。このようなクラスにはRemoteObjectInvocationHandlerのインスタンスが含まれていますが、このリリースより前のバージョンでは利用できないからです。
  • Java SE 5.0より前のバージョンでは、リモート・オブジェクトをエクスポートする際にそのリモート・オブジェクトのクラスに対応する生成済みスタブ・クラスを読み込むことができないと、java.rmi.StubNotFoundExceptionがスローされます。動的に生成されたスタブ・クラスのサポートが追加されたため、生成済みのスタブ・クラスを持たないリモート・オブジェクトをエクスポートしても、そのまま処理が続行されます。リリース5.0より前のバージョンをサポートするサーバー・アプリケーションを配備しているユーザーは、エクスポート時にスタブ・クラスがなくてもエラーは報告されませんが、引き続きそのサーバーのリモート・オブジェクトのクラスに対応するスタブ・クラスを必ず事前に生成する必要があります。代わりにこのようなエラーは、動的に生成されたスタブ・クラスの直列化を復元するときに、5.0より前のリリースのクライアントに報告されます。

1 staticメソッドUnicastRemoteObject.exportObject(Remote)は、java.rmi.server.RemoteStubを返すように宣言されています。そのため、動的に生成されたスタブ・クラスをそれ自体のスタブとして使用するためにリモート・オブジェクトをエクスポートする場合には使用できません。動的に生成されたスタブ・クラスのインスタンスは、java.lang.reflect.Proxyインスタンスであり、RemoteStubに割り当てられません。

標準SSL/TLSソケット・ファクトリ・クラス(Java SE 5.0以降)
今回のリリースでは、標準のJava RMIソケット・ファクトリ・クラスであるjavax.rmi.ssl.SslRMIClientSocketFactoryjavax.rmi.ssl.SslRMIServerSocketFactoryが追加されています。これらのクラスでは、Java Secure Socket Extension (JSSE)を使って、Secure Sockets Layer (SSL)プロトコルまたはTransport Layer Security (TLS)プロトコルを介して通信します。これらのソケット・ファクトリ・クラスでは、Java RMIで簡単にJSSEを使う方法が提供されるので、リモート・メソッド呼出しのための整合性、暗号化による機密性、サーバー認証およびクライアント認証(任意)を強化できます。Java RMIでのカスタム・ソケット・ファクトリの使い方の詳細は、Java RMIによるカスタム・ソケット・ファクトリの使用に関するチュートリアルを参照してください。構成を含むJSSEの詳細は、「JSSEリファレンス・ガイド」を参照してください。
inetd/xinetdからrmidまたはJava RMIサーバーを起動する(Java SE 5.0以降)
System.inheritedChannelメソッドにより提供される新しい機能によって、アプリケーションは、仮想マシン(VM)を起動したプロセスから継承されるチャネル(java.nio.channels.SocketChannelまたはjava.nio.channels.ServerSocketChannelなど)を取得することができます。この継承チャネルは、SocketChannelの場合は単一の着信接続を行うため、ServerSocketChannelの場合は複数の着信接続を受け入れるために使用できます。その結果、inetd (Solarisオペレーティング・システム)またはxinetd (Linux)によって起動されたJavaネットワーキング・アプリケーションは、inetd/xinetdから継承されたSocketChannelまたはServerSocketChannelを取得できるようになりました。

この機能の追加によって、Java RMI起動デーモンrmidは、着信した接続要求を受け取ったときにのみrmidを起動できるように、inetd/xinetdからの起動をサポートするように拡張されました。この機能をサポートするためのrmidの拡張機能の詳細は、rmid (Solaris、LinuxまたはMac OS Xオペレーティング・システム用)のツール・ページを参照してください。rmidを起動するようにinetdを構成する方法についての詳細は、rmidを起動するinetdの構成」チュートリアルを参照してください。

Java RMIを使用するアプリケーションは、inetdまたはxinetdから起動されるように設計することもできます。この技法を実装する方法の例については、inetdから起動されるサービスの設計」チュートリアルを参照してください。

rmicの現在のデフォルトのスタブ・プロトコルのバージョン-v1.2 (Java SE 5.0以降)
生成されたクラスに使用されるJRMPスタブ・プロトコルのバージョンを指定するオプションなしでrmicが実行されると、前のリリースの-vcompatオプションの代わりに-v1.2オプションが指定されているかのように実行されます。

つまり、この変更によって、デフォルトでは、rmicはスケルトン・クラスは生成せず、1.2スタブ・プロトコルのバージョンだけを実装するスタブ・クラスを生成するようになりました。JDK 1.1で実行されるクライアントをサポートするためにリモート実装クラスを構築する必要がある場合は、-vcompatオプションを明示的に指定する必要があります。(さらに、前述のようにリモート実装クラスがJava SE 5.0より前のバージョンで実行されるクライアントをサポートする必要がない場合は、そのようなクラスのためにrmicを実行する必要はありません。)

これらのコマンド行オプションの詳細は、rmicのツール・ドキュメント(Solaris、LinuxまたはMac OS X用Windows用)を参照してください。

rmicがクラス・パス内の任意のソース・ファイルをコンパイルすることはない(Java SE 5.0以降)
以前のリリースでは、入力クラス・ファイルの処理中に、クラス・パス内にある任意の.javaソース・ファイルをrmicがコンパイルしようとすることがありました。Java SE 5.0では、rmicは自ら生成したスタブ、スケルトンまたはタイ・クラス以外のソース・ファイルをコンパイルしようとすることはありません。

rmicに渡されるリモート実装クラスは、そのクラスが依存しているすべてのクラスおよびインタフェースと同様に、rmicが実行される前にすでにjavacで正常にコンパイルされています。既存の構築手順が、一部のアプリケーション・ソース・ファイルをコンパイルするrmicの以前の動作に依存している場合、その構築手順を修正し、rmicを実行する前に、必要なすべてのクラスがjavacで正しくコンパイルされるようにしてください。

サーバー側スタック・トレースがリモートの例外に保持される(Java SE 1.4以降)
Java RMIランタイム実装が、以前のリリースで行なっていたようにクライアント側スタック・トレースを記入するだけでなく、リモート呼び出しからスローされる例外のサーバー側スタック・トレース情報を保持するようになりました。したがって、そのような例外がクライアント・コードにアクセス可能になると、そのスタック・トレースには、元のサーバー側トレース・データと、それに続くクライアント側トレースのすべてが含まれることになります。

この機能は、Java SE 1.4のjava.lang.Throwableの新しい「スタック・トレース情報へのプログラムによるアクセス」機能によって可能になりました。これには、デフォルトの直列化形式のThrowableのスタック・トレース・データ部分の作成が含まれます。クライアント側Java RMIランタイム実装は、この機能と連携するために、以前のリリースのように単にクライアント側トレースで上書きするのではなく、クライアント側トレースを非整列化されたサーバー側トレースに追加します。

特定のサーバー・アプリケーションでは、パフォーマンスや機密上の理由により、Java SE 1.4での例外のデフォルトの直列化形式の一部としてリモート呼出しにより直列化される例外がサーバー側スタック・トレース・データで発生しないようにする場合があります。そのような場合は、実装に固有のシステム・プロパティである

sun.rmi.server.suppressStackTraces
を「true」に設定すると、サーバー側Java RMIランタイム実装によって、リモート・メソッドの呼出しの結果、現在の仮想マシンからスローされたすべての例外のスタック・トレースが消去されます。
RMIClassLoader用サービス・プロバイダ・インタフェース(Java SE 1.4以降)
java.rmi.server.RMIClassLoaderの一部のstaticメソッドの動作は、新しいサービス・プロバイダ・インタフェースjava.rmi.server.RMIClassLoaderSpiのインスタンスに委譲されています。特定のアプリケーションに対するJava RMI動的クラスのロード動作を拡張するようにサービス・プロバイダを構成できます。デフォルトでは、サービス・プロバイダは、RMIClassLoaderのstaticメソッドすべての標準動作を実装しています。詳細については、RMIClassLoaderおよびRMIClassLoaderSpiのクラス・ドキュメントを参照してください。
動的なサーバー・ホスト名(Java SE 1.4以降)
java.rmi.server.hostnameプロパティが動的に更新され、そのあとのエクスポートで新しいホスト名を使用するように指示できるようになりました。したがって、新しいホスト名の値は、このプロパティが更新されたあとにエクスポートされるオブジェクトのスタブに格納されます。
HTTPフォール・バック構成の拡大(Java SE 1.4.1以降)
実装固有のシステム・プロパティsun.rmi.transport.proxy.eagerHttpFallbackが追加され、Java RMIのデフォルトのソケット・ファクトリがHTTPトンネリングにフォール・バックする際により細かく制御できるようになりました。このプロパティは、デフォルトのソケット・ファクトリを構成して、最初の(直接的な)接続試行によってスローされたSocketExceptionがHTTPトンネリングのトリガーになるようにします。より「積極的」になったこのフォール・バック戦略は、承認されていないポートへの接続試行を無視するのではなく、拒否するファイアウォールに対処する場合に役に立つ場合があります。
java.rmi.Naming.listメソッドは返される名前にスキームを付加することはない(Java SE 1.4.1以降)
以前のリリースでは、Naming.listメソッドは、返された文字列の配列に含まれる名前にスキームrmi: を付加していました。現在のNNaming.listの実装はその仕様に合致しており、URL形式の名前の配列を返しますが、スキーム・コンポーネントは含まれません。
java.rmi.activation.ActivationGroupDesc (Java SE 1.3以降)
グループのクラス名を返すgetClassNameメソッドが、システムのデフォルト・グループ実装を示すnullを返すことが可能になりました。これまでは、記述子の構築時にデフォルトのグループ実装が選択された場合、getClassNameメソッドは内部の実装クラスの名前を返していました。

この変更に対応するために、Java SE 1.3の仮想マシンで稼働するアプリケーションが新たな起動可能オブジェクトをActivationSystemに登録する場合、rmidもJava SE 1.3を実行できるようにアップグレードする必要があります。これは、1.3より前のrmidでは新たに登録された起動可能オブジェクトを起動できないためです。

Java RMIスタブ・コンパイラrmic (Java SE 1.3以降)
rmic (Solaris、LinuxまたはMac OS X用Windows用)では、スタブのデフォルトの生成先ディレクトリが、パッケージ名の付いた、現在の作業ディレクトリのサブディレクトリになりました。「-d」オプションを指定しない場合は、現在の作業ディレクトリ「.」が引数として指定されていると見なされます。デフォルトの生成先ディレクトリをオーバーライドするには、引き続き「-d」を使用できます。

IDLおよびIIOPのスタブを生成するために、2つの新しいオプション「-idl」および「-iiop」が追加されました。

Java RMI起動デーモンrmid (Java SE 1.3以降)
デフォルトでは、rmid (Solaris、LinuxまたはMac OS X用Windows用)は現在、セキュリティ・ポリシー・ファイルを要求します。
リモート・オブジェクトの直列化(Java SE 1.2.2以降)
Java SE 1.2.2以前では、アンエクスポートされたリモート・オブジェクトをRMI呼出しで渡そうとすると、java.rmi.StubNotFoundExceptionが発生しました。リモート・オブジェクトの実装を対応するスタブに置換しようとしている最中にRMIランタイムがスタブ・オブジェクトを見つけられなかった場合に、この例外が発生しました。Java SE 1.2.2以降のリリースでは、アンエクスポートされたリモート・オブジェクトがRMI呼出しで渡されても例外とはならず、スタブではなく、リモート・オブジェクトが直列化されます。リモート・オブジェクトの実装が直列化できない場合、アンエクスポートされたオブジェクトをRMI呼出しで渡そうとすると、java.rmi.RemoteExceptionとなります。この例外には、java.io.NotSerializableExceptionが入れ子にされています。

Copyright © 1993, 2020, Oracle and/or its affiliates. All rights reserved.