除了重新编译之外,rt.jar
还有什么方法可以用currentTimeMillis()
我自己的方法替换调用?
1#正确的做法是使用Clock
对象和抽象时间。
我知道,但我们将运行由无数尚未实现Clock
或已经自己实现的开发人员开发的代码。
2# 使用 JMockit 之类的模拟工具来模拟该类。
尽管这只适用于禁用热点-Xint
并且我们使用下面的代码成功,但它不会“持久”在外部库上。这意味着您必须在任何地方模拟它,因为代码超出了我们的控制范围,这是不可行的。下面的所有代码main()
都返回 0 milis(如示例所示),但 anew DateTime()
将返回实际的系统 milis。
@MockClass(realClass = System.class)
public class SystemMock extends MockUp<System> {
// returns 1970-01-01
@Mock public static long currentTimeMillis() { return 0; }
}
System
3#在启动时重新声明-Xbootclasspath/p
使用(已编辑)
尽管可能,并且您可以创建/更改方法,但有问题的方法被声明为public static native long currentTimeMillis();
. 如果不深入研究 Sun 的专有和本机代码,就无法更改它的声明,这将使其成为逆向工程的练习,并且几乎不是一种稳定的方法。所有最近的 SUN JVM 崩溃并出现以下错误:
EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00000, pid=4668, tid=5736
4# 使用自定义类加载器(评论中建议的新测试)
虽然使用-Djava.system.class.loader
JVM 替换系统 CL 很简单,但实际上使用默认的 classLoader 加载了自定义 classLoader,并且系统甚至没有通过自定义 CL 推送。
public class SimpleClassLoader extends ClassLoader {
public SimpleClassLoader(ClassLoader classLoader) {
super(classLoader);
}
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
return super.loadClass(name);
}
}
我们可以看到它是从使用java.lang.System
加载的rt.jar
java -verbose:class
Line 15: [Loaded java.lang.System from C:\jdk1.7.0_25\jre\lib\rt.jar]
我的选择已经不多了。
有什么我缺少的方法吗?