我们现有的产品对时间非常敏感。例如,统计数据以5分钟,1小时,24小时为基础发布。这意味着在现实世界条件下测试非常缓慢(因此我们实际上不测试1小时和24小时的统计数据)。
我想要的是加快JVM时钟......我知道我可以创建一个虚拟时间类,就像我见过别人那样。但代码库是巨大的,所以这将是很多改造工作+第三方库仍将使用正常的日期类/ System.getCurrentTimeInMillis ...
我真正想要的是一种覆盖Java时间行为的方法(在ruby世界中修补猴子)。我猜应该可以使用字节码操作来做到这一点。但我不知道从哪里开始....我找不到任何这样做的库或任何通过字节码操作解决了这个问题的人。
问题1:是否可以覆盖日期行为? 问题2:如何做到这一点?也许是覆盖另一个核心java类的一个例子?
感谢您的任何想法
答案 0 :(得分:1)
修改系统时间(如果正在使用,则禁用ntpd),Java时间将相应反映。
答案 1 :(得分:0)
主要有两种方法。修改Date类本身,或修改对它的所有引用。
Date类是标准库的一部分,因此它具有特权状态。我能想到修改它的唯一方法是实际修改系统jar。您可以将修改后的jar放在正常位置,也可以让JVM查看其他位置。请注意,这不是Oracle正式支持的,仅供个人使用。
另一种方法是修改所有类以引用类的模拟版本。即使在大型代码库中,您也可以使用简单的脚本执行此操作。如果您只关心普通引用,则可以静态或动态地(在加载类时)执行此操作。
如果您担心通过反射访问日期,那么动态执行此操作是唯一的选择。通常,您将使用带有ASM的自定义类加载器来执行字节码重写。为了捕获反射,您必须模拟所有反射类并替换对这些反射类的引用。这非常棘手,尤其是当您考虑使用反射来访问反射以访问Date时,但这是可能的。
另外,请注意字节码重写不会让您搞乱系统类,因为它们使用硬编码的系统类加载器。因此,如果另一个系统类引用Date,它将使用未修改的版本。
我相信Java代理也可以用来进行字节码重写而无需自定义类加载器,但我没有这方面的经验。
答案 2 :(得分:0)
Java 8包含由java.time.* package定义的新JSR 310,受Joda-Time启发(但重新设计)。
这些新类取代了臭名昭着的java.util.Date,java.util.Calendar和java.text.SimpleDateFormat类。
新类中有抽象类Clock。
设计师完全满足您的需求,是系统时钟的可插拔替代品,可创建虚假的“模拟”日期时间值,以方便测试。 Clock类可以由您(或其他人)为您想要的任何非自然行为进行扩展。将该更改时钟的实例传递给其他java.time。*类。那些其他类将使用您的Clock作为日期时间数据的来源,而不是计算机/ JVM的真实时钟。
看起来Joda-Time可能有类似的东西。阅读关于“MillisProvider”的讨论。显然是指DateTimeUtils.MillisProvider
。