Como posso medir o tempo em Java não suscetível às alterações do relógio do sistema?

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

  •  20-09-2019
  •  | 
  •  

Pergunta

Eu gostaria de medir o tempo decorrido em um java. No entanto, diferenças em System.currentTimeMillis() E (eu acredito) System.nanoTime() pode ser alterado por alterações externas, por exemplo, alguém (ou o sistema) que altera o relógio do sistema.

O uso de chamadas de rede não é uma opção, pois é possível que sejam necessários retornos muito frequentes e rápidos.

Existe uma solução comum para isso?

EDITAR

Desculpe, eu deveria ter elaborado sobre o motivo. Não é para interromper usuários maliciosos - são coisas como o cliente iniciado o Logout por serem ociosos e rotineiros de eventos do cliente.

Foi útil?

Solução

Isso realmente não responde à sua pergunta, mas Bug #6458294 implica que, sempre que possível, a implementação do Nanotime () da Sun usará mecanismos que são verdadeiramente monotônicos (Clock_monotonic no Linux, QueryPerformanceFrequency/QueryPerformAncounter no Windows). Somente se estes não estiverem disponíveis, ele voltará a um mecanismo que é suscetível às alterações do relógio do sistema.

Se você tiver controle (ou pelo menos conhecimento) do hardware em que está em execução e pode garantir que esses mecanismos de relógio estejam disponíveis, você pode estar com sorte e o nanotime () se sairá bem.

Você também pode gostar de ler esta postagem do blog, que discute o caso do ponto de acesso na janela com mais detalhes.

Outras dicas

Eu não acho que exista uma maneira de fazer isso.

Certamente não há como fazer isso que não possa ser subvertido. Fundamentalmente, você está à mercê do sistema operacional e da JVM sobre o que é relatado ao aplicativo Java como o horário atual. Um ou ambos podem ser corrigidos para que o código Java acabe obtendo um valor de timestamp falso. Você pode tentar se defender contra isso, mas tudo o que o hacker precisa fazer é consertar seu aplicativo para desativar completamente a verificação da licença.

Para o registro, essa "vulnerabilidade" aplica se você está usando ou não Java.

Se você está tentando impedir as pessoas de subverter um esquema de licença, colocando o relógio de volta, precisar Vai menos do que o mais alto que você viu (com algum subsídio para ajustes do relógio NTP e alterações no horário de verão), ou se de alguma forma adulterar ou excluir a loja segura.

Não sei se o nanotime () provavelmente mudará se o relógio do sistema mudar, mas suponho que seja possível. Também o nanotime () pode não ser preciso.

Se você realmente precisa se proteger contra as mudanças de relógio, poderá monitorar o relógio em um tópico. Durma por 100ms ou 1000ms e ligue para CurrentTimemillis (). Se o relógio avançou mais, então 1000 + x ou foi para trás, provavelmente o relógio mudou (ou o thread foi pendurado em algo, o que é possível).

No caso de uma disjunção, você pode realmente fazer a rede ligar para verificar. Obviamente, é possível que o tempo de rede mude devido à inserção de salto segundos. Certa vez, li um comentário de Slashdot de alguns cientistas que estavam coordenando dados astronômicos de muitas fontes diferentes. Um salto em segundo lugar foi adicionado durante seu experimento, e basicamente o arruinou porque alguns sites o inseriram e outros não.

Outra possibilidade pode ser usar uma API nativa de baixo nível para obter outros temporizadores do sistema. Como o sistema de atividade do sistema ou da rede para calibrar a API. O Windows possui a função getTickCount () que retorna o número de milissegundos desde a inicialização. Nos sistemas UNIX, você pode usar o comando de tempo de atividade para obter uma estimativa aproximada. Você pode verificar periodicamente esses valores para verificar se o relógio do sistema mudou.

Se você não se importa de adicionar um pouco de código nativo ao seu aplicativo Java, use:

  • QueryPerformanceCounter() e QueryPerformanceFrequency() no Windows; ou

  • Posix clock_gettime() função com CLOCK_MONOTONIC ID do relógio.

Observe que o uso do x86 Registro TSC é desencorajado nos sistemas multiprocessadores, então você usa melhor as APIs acima.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top