ネットワーク IPv6 ユーザガイド (JDK/JRE 5.0)


このドキュメントでは、次のトピックについて説明します。

概要

このわずか数年で、IPv6 は業界で (特に、ヨーロッパとアジア太平洋地域の業界で)、幅広く受け入れられるようになりました。拡張性、モビリティ、サービス品質、広大なアドレス空間、自動 構成、セキュリティ、マルチホーム、エニーキャストとマルチキャスト、リナンバリングなどは、IPv6 で実現できる機能の一部です。

J2SE 1.4 が 2002 年 2 月にリリースされてから、Java では Solaris と Linux での IPv6 サポートを開始しました。Windows での IPv6 サポートは、J2SE 5.0 で追加されました。C や C++ などのその他の言語でも IPv6 をサポートしていますが、 Java には大きな利点がいくつかあります。

後述するコード例で以上の点を証明し、IPv6 サポートについて追加の情報を説明します。

サポートされるオペレーティングシステム

J2SE リファレンス実装では、次のオペレーティングシステムがサポートされています。

Java での IPv6 の使用

IPv6 を Java で使用するのは簡単かつ透過的で自動的に行われます。その他の多くの言語とは異なり、移植は必要ありません。実際、ソースファイルの再コンパイルさえ必要 ありません。

「The Java Tutorial」からの例を示します。

Socket echoSocket = null;
   PrintWriter out = null;
   BufferedReader in = null;

   try {
      echoSocket = new Socket("taranis", 7);
      out = new PrintWriter(echoSocket.getOutputStream(), true);
      in = new BufferedReader(new InputStreamReader(
         echoSocket.getInputStream()));
   } catch (UnknownHostException e) {
      System.err.println("Don't know about host: taranis.");
      System.exit(1);
   } catch (IOException e) {
      System.err.println("Couldn't get I/O for "
         + "the connection to: taranis.");
      System.exit(1);
   }
// ... code omitted here
communicateWithEchoServer(out, in);

out.close();
in.close();
stdIn.close();
echoSocket.close();

ローカルホストマシンと宛先マシン (taranis) が IPv6 に対応していれば、この例と同じバイトコードを IPv6 モードで実行することができます。

対照的に、対応する C プログラムを IPv6 モードで実行しようとすると、最初に移植しなければなりません。次に、何をしなければならないかを示します。

オリジナルの C コードの一部

struct sockaddr_in sin;
struct hostent *hp;
int sock;

/* Open socket.*/
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == -1) {
   perror("socket");
   return (-1);
}

/* Get host address */
hp = gethostbyname(hostname);
if (hp == NULL || hp->h_addrtype != AF_INET || hp->h_length != 4) {
   (void) fprintf(stderr, "Unknown host '%s'\n", hostname);
   (void) close(sock);
   return (-1);
}

sin.sin_family = AF_INET;
sin.sin_port = htons(port);
(void) memcpy((void *) &sin.sin_addr, (void *)hp->h_addr, hp->h_length);

/* Connect to the host */
if (connect(sock, (struct sockaddr *)&sin, sizeof(sin)) == -1) {
   perror("connect");
   (void) close(sock);
   return (-1);
}

修正した IPv6 対応の C コード

struct addrinfo *res, *aip;
struct addrinfo hints;
int sock = -1;
int error;

/* Get host address.Any type of address will do. */
bzero(&hints, sizeof(hints));
hints.ai_flags = AI_ALL|AI_ADDRCONFIG;
hints.ai_socktype = SOCK_STREAM;

error = getaddrinfo(hostname, servicename, &hints, &res);
if (error != 0) {
   (void) fprintf(stderr,
      "getaddrinfo: %s for host %s service %s\n",
      gai_strerror(error), hostname, servicename);
   return (-1);
}
/* Try all returned addresses until one works */
for (aip = res; aip != NULL; aip = aip->ai_next) {
   /*
   * Open socket.The address type depends on what
   * getaddrinfo() gave us.
   */
   sock = socket(aip->ai_family, aip->ai_socktype, aip->ai_protocol);
   if (sock == -1) {
      perror("socket");
      freeaddrinfo(res);
      return (-1);
   }

/* Connect to the host.*/
if (connect(sock, aip->ai_addr, aip->ai_addrlen) == -1) {
   perror("connect");
   (void) close(sock);
   sock = -1;
   continue;
}
break;
}
   freeaddrinfo(res);

新しいアプリケーションの場合、アドレスファミリを許容するデータ構造体を作成した場合、移植は必要ありません。

しかし、C または C++ によるサーバサイドプログラミングでは、さらに欠点があります。アプリケーションが Solaris や Linux などのデュアルスタックプラットホーム用に作成されたものか、Windows などのシングルスタックプラットホーム用に記述されたものなのかによって、異なるコード構造にしなければなりません。サーバサイドプログラミングの場合、 Java には大きな利点があります。これまでどおり、同じコードを記述します。

ServerSocket server = new ServerSocket(port);
Socket s;
while (true) {
   s = server.accept();
   doClientStuff(s);
}

そして、このコードを IPv6 対応のマシンで実行する場合は、IPv6 対応サービスをすぐに提供できます。

デュアルスタックプラットホームで、C による対応するサーバコードは次のとおりです。

int ServSock, csock;
struct sockaddr addr, from;
...
ServSock = socket(AF_INET6, SOCK_STREAM, PF_INET6);
bind(ServSock, &addr, sizeof(addr));
do {
   csock = accept(ServSocket, &from, sizeof(from));
   doClientStuff(csock);
} while (!finished);

デュアルスタックマシンでは、IPv6 ソケット 1 つが IPv4 と IPv6 プロトコルスタックの両方にアクセスするため、1 ソケットだけ作成する必要があります。そのため、このサーバは潜在的に IPv4 と IPv6 クライアントの両方をサポートできます。

シングルスタックプラットホーム用の、同じサーバの C コードは次のようになります。

SOCKET ServSock[FD_SETSIZE];
ADDRINFO AI0, AI1;
ServSock[0] = socket(AF_INET6, SOCK_STREAM, PF_INET6);
ServSock[1] = socket(AF_INET, SOCK_STREAM, PF_INET);
 ...
bind(ServSock[0], AI0->ai_addr, AI0->ai_addrlen);
bind(ServSock[1], AI1->ai_addr, AI1->ai_addrlen);
 ...
select(2, &SockSet, 0, 0, 0);
if (FD_ISSET(ServSocket[0], &SockSet)) {
   // IPv6 connection csock = accept(ServSocket[0], (LPSOCKADDR)&From, FromLen);
    ...
}
if (FD_ISSET(ServSocket[1], &SockSet))
   // IPv4 connection csock = accept(ServSocket[1], (LPSOCKADDR)&From, FromLen);
    ...
}

ここでは、IPv6 スタック用に 1 つと IPv4 スタック用に 1 つ、合計 2 つのサーバソケットを作成する必要があります。また、IPv4 または IPv6 クライアントからの接続を待機するために、2 つのソケット上で多重化する必要があります。

Java を使用すれば、J2SE 1.4 以降を使用して、あらゆる Java アプリケーション、クライアント、またはサーバを IPv6 対応プラットホームで実行できます。また、アプリケーションは魔法のように自動的に IPv6 対応となります。

対照的に、レガシーなネイティブ言語アプリケーションでは、C または C++ アプリケーションを IPv6 対応にしようとすると、移植と再コンパイルが必要になります。

Java プラットホームでの IPv6 の動作

Java ネットワーキングスタックはまず、IPv6 を基本となる OS でサポートしているかどうかを確認します。IPv6 がサポートされている場合は、IPv6 スタックを使用しようとします。具体的には、デュアルスタックシステムの場合、IPv6 ソケットを作成します。個別スタックシステムの場合は、もっと複雑です。IPv4 通信と IPv6 通信用に 1 つずつ、合計 2 つのソケットを作成します。クライアント側の TCP アプリケーションでは、ソケットが接続されると、インターネットプロトコルファミリータイプが固定され、もう 1 つのソケットが閉じられます。サーバ側の TCP アプリケーションでは、次のクライアント要求がどの IP ファミリータイプから送信されるかを知る方法がないため、2 つのソケットを維持しておく必要があります。UDP アプリケーションでは、通信の継続期間中、両方のソケットが必要です。

Java では、ネームサービスから IP アドレスを取得します。

Java での IPv6 サポートの詳細

IPv6 を Java で使用するには、次の内容を知っておく必要はありません。しかし、さまざまな状況で疑問を感じたり何が行われているのかを知るために、このドキュメントの 残りの部分で説明しておきます。

特殊な IPv6 アドレス型

未指定アドレス (:: IPv4 の 0.0.0.0 に対応)

これは「エニーローカル (anylocal)」または「ワイルドカード」アドレスとも呼ばれます。ソケットがデュアルスタックのマシン上の IPv6 エニーローカルアドレスにバインドされている場合、そのソケットは、IPv6 トラフィックと IPv4 トラフィックの両方を受け入れることができます。ソケットが IPv4 (IPv4 マップ) エニーローカルアドレスにバインドされている場合、そのソケットは IPv4 トラフィックだけを受け入れることができます。デュアルスタックのマシン上では、関連するシステムプロパティで IPv4 スタックの指定が設定されていないかぎり、IPv6 エニーローカルアドレスにバインドすることが試みられます。

:: にバインドされているとき、メソッド ServerSocket.accept は、IPv6 ホストと IPv4 ホストの両方からの接続を受け入れます。現在の Java プラットフォーム API では、IPv6 ホストからの接続だけを受け入れるように指定する方法はありません。

アプリケーションでは、NetworkInterface を使用してインタフェースを列挙し、各 IPv6 アドレスに ServerSocketChannel をバインドして、New I/O API からのセレクタを使用してそれらのソケットからの接続を受け入れることができます。

注: このあと説明するオプションは、Draft-ietf-ipngwg-rfc2553bis-03.txt で導入されています。それが標準規格になった時点で、そのオプションが Java 2 プラットフォームでサポートされる予定です。

ただし、前述の動作を変更する、新しいソケットオプションがあります。Draft-ietf-ipngwg-rfc2553bis-03.txt では、新しい IP レベルのソケットオプションとして、IPV6_V6ONLY が導入されました。このソケットオプションは、AF_INET6 ソケットを IPv6 通信だけに限定します。通常、AF_INET6 ソケットは、IPv4 および IPv6 の両方の通信のために使用できます。アプリケーションによっては、AF_INET6 ソケットの使用を IPv6 通信だけに限定したい場合があります。そのようなアプリケーションでは、IPV6_V6ONLY ソケットオプションを定義します。このオプションをオンに設定すると、IPv6 パケットだけを送受信するためにそのソケットを使用できます。デフォルトでは、このオプションはオフになっています。

ループバックアドレス (::1 IPv4 の 127.0.0.1 に対応)

ループバックアドレスを指定されたパケットは、決してリンク上に送信したり、IPv6 ルータによって転送したりしないでください。IPv4 と IPv6 には 2 つの異なるループバックアドレスがあり、それぞれ別個に処理されます。

IPv4 と IPv6 のアドレスは、「::」の場合を除いて、別々のアドレス空間を占めます。

互換アドレス (::w.x.y.z)

このアドレスは、ホストおよびルータが、IPv6 パケットを IPv4 ルーティングインフラストラクチャ上を動的にトンネルするために使用されます。このアドレスは、OS カーネルとルータに対して意味を持ちます。Java では、このアドレスをテストするためのユーティリティメソッドが提供されています。

IPv4 マップアドレス (::ffff:w.x.y.z)

これは、IPv4 アドレスを表現するために使用される IPv6 アドレスです。このアドレスを利用すると、ネイティブプログラムでは、IPv4 ノードと IPv6 ノードの両方と通信する際に、同じアドレスデータ構造と、さらには同じソケットを使用できます。このため、IPv4 マップアドレスをサポートするデュアルスタックノード上では、IPv6 アプリケーションは IPv4 ピアと IPv6 ピアの両方と通信できます。IPv4 のデータグラムを送受信するのに必要な基本となる諸処理は OS が実行して、その結果を IPv6 の宛先ソケットに渡します。また、OS は、必要なときに IPv4 マップ IPv6 アドレスを合成します。

Java では、このアドレスは内部の表現に使用され、機能上の役割はありません。Java から IPv4 マップアドレスが返されることはありません。Java では、IPv4 マップアドレスの構文が、バイト配列とテキスト表現の両方で理解されます。ただし、そのアドレスは IPv4 アドレスに変換されます。

IPv6 関連のシステムプロパティ

デュアルスタックマシンでは、優先されるプロトコルスタック (IPv4 または IPv6) と、優先されるアドレスファミリの型 (inet4 または inet6) を設定するためのシステムプロパティが提供されます。

デフォルトでは、IPv6 スタックが優先されます。デュアルスタックマシンでは、IPv6 ソケットが IPv4 ピアと IPv6 ピアの両方と通信できるためです。

この設定を変更するには、java.net.preferIPv4Stack=<true|false> システムプロパティを使用します。

アドレスのデフォルトについては、IPv6 アドレスよりも IPv4 アドレスをお勧めします。ネームサービス (DNS サービスなど) に照会すると、IPv6 アドレスではなく IPv4 アドレスが返されます。この選択には、次の 2 つの理由があります。

  1. 一部のアプリケーションでは、IPv4 アドレスのテキスト形式 (%d.%d.%d.%d) が想定されている。IPv4 アドレスを使用すれば、予期しない動作を最小限にできる
  2. IPv4 アドレスを使用すれば、1 つの呼び出し (IPv6 ソケットを使う) で、旧来の IPv4 だけのサービスと、IPv6 サービスのどちらにも到達できる (IPv6 サービスが IPv6 だけのノード上にない場合)

この設定を変更するには、java.net.preferIPv6Addresses=<true|false> システムプロパティを使用します。

デュアルスタックノード

今後何年もの間 (永久にではないとしても)、インターネットは IPv6 ノードと IPv4 ノードが混在した状態になるでしょう。このため、IPv4 ノードの大規模なインストールベースとの互換性が、IPv4 から IPv6 への移行を成功させるために重要です。デュアルスタック (RFC 1933 で定義されている) は、円滑な移行を保証するための主要な機構の 1 つです。もう 1 つの機構は IPv6 パケットのトンネリングですが、この機構と J2SDK との関連性は IPv4 互換アドレスに関係するものだけです。前者の機構は、J2SDK ともっとも関連性があります。デュアルスタックには、IPv4 と IPv6 の両方のバージョンのインターネットプロトコルを実装することが含まれます。

デュアルスタックノードの一般的な特性は、IPv6 ソケットが IPv4 ピアおよび IPv6 ピアの両方とトランスポート層 (TCP または UDP) で通信できるということです。ネイティブレベルでは、IPv6 ソケットは、IPv4 マップ IPv6 アドレスを使って IPv4 と通信します。ただし、ソケットがピアのアドレス型を調べないかぎり、IPv4 ピアまたは IPv6 ピアのどちらと通信しているかをソケットが認識することはありません。アドレス型に関係した内部の処理と変換はすべて、デュアルプロトコルスタックによっ て実行されます。

注: IPv4 マップアドレスは、デュアルプロトコルスタックの実装においてだけ意味を持ちます。IPv4 マップアドレスは、IPv6 アドレスを「模倣」して (IPv6 と同じ形式になるようにして)、アドレスを IPv6 ソケットに渡せるようにするために使用されます。概念上のレベルでは特に役割がなく、その役割は Java API のレベルに限定されています。IPv4 マップアドレスの解析はサポートされていますが、IPv4 マップアドレスが返されることはありません。

Java アプリケーションへの影響

  1. すべてが適切に記述されていれば、Java アプリケーションコードに変更は必要ない。つまり、IPv4 のリテラルアドレスを直接に参照するのではなく、ホスト名を使用していればよい
  2. アドレスやソケットの型に関する情報はすべて、Java ネットワーク API にカプセル化されている
  3. システムプロパティを設定することで、優先されるアドレスやソケットの型を設定できる
  4. 新規アプリケーションでは、IPv6 に固有の新しいクラスおよび API を利用できる

通信のシナリオ

(ノード) V4 のみ V4/V6 V6 のみ
V4 のみ x x  
V4/V6 x x x
V6 のみ   x x

1 番上の行と左端の列は、通信しようとするノードの種類を表します。「x」は、それらのノードが互いに通信できることを示します。

UDP
シナリオ 1:

host1 または host2 のどちらかは、ネイティブアプリケーションにできます。

host1 がサーバ、host2 がクライアント

host2 から host1 に通信しようとするとき、host2 は V6 ソケットを作成します。次に、host2 は host1 の IP アドレスを検索します。host1 は V4 プロトコルスタックだけしか持っていないため、名前検索サービスにも IPv4 のレコードしかありません。そのため、hots2 は IPv4 マップアドレスを使って host1 に到達しようとします。host2 からは IPv4 パケットが送信されてくるので、host1 は、自身が V4 クライアントと通信しているものと認識します。

host1 がクライアント、host2 がサーバ

host2 がサーバの場合、host2 はまず V6 型のソケット (これがデフォルト) を作成して、接続を待機します。host1 は V4 だけしかサポートしていないため、host1 は V4 型のソケットを作成します。両者は、host2 の名前を解決します。host1 は、IPv6 アドレスを認識しないため、host2 の V4 アドレスだけを取得します。そのため、host1 は V4 アドレスを使って host2 に接続します。そして、V4 パケットが回線上に送信されます。host2 では、デュアルスタックによって V4 パケットが V6 パケット (V4 マップアドレスを持つ) に変換され、V6 ソケットに渡されます。サーバアプリケーションは、それが V6 ノードからの接続であるかのようにしてパケットを処理します。

クラスの変更

InetAddress

このクラスは、IP アドレスを表します。そして、アドレスの格納場所、名前とアドレスを変換するメソッド、アドレスを変換するメソッド、およびアドレスをテストするメソッド を提供します。J2SE 1.4 では、IPv4 アドレスと IPv6 アドレスの両方をサポートするようにこのクラスが拡張されました。また、アドレス型とスコープをチェックするユーティリティメソッドが追加されました。 IPv4 と IPv6 という 2 つの型のアドレスは、Java 型の Inet4Address および Inet6Address によって区別できます。

InetAddress の新しいサブクラスとして、Inet4Address および Inet6Address の 2 つのクラスが作成されました。この 2 つのサブクラスには、V4 および V6 に固有の状態と動作が実装されています。Java のオブジェクト指向の性質のため、アプリケーションは通常、InetAddress クラスを取り扱うだけで済みます。多相性によって、正しい動作を得ることができるためです。各プロトコルファミリに固有の動作にアクセスする必要がある場 合 (たとえば、IPv6 専用のメソッドを呼び出す場合や、IP アドレスのクラス型を知る必要がある場合) にかぎり、アプリケーションは Inet4AddressInet6Address を区別することになります。

導入された新しいメソッドは次のとおりです。

InetAddress:
isAnyLocalAddress
isLoopbackAddress
isLinkLocalAddress
isSiteLocalAddress
isMCGlobal
isMCNodeLocal
isMCLinkLocal
isMCSiteLocal
isMCOrgLocal
getCanonicalHostName
getByAddr

Inet6Address:
isIPv4CompatibleAddress

InetAddress および異なるネームサービス

1.4 より前では、InetAddress は、システムに構成されたネームサービスを利用してホスト名を解決していました。1.4 では、代わりになる名前検索手段として、JNDI を介した Java DNS プロバイダが追加されました。いくつかのシステムプロパティを設定すれば、このプロバイダを使用するように J2SDK に命令することができます。これらのシステムプロパティについては、Java システムプロパティの項に説明があります。将来的には、開発者が独自のネームサービスプロバイダを記述できるようにするため、汎用的なサービスプロバイダ のフレームワークを提供する予定です。

直列化について

すべての IPv4 アドレスは、Java では Inet4Address オブジェクトとして表現されます。そのオブジェクトは InetAddress オブジェクトとして直列化され、下位互換性を保つために、InetAddress からは Inet4Address に直列化復元されます。IPv6 アドレスは Inet6Address として表現され、同様に直列化されます。

SocketServerSocket、および DatagramSocket

Java のオブジェクト指向の性質のため、アドレスの種類と情報を格納している構造体は、ソケット API のレベルでは公開されません。そのため、新しい API は不要です。既存のソケット API により、IPv4 トラフィックと IPv6 トラフィックの両方が扱われます。

どちらのスタックが使用されるかの選択は、次の基準によります。

  1. 基本となる OS サポート
  2. 優先するスタックに関するプロパティをユーザがどのように設定したか

サポートされるすべての IPv6 ソケットオプションには、対応する IPv4 オプションがあります。したがって、IPv6 ソケットオプションをサポートするための新しい API は追加されていません。その代わりに、古い API が、V4 と V6 の両方のソケットオプションをサポートするようにオーバーロードされました。

MulticastSocket

このソケットの場合も、ソケットオプションのすべての API が、IPv6 のマルチキャストソケットオプションをサポートするようにオーバーロードされました。

ネットワークインタフェースを設定および取得するための新しい 2 つの API が追加されました。これは、InetAddress インスタンスを設定および取得する既存の MulticastSocket.setInterface および MulticastSocket.getInterface とは別に追加されたものです。2 つの既存のメソッドは、マルチキャストパケットを送信するための現在の MulticastSocket で使用されているネットワークインタフェースを設定または取得するために使用されます。IPv4 の場合、インタフェースは IP アドレスによって示されていました。そのため、Java では、それと等価の InetAddress を使用できます。この 2 つのメソッドは、IPv6 のマルチキャストソケットに対しても引き続き機能します。ただし、IPv6 では、RFC 2553 の仕様によると、インタフェースはインタフェースインデックスを使って示す必要があります。ネットワークインタフェースの概念をより適切にサポートするた め、新しいクラスとして NetworkInterface が導入されました。このクラスは、ネットワークインタフェースの状態を表すデータをカプセル化します。名前や IP アドレスなどのデータと、いくつかの基本操作を実行するメソッドが組み込まれています。これに伴い、マルチキャストソケットの送出インタフェースを設定す るための新しい 2 つのメソッドとして、setNetworkInterfacegetNetworkInterface が導入されました。この 2 つのメソッドは、NetworkInterface オブジェクトを引数にとり、戻り値として返します。新しいメソッドは、V4 と V6 の両方のマルチキャストで使用できます。

さらに、ネットワークインタフェース上のマルチキャストグループに参加したり、そこから抜けたりするためのメソッドも追加されました。これは、以前 の Java API では利用できませんでした。

MulticastSocket:
NetworkInterface getNetworkInterface()
setNetworkInterface(NetworkInterface netIf)
joinGroup(SocketAddress mcastaddr,NetworkInterface netIf)
leaveGroup(SocketAddress mcastaddr,NetworkInterface netIf)

URLURI パーサ

URL や URI では、リテラル IP アドレスを使用できます。ただし、既存の URL および URI の仕様では、ホストとポートを区切るためにコロン (:) が使用されているため、現状のままで URL または URI にリテラルの IPv6 表現を使用すると、解析に失敗します。このため、URL や URI にリテラルの IPv6 アドレスを指定するために、RFC 2732 が作成されました。URL と URI の解析処理は、RFC 2732 に準拠するように更新されました。

SocketPermission

SocketPermission は URL を利用するので、RFC 2732 に準拠するように実装が更新されました。

アクセス権を定義するのに使用される codebase は、URL を変形したものです。したがって、codebase も、URL の形式と規定に従う必要があります。URL と codebase の場合は RFC 2732 形式が使用され、その他の場合には RFC 2373 形式が使用されます。

IPv6 のネットワークプロパティ

java.net.preferIPv4Stack (デフォルト: false)

IPv6 を利用可能なオペレーティングシステムでは、基本となるネイティブソケットは IPv6 ソケットです。このため、Java(TM) アプリケーションは、IPv4 ホストと IPv6 ホストの両方に接続したり、その両方のホストからの接続を受け入れたりできます。

IPv4 ソケットだけを使用するよう設定されているアプリケーションでは、このプロパティを true に設定できます。つまり、そのアプリケーションは IPv6 ホストと通信できないということです。

java.net.preferIPv6Addresses (デフォルト: false)

IPv6 を利用可能なオペレーティングシステムでは、デフォルトの設定として、IPv4 マップのアドレスを IPv6 アドレスよりも優先するようになっています。これは、下位互換性の理由によります。たとえば、IPv4 だけのサービスへのアクセスに依存するアプリケーションや、%d.%d.%d.%d の形式で表現された IP アドレスに依存するアプリケーションとの互換性のためです。
IPv6 アドレスを IPv4 アドレスよりも優先する設定を試してみるには、このプロパティを true に設定します。そうすれば、アプリケーションが IPv6 サービスに接続されると予想される環境でアプリケーションをテストし、そのような環境にアプリケーションを配置することができます。

JNDI DNS サービスプロバイダの設定

sun.net.spi.nameservice.provider.<n>=<default|dns,sun|...>

使用できるネームサービスプロバイダを指定します。デフォルトでは、Java は、システムに構成された名前検索機構を使用します (file、nis など)。このオプションを設定すると、独自の名前サービスプロバイダを指定できます。<n> には、正の数値を指定します。この数値は優先順位を示しており、小さい値ほど優先順位が高くなります。1.4 では、JNDI を使用して 1 つの DNS ネームサービスプロバイダが提供されており、その名前は dns,sun です。

sun.net.spi.nameservice.nameservers=<server1_ipaddr,server2_ipaddr ...>

使用する DNS サーバを指す IP アドレスを、コンマで区切ったリストとして指定できます。

sun.net.spi.nameservice.domain=<domainname>

このプロパティでは、デフォルトの DNS ドメイン名 (たとえば、eng.sun.com) を指定します。