我想用Java 来测量经过的时间。然而差异在于 System.currentTimeMillis() 和(我相信) System.nanoTime() 可以通过外部变化来改变,例如某人(或系统)改变系统时钟。

使用网络调用不是一种选择,因为可能需要非常频繁且快速的返回。

有一个通用的解决方案吗?

编辑

抱歉,我应该详细说明原因。它不是为了阻止恶意用户 - 它是诸如客户端因空闲而发起的注销和例行客户端事件之类的事情。

有帮助吗?

解决方案

这并不能真正回答你的问题,但是 错误#6458294 意味着在可能的情况下,Sun 的 nanoTime() 实现将使用真正单调的机制(Linux 上的 CLOCK_MONOTONIC,Windows 上的 QueryPerformanceFrequency/QueryPerformanceCounter)。只有当这些不可用时,它才会回退到易受系统时钟更改影响的机制。

如果您可以控制(或至少了解)正在运行的硬件,并且可以确保这些时钟机制可用,那么您可能很幸运,nanoTime() 会做得很好。

您可能还喜欢阅读 这篇博文, ,其中更详细地讨论了 Windows 上的 HotSpot 案例。

其他提示

我认为没有办法做到这一点。

当然没有办法做到这一点是不可颠覆的。从根本上来说,向 Java 应用程序报告的当前时间取决于操作系统和 JVM。可以对其中一个或两个进行修补,以便 Java 代码最终获得虚假的时间戳值。您可以尝试防御这种情况,但黑客所需要做的就是修补您的应用程序以完全禁用许可证检查。

根据记录,无论您是否使用 Java,此“漏洞”都适用。

如果您试图通过设置时钟来阻止人们破坏许可方案,则需要将迄今为止看到的最高时间存储在某种加密且安全的存储中,然后在以下情况下禁用该程序:低于您所见过的最高值(当然,需要考虑 NTP 时钟调整和 DST 更改),或者它们是否以某种方式篡改或删除安全存储。

我不知道如果系统时钟发生变化,nanoTime() 是否会发生变化,但我认为这是可能的。nanoTime() 也可能不准确。

如果您确实需要防止时钟更改,您可以在线程中监视时钟。休眠100ms或1000ms,然后调用currentTimeMillis()。如果时钟前进超过 1000 + x 或已经倒退,那么时钟可能会改变(或者线程被某些东西挂起,这是可能的)。

如果发生分离,您实际上可以进行网络调用来检查。当然,网络时间可能会因插入而改变 闰秒. 。我曾经读过一些科学家在 Slashdot 上发表的评论,他们正在协调来自许多不同来源的天文数据。在他的实验中添加了闰秒,这基本上毁了它,因为有些网站插入了它,而另一些网站没有插入。

另一种可能性可能是使用低级本机 API 来获取其他一些系统计时器。例如系统或网络正常运行时间来校准 API。Windows 具有 getTickCount() 函数,该函数返回自启动以来的毫秒数。在 UNIX 系统上,您可以使用 uptime 命令来粗略估计。您可以定期检查这些值以查看系统时钟是否已更改。

如果您不介意向 Java 应用程序添加一些本机代码,请使用:

  • QueryPerformanceCounter()QueryPerformanceFrequency() 在 Windows 上;或者

  • POSIX clock_gettime() 功能与 CLOCK_MONOTONIC 时钟 ID。

注意,使用x86 TSC 寄存器 在多处理器系统上不鼓励使用,因此您最好使用上述 API。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top