回答:
バイロンの答えごとに、あなたが設定することはできませんnetworkaddress.cache.ttl
またはnetworkaddress.cache.negative.ttl
使用することにより、システムのプロパティとして-D
フラグを呼び出すか、System.setProperty
これらはシステムのプロパティではありませんので、 -それらはセキュリティのプロパティ。
システムプロパティを使用してこの動作をトリガーする(-D
フラグを使用するかを呼び出すことができるSystem.setProperty
)場合は、次のシステムプロパティを設定する必要があります。
-Dsun.net.inetaddr.ttl=0
このシステムプロパティは、目的の効果を有効にします。
ただし、注意してください-D
。JVMプロセスの開始時にフラグを使用せず、コードからこれを呼び出すことを選択した場合:
java.security.Security.setProperty("networkaddress.cache.ttl" , "0")
このコードは、JVMの他のコードがネットワーク操作を実行する前に実行する必要があります。
これは重要です。たとえば、Security.setProperty
.warファイルを呼び出して.warをTomcatにデプロイした場合、これは機能しません。Tomcatは、.warのコードが実行されるよりもはるか前に、Javaネットワークスタックを使用して初期化します。この「競合状態」のため、通常-D
、JVMプロセスを開始するときにフラグを使用する方が便利です。
を使用し-Dsun.net.inetaddr.ttl=0
たり呼び出したりしない場合は、そのファイルのセキュリティプロパティSecurity.setProperty
を編集$JRE_HOME/lib/security/java.security
して設定する必要があります。たとえば、
networkaddress.cache.ttl = 0
networkaddress.cache.negative.ttl = 0
ただし、これらのプロパティに関するコメントのセキュリティ警告に注意してください。DNSスプーフィング攻撃の影響を受けにくいと確信できる場合にのみ、これを行ってください。
Javaには、非常に奇妙なDNSキャッシング動作があります。あなたの最善の策は、DNSキャッシングをオフにするか、5秒などの低い数値に設定することです。
networkaddress.cache.ttl(デフォルト:-1)
ネームサービスからの名前検索が成功した場合のキャッシュポリシーを示します。値は整数として指定され、成功したルックアップをキャッシュする秒数を示します。値-1は、「永久にキャッシュ」を示します。networkaddress.cache.negative.ttl(デフォルト:10)
ネームサービスからの名前検索が失敗した場合のキャッシュポリシーを示します。値は整数として指定され、失敗したルックアップの失敗をキャッシュする秒数を示します。値0は、「キャッシュしない」を示します。値-1は、「永久にキャッシュ」を示します。
System.getSecurityManager()
。Javaの8のためのドキュメント:docs.oracle.com/javase/8/docs/api/java/lang/...
これは明らかに新しいリリース(SE 6および7)で修正されています。tcpdumpを使用してポート53のアクティビティを監視しながら次のコードスニペットを実行すると、最大30秒のキャッシュ時間が発生します。
/**
* http://stackoverflow.com/questions/1256556/any-way-to-make-java-honor-the-dns-caching-timeout-ttl
*
* Result: Java 6 distributed with Ubuntu 12.04 and Java 7 u15 downloaded from Oracle have
* an expiry time for dns lookups of approx. 30 seconds.
*/
import java.util.*;
import java.text.*;
import java.security.*;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
public class Test {
final static String hostname = "www.google.com";
public static void main(String[] args) {
// only required for Java SE 5 and lower:
//Security.setProperty("networkaddress.cache.ttl", "30");
System.out.println(Security.getProperty("networkaddress.cache.ttl"));
System.out.println(System.getProperty("networkaddress.cache.ttl"));
System.out.println(Security.getProperty("networkaddress.cache.negative.ttl"));
System.out.println(System.getProperty("networkaddress.cache.negative.ttl"));
while(true) {
int i = 0;
try {
makeRequest();
InetAddress inetAddress = InetAddress.getLocalHost();
System.out.println(new Date());
inetAddress = InetAddress.getByName(hostname);
displayStuff(hostname, inetAddress);
} catch (UnknownHostException e) {
e.printStackTrace();
}
try {
Thread.sleep(5L*1000L);
} catch(Exception ex) {}
i++;
}
}
public static void displayStuff(String whichHost, InetAddress inetAddress) {
System.out.println("Which Host:" + whichHost);
System.out.println("Canonical Host Name:" + inetAddress.getCanonicalHostName());
System.out.println("Host Name:" + inetAddress.getHostName());
System.out.println("Host Address:" + inetAddress.getHostAddress());
}
public static void makeRequest() {
try {
URL url = new URL("http://"+hostname+"/");
URLConnection conn = url.openConnection();
conn.connect();
InputStream is = conn.getInputStream();
InputStreamReader ird = new InputStreamReader(is);
BufferedReader rd = new BufferedReader(ird);
String res;
while((res = rd.readLine()) != null) {
System.out.println(res);
break;
}
rd.close();
} catch(Exception ex) {
ex.printStackTrace();
}
}
}
バイロンの答えを拡張するにjava.security
は、%JRE_HOME%\lib\security
ディレクトリ内のファイルを編集してこの変更を有効にする必要があると思います。
関連セクションは次のとおりです。
#
# The Java-level namelookup cache policy for successful lookups:
#
# any negative value: caching forever
# any positive value: the number of seconds to cache an address for
# zero: do not cache
#
# default value is forever (FOREVER). For security reasons, this
# caching is made forever when a security manager is set. When a security
# manager is not set, the default behavior is to cache for 30 seconds.
#
# NOTE: setting this to anything other than the default value can have
# serious security implications. Do not set it unless
# you are sure you are not exposed to DNS spoofing attack.
#
#networkaddress.cache.ttl=-1
java.security
ファイルのドキュメントはこちら。
他の回答を要約する<jre-path>/lib/security/java.security
と、プロパティの値を設定して、networkaddress.cache.ttl
DNSルックアップのキャッシュ方法を調整できます。これはシステムプロパティではなくセキュリティプロパティであることに注意してください。私はこれを使ってこれを設定することができました:
java.security.Security.setProperty("networkaddress.cache.ttl", "<value>");
これはシステムプロパティで-Dsun.net.inetaddr.ttl
も設定できますが、セキュリティプロパティが他の場所で設定されている場合、これはオーバーライドされません。
また、WebSphereのWebサービスでこの問題が発生している場合、私がそうであったように、設定networkaddress.cache.ttl
だけでは不十分であることも付け加えておきます。システムプロパティdisableWSAddressCaching
をに設定する必要がありますtrue
。有効期間プロパティとは異なり、これはJVM引数として、またはSystem.setProperty
)を介して設定できます。
IBMは、ここで WebSphereがDNSキャッシングをどのように処理するかについてかなり詳細な投稿をしています。上記に関連する部分は次のとおりです。
Webサービスのアドレスキャッシングを無効にするには、追加のJVMカスタムプロパティdisableWSAddressCachingをtrueに設定する必要があります。このプロパティを使用して、Webサービスのアドレスキャッシュを無効にします。通常、システムが多数のクライアントスレッドで実行されているときにwsAddrCacheキャッシュでロックの競合が発生した場合は、このカスタムプロパティをtrueに設定して、Webサービスデータのキャッシュを回避できます。
公式のoracle javaプロパティによると、sun.net.inetaddr.ttl
Sunの実装固有のプロパティであり、「将来のリリースではサポートされなくなる可能性があります」。「推奨される方法は、セキュリティプロパティを使用することnetworkaddress.cache.ttl
です」。
java.security.Security
(少なくともjdk7では)