java.lang.System.currentTimeMillis() 替换方法 [英] java.lang.System.currentTimeMillis() replace method

查看:19
本文介绍了java.lang.System.currentTimeMillis() 替换方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

除了重新编译 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 mils(如示例所示),但 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重新声明System(已编辑)

尽管可能,并且您可以创建/更改方法,但有问题的方法被声明为 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# 使用自定义类加载器(根据评论建议进行新测试)


4# Use a custom ClassLoader (new test as suggested on the comments)

虽然使用 -Djava.system.class.loader 替换系统 CL 很简单,但 JVM 实际上加载了使用默认类加载器的自定义类加载器,系统甚至没有通过自定义 CL 推送.

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

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_25jrelib
t.jar]

<小时>

我的选择不多了.
有什么我遗漏的方法吗?

推荐答案

您可以使用 AspectJ 编译器/编织器来编译/编织有问题的用户代码,用您自己的替换对 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆