java 更改 currenttime,java.lang.System.currentTimeMillis()替换方法

Aside from recompiling rt.jar is there any way I can replace the currentTimeMillis() call with one of my own?

1# The right way to do it is use a Clock object and abstract time.

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# Use a mock tool like JMockit to mock that class.

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 {

// returns 1970-01-01

@Mock public static long currentTimeMillis() { return 0; }

}

3# Re-declare System on start up by using -Xbootclasspath/p (edited)

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# Use a custom ClassLoader (new test as suggested on the comments)

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);

}

}

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]

I'm running out of options.

Is there some approach I'm missing?

解决方案

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

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值