システムクロックの変化の影響を受けずに Java で時間を測定するにはどうすればよいですか?
質問
Javaで経過時間を計測したいと考えています。ただし、違いは System.currentTimeMillis()
そして(私は信じています) System.nanoTime()
誰か (またはシステム) がシステム クロックを変更するなど、外部の変化によって変更される可能性があります。
非常に頻繁かつ迅速な応答が必要になる可能性があるため、ネットワーク通話の使用はオプションではありません。
これに対する一般的な解決策はありますか?
編集
申し訳ありませんが、理由を詳しく説明する必要がありました。これは悪意のあるユーザーを阻止するためのものではありません。アイドル状態や日常的なクライアント イベントに対してクライアントが開始したログアウトなどです。
解決
これは本当にあなたの質問に答えていませんが、バグ#6458294 可能であれば、nanoTimeのSunの実装では、()(Linuxでは、Windows上でQueryPerformanceFrequency / QueryPerformanceCounterの上CLOCK_MONOTONIC)本当に単調あるメカニズムを使用することを意味します。これらが使用できない場合にのみ、それがバックシステムクロックの変更の影響を受けやすい仕組みに分類されます。
あなたはあなたが実行しているハードウェアの制御(または少なくとも知識)を持っており、これらのクロックメカニズムが利用可能になることを確認できた場合は、は、あなたが罰金を行います幸運とnanoTime()になっている可能性があります。
またHotSpot-を議論このブログの記事を、読むのが好きかもしれより詳細に上のWindowsケースます。
他のヒント
私はこれを行う方法はないと思います。
確かに堕落することができない、これを行う方法はありません。基本的に、あなたは現在の時刻としてのJavaアプリに報告されたものに、オペレーティングシステムとJVMの慈悲です。 Javaコードは、偽のタイムスタンプ値を取得し終わるように、これらのいずれかまたは両方がパッチを適用することができます。あなたはこれを防御しようとすることができますが、その後のすべてのハッカーは完全にライセンスチェックを無効にするために、あなたのアプリケーションにパッチを適用することで行う必要があります。
あなたは、Javaを使用しているかどうかをのレコードについては、この「脆弱性」は適用されます。
、あなたは暗号化され、安全なストレージのいくつかの並べ替えでは、これまで見てきた最高の時間を保存し、その後場合は、プログラムを無効にする必要がありますいずれかの時間は、あるいは、彼らが何らかの形で改ざんやセキュアストアを削除した場合。
(NTPクロック調整やコースのDSTの変更のためのいくつかの余裕をもって)あなたが見てきた最高未満行きますnanoTime()は、システムクロックが変化した場合に変更する可能性がある場合、私は知らないが、私はそれが可能だと仮定します。また、nanoTime()は正確ではないかもしれません。
あなたが本当にクロックの変更を防ぐために必要がある場合は、、あなたはスレッドでクロックを監視することができます。 100ms以上1000msでのための睡眠が、その後にcurrentTimeMillis()を呼び出します。時計はもっとして1000年+ Xを進めるか、後方しまった場合は、可能性の高いクロックが変更された(またはスレッドが可能な、何かにハングアップしてしまいました)。
和のイベントでは、実際にネットワーク呼び出しをチェックするために作ることができます。もちろん、それはネットワークの時間が原因うるう秒での挿入に変更される可能性がありますいる可能性があります。私はかつて、さまざまなソースの多くからの天文データを調整して、いくつかの科学者によってスラッシュドットのコメントをお読みください。閏秒は彼の実験中に添加し、いくつかのサイトがそれを挿入し、他の人がやっていないので、それは基本的にそれを台無しにします。
別の可能性は、いくつかの他のシステムタイマーを取得するために、低レベルのネイティブAPIを使用するのが良いかもしれません。このようなAPIを校正するシステムやネットワークの稼働時間など。 Windowsのブートからのミリ秒数を返すのGetTickCount()関数があります。 UNIXシステムでは、あなたは大まかな推定値を得るためにuptimeコマンドを使用することができます。あなたは、定期的にシステムクロックが変更されているかどうかを確認するために、これらの値をチェックすることができます。
Java アプリにネイティブ コードを少し追加しても構わない場合は、次を使用します。
QueryPerformanceCounter()
そしてQueryPerformanceFrequency()
Windows の場合。またはPOSIX
clock_gettime()
機能付きCLOCK_MONOTONIC
時計ID。
x86 の使用に注意してください。 TSCレジスタ マルチプロセッサ システムでは推奨されないため、上記の API を使用することをお勧めします。