java.lang.System.currentTimeMillis() replace method

前端 未结 4 1494
-上瘾入骨i
-上瘾入骨i 2020-11-30 11:33

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

相关标签:
4条回答
  • 2020-11-30 11:38

    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)
  • 2020-11-30 11:39

    As discussed in the comments, it is possible that option #3 in the original question has actually worked, successfully replacing the default System class.

    If that is true, then application code which calls currentTimeMillis() will be calling the replacement, as expected.

    Perhaps unexpectedly, core classes like java.util.Timer would also get the replacement!

    If all of the above are true, then the root cause of the crash could be the successful replacement of the System class.

    To test, you could instead replace System with a copy that is functionally identical to the original to see if the crashes disappear.

    Unfortunately, if this answer turns out to be correct, it would seem that we have a new question. :) It might go like this:

    "How do you provide an altered System.currentTimeMillis() to application classes, but leave the default implementation in place for core classes?"

    0 讨论(0)
  • 2020-11-30 11:44

    I'm not 100% sure if I oversee something here, but you can create your own System class like this:

    public static class System {
        static PrintStream err = System.err;
        static InputStream in = System.in;
        static PrintStream out = System.out;
    
        static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length) {
            System.arraycopy(src, srcPos, dest, destPos, length);
        }
    
        // ... and so on with all methods (currently 26) except `currentTimeMillis()`
    
        static long currentTimeMillis() {
            return 4711L; // Your application specific clock value
        }
    }
    

    than import your own System class in every java file. Reorganize imports in Eclipse should do the trick. And than all java files should use your applicatikon specific System class.

    As I said, not a nice solution because you will need to maintain your System class whenever Java changes the original one. Also you must make sure, that always your class is used.

    0 讨论(0)
  • 2020-11-30 11:58

    i've tried using javassist to remove the native currentTimeMills, add a pure java one and load it using bootclasspath/p, but i got the same exception access violation as you did. i believe that's probably because of the native method registerNatives that's called in the static block but it's really too much to disassemble the native library.

    so, instead of changing the System.currentTimeMills, how about changing the user code? if the user code already compiled (you don't have source code), we can use tools like findbugs to identify the use of currentTimeMillis and reject the code (maybe we can even replace the call to currentTimeMills with your own implementation).

    0 讨论(0)
提交回复
热议问题