java.lang.System.currentTimeMillis()替换方法 [英] java.lang.System.currentTimeMillis() replace method
问题描述
除了重新编译 rt.jar
有什么方法可以用其中一个替换 currentTimeMillis()
调用我自己的?
Aside from recompiling rt.jar
is there any way I can replace the currentTimeMillis()
call with one of my own?
1#正确的方法是使用 Clock
对象和抽象时间。
1# The right way to do it is use a Clock
object and abstract time.
我知道但是我们将运行由无数开发人员开发的代码,这些开发人员尚未实现 Clock
或已经实现了自己的实现。
I know it but we'll be running code developed by an endless number of developers that have not implemented Clock
or have made an implementation of their own.
2#使用像JMockit这样的模拟工具来模拟该类。
即使只适用于已停用的热点 -Xint
,我们也成功使用下面的代码不会持久在外部库上。这意味着你必须在任何地方模拟它,因为代码不受我们的控制,是不可行的。 main()
下的所有代码确实返回0 milis(如示例所示),但 new DateTime()
将返回实际的系统毫秒。
Even though that only works with Hotspot disabled -Xint
and we have success using the code bellow it does not "persist" on external libraries. Meaning that you'd have to Mock it everywhere which, as the code is out of our control, is not feasible. All code under main()
does return 0 milis (as from the example) but a new DateTime()
will return the actual system millis.
@MockClass(realClass = System.class)
public class SystemMock extends MockUp<System> {
// returns 1970-01-01
@Mock public static long currentTimeMillis() { return 0; }
}
3 #重新声明系统
启动时使用 -Xbootclasspath / p
(已编辑)
3# Re-declare System
on start up by using -Xbootclasspath/p
(edited)
尽管可能,虽然您可以创建/更改方法,但有问题的方法被声明为 public static native long currentTimeMillis();
。如果不深入研究Sun的专有和原生代码,你就无法改变它的声明,这将使这成为逆向工程和不稳定的方法。
所有最近的SUN JVM崩溃时出现以下错误:
While possible, and though you can create/alter methods, the one in question is declared as public static native long currentTimeMillis();
. You cannot change it's declaration without digging into Sun's proprietary and native code which would make this an exercise of reverse engineering and hardly a stable approach.
All recent SUN JVM crash with the following error:
EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00000, pid=4668, tid=5736
4#使用自定义ClassLoader (评论中建议的新测试)
4# Use a custom ClassLoader (new test as suggested on the comments)
尽管使用 -Djava.system替换系统CL是微不足道的。 class.loader
JVM实际上加载了使用默认classLoader的自定义classLoader,甚至没有通过自定义CL推送System。
While trivial to replace the system CL using -Djava.system.class.loader
JVM actually loads up the custom classLoader resorting to the default classLoader and System is not even pushed trough the custom 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
使用 java -verbose:class
<从 rt.jar
加载/ p>
We can see that java.lang.System
is loaded from rt.jar
using java -verbose:class
Line 15: [Loaded java.lang.System from C:\jdk1.7.0_25\jre\lib\rt.jar]
我用完了选项。
我缺少一些方法吗?
推荐答案
您可以使用AspectJ编译器/ weaver来编译/编织有问题的用户代码,用您自己的代码替换对java.lang.System.currentTimeMillis()的调用。以下方面只会这样做:
You could use an AspectJ compiler/weaver to compile/weave the problematic user code, replacing the calls to java.lang.System.currentTimeMillis() with your own code. The following aspect will just do that:
public aspect CurrentTimeInMillisMethodCallChanger {
long around():
call(public static native long java.lang.System.currentTimeMillis())
&& within(user.code.base.pckg.*) {
return 0; //provide your own implementation returning a long
}
}
这篇关于java.lang.System.currentTimeMillis()替换方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!