Come posso misurare il tempo in Java non suscettibile di cambiamenti di clock di sistema?

StackOverflow https://stackoverflow.com/questions/1937619

  •  20-09-2019
  •  | 
  •  

Domanda

Vorrei misurare il tempo trascorso in un Java. Tuttavia le differenze di System.currentTimeMillis() e (credo) System.nanoTime() può essere modificato da cambiamenti esterni ad esempio qualcuno (o sistema) alterando l'orologio di sistema.

Utilizzando le chiamate di rete non è un'opzione come sia possibile sono necessari rendimenti molto frequenti e veloci.

C'è una soluzione comune per questo?

Modifica

Siamo spiacenti, avrei elaborato sul motivo. Non è per fermare utenti malintenzionati -. È cose come client di logout avviato per essere eventi client di inattività e di routine

È stato utile?

Soluzione

Questo in realtà non rispondere alla tua domanda, ma bug # 6.458.294 implica che, ove possibile, l'implementazione di Sun di nanoTime () utilizzerà i meccanismi che sono veramente monotona (CLOCK_MONOTONIC su Linux, QueryPerformanceFrequency / QueryPerformanceCounter su Windows). Solo se questi non sono disponibili intende ripiegare ad un meccanismo che è suscettibile di modifiche di clock di sistema.

Se si ha il controllo (o almeno la conoscenza) l'hardware è in esecuzione, e possibile garantire che tali meccanismi dell'orologio saranno disponibili, si potrebbe essere fortunati e nanoTime () farà bene.

È possibile, come anche di leggere questo post blog, che discute la HotSpot- caso on-Windows in modo più dettagliato.

Altri suggerimenti

Non credo che ci sia un modo per fare questo.

Non v'è certamente modo per fare ciò che non può essere sovvertito. Fondamentalmente, si è in balia del sistema operativo e la JVM su ciò che è segnalato per l'applicazione Java come l'ora corrente. Uno o entrambi questi potrebbe essere corretto in modo che il codice Java finisce per ottenere un valore di timestamp fasullo. Si potrebbe provare a difendere contro questo, ma poi tutto l'hacker deve fare è patchare la vostra applicazione per disabilitare il controllo di licenza del tutto.

Per la cronaca, questa "vulnerabilità" si applica anche se non si sta utilizzando Java.

Se si sta cercando di impedire alla gente di sovvertire un sistema di licenze impostando l'orologio indietro, è necessario memorizzare il tempo più alto che hai visto fino ad ora in una sorta di stoccaggio criptato e sicuro, e quindi disattivare il programma se sia il tempo passa meno il più alto che hai visto (con qualche concessione per la regolazione dell'orologio NTP e modifiche dell'ora legale, naturalmente), o se in qualche modo manomettere o eliminare l'archivio protetto.

Non so se nanoTime () è destinata a cambiare se cambia il clock di sistema, ma suppongo che sia possibile. Anche nanoTime () potrebbe non essere preciso.

Se avete veramente bisogno di premunirsi contro le modifiche di clock, si potrebbe monitorare l'orologio in un thread. Il sonno per 100 ms o 1000 ms, quindi chiamare currentTimeMillis (). Se Advanced Clock più di 1000 + x o è andato a ritroso quindi probabile che l'orologio ha cambiato (o il filo ottenuto appeso su di una cosa, che è possibile).

In caso di una disgiunzione, si potrebbe effettivamente fare la chiamata di rete per controllare. Naturalmente, è possibile che il tempo della rete potrebbe cambiare a causa l'inserimento di salto secondi . Una volta ho letto un commento Slashdot da parte di alcuni scienziati che coordinava i dati astronomici da molte fonti diverse. Un salto secondo è stato aggiunto durante il suo esperimento, ed è fondamentalmente rovinato perché alcuni siti inseriti e altri no.

Un'altra possibilità potrebbe essere quella di utilizzare un basso livello di API native per ottenere alcuni altri timer di sistema. Come il sistema o la disponibilità della rete per calibrare l'API. Windows ha la funzione GetTickCount (), che restituisce il numero di millisecondi dal momento di avvio. Su sistemi UNIX è possibile utilizzare il comando uptime per ottenere una stima approssimativa. È possibile controllare periodicamente questi valori per vedere se l'orologio di sistema è cambiato.

Se non ti dispiace l'aggiunta di un po 'di codice nativo per la vostra applicazione Java, utilizzare:

  • QueryPerformanceCounter() e QueryPerformanceFrequency() su Windows; o

  • funzione POSIX clock_gettime() con ID orologio CLOCK_MONOTONIC.

Si noti che l'uso del x86 TSC registrare è scoraggiato su sistemi multiprocessore, in modo da utilizzare al meglio le API di cui sopra.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top