java.lang.System.currentTimeMillis()替换方法

Fra*_*kie 15 java time

除了重新编译之外,rt.jar有什么方法可以用currentTimeMillis()我自己的一个替换呼叫吗?

1#正确的方法是使用Clock对象和抽象时间.

我知道但我们将运行由无数开发人员开发的代码,这些开发人员尚未实现Clock或已经实现了自己的实现.


2#使用像JMockit这样的模拟工具来模拟该类.

即使这只适用于禁用Hotspot -Xint并且我们使用下面的代码成功,但它不会"持久"在外部库上.这意味着你必须在任何地方模拟它,因为代码不受我们的控制,是不可行的.所有代码main()都返回0 milis(从示例中),但a new DateTime()将返回实际系统millis.

    @MockClass(realClass = System.class)
    public class SystemMock extends MockUp<System> { 
        // returns 1970-01-01   
        @Mock public static long currentTimeMillis() { return 0; }
    }
Run Code Online (Sandbox Code Playgroud)

3#System使用-Xbootclasspath/p(编辑) 重新声明启动

尽管可能,虽然您可以创建/更改方法,但有问题的方法被声明为public static native long currentTimeMillis();.如果不深入研究Sun的专有和原生代码,你就无法改变它的声明,这将使这成为逆向工程和不稳定的方法.所有最近的SUN JVM都崩溃,出现以下错误:

    EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00000, pid=4668, tid=5736  
Run Code Online (Sandbox Code Playgroud)

4#使用自定义ClassLoader(评论中建议的新测试)

虽然使用-Djava.system.class.loaderJVM 替换系统CL的微不足道实际上加载了使用默认classLoader的自定义classLoader,并且甚至没有通过自定义CL推送System.

    public class SimpleClassLoader extends ClassLoader {
        public SimpleClassLoader(ClassLoader classLoader) {
            super(classLoader);
        }

        @Override 
        public Class<?> loadClass(String name) throws ClassNotFoundException {
            return super.loadClass(name);
        }   
    }
Run Code Online (Sandbox Code Playgroud)

我们可以看到java.lang.Systemrt.jar使用中加载java -verbose:class

Line 15: [Loaded java.lang.System from C:\jdk1.7.0_25\jre\lib\rt.jar]
Run Code Online (Sandbox Code Playgroud)

我的选择已经用完了.
有什么方法我不见了?

Nán*_*ete 10

您可以使用AspectJ编译器/编织器来编译/编织有问题的用户代码,用您自己的代码替换对java.lang.System.currentTimeMillis()的调用.以下方面将执行此操作:

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
    }
}
Run Code Online (Sandbox Code Playgroud)