如何测量Java中不受系统时钟变化影响的时间?
我想测量Java中的经过时间。 但是, System.currentTimeMillis()
和(我相信) System.nanoTime()
差异可以通过外部更改来更改,例如某人(或系统)更改系统时钟。
使用网络呼叫不是一种选择,因为它可能非常频繁且需要快速返回。
对此有一个共同的解决方案吗?
编辑
对不起,我应该详细说明原因。 它不是为了阻止恶意用户 – 它是客户端发起的空闲注销和日常客户端事件。
这并没有真正回答你的问题,但是错误#6458294意味着在可能的情况下,Sun的nanoTime()实现将使用真正单调的机制(Linux上的CLOCK_MONOTONIC,Windows上的QueryPerformanceFrequency / QueryPerformanceCounter)。 只有当这些不可用时,它才会回归到易受系统时钟变化影响的机制。
如果您对正在运行的硬件有控制(或至少知识),并且可以确保这些时钟机制可用,那么您可能很幸运,nanoTime()也可以。
您可能还想阅读此博文 ,其中更详细地讨论了HotSpot-on-Windows案例。
我认为没有办法做到这一点。
当然没有办法做到这一点,不能被颠覆。 从根本上说,您将受操作系统和JVM的支配,因为当前时间报告给Java应用程序的内容。 可以修补其中任何一个或两个,以便Java代码最终获得伪造的时间戳值。 您可以尝试防范此问题,但黑客需要做的就是修补您的应用以完全禁用许可证检查。
无论您是否使用Java,此“漏洞”都适用于此记录。
如果您试图通过设置时钟来阻止人们破坏许可证方案,您需要存储到目前为止在某种加密和安全存储中看到的最高时间,然后在任何时候禁用该程序不到你所看到的最高值(当然有一些NTP时钟调整和DST更改的余量),或者如果它们以某种方式篡改或删除安全存储。
我不知道如果系统时钟发生变化,nanoTime()是否可能会发生变化,但我认为这是可能的。 nanoTime()也可能不准确。
如果你真的需要防止时钟变化,你可以监视线程中的时钟。 睡眠100毫秒或1000毫秒,然后调用currentTimeMillis()。 如果时钟提前超过1000 + x或已经倒退,则可能时钟发生了变化(或者线程挂起了某些东西,这是可能的)。
如果发生分离,您实际上可以进行网络呼叫检查。 当然,由于插入闰秒 ,网络时间可能会发生变化。 我曾经读过一些科学家的Slashdot评论,他们正在协调来自许多不同来源的天文数据。 在他的实验中添加了闰秒,它基本上毁了它,因为有些网站插入了它而其他网站没有。
另一种可能性是使用低级本机API来获取其他系统计时器。 如系统或网络正常运行时间来校准API。 Windows具有getTickCount()函数,该函数返回自引导以来的毫秒数。 在unix系统上,您可以使用uptime命令进行粗略估计。 您可以定期检查这些值以查看系统时钟是否已更改。
如果您不介意在Java应用程序中添加一些本机代码,请使用:
-
Windows上的
QueryPerformanceCounter()
和QueryPerformanceFrequency()
; 要么 -
带有
CLOCK_MONOTONIC
时钟ID的POSIXclock_gettime()
函数。
请注意,不建议在多处理器系统上使用x86 TSC寄存器 ,因此最好使用上述API。
- 在java中通过ref传递枚举
- 从另一个进程的输出流中读取
- Weblogic 12c和Java EE 7function
- 如何使用cascade =“all,delete-orphan”制作hibernate集合的副本
- Spring MqttPahoMessageDrivenChannelAdapter丢失连接:连接丢失; 重试
- Eclipse / Java – 导入java是否有害。(命名空间)。*?
- Java:如何设置htmlunit
- Java 9 + maven + junit:测试代码是否需要自己的module-info.java以及放置它的位置?
- spring – 从类的静态字段中的属性文件中读取属性值