Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

java.lang.System.currentTimeMillis() replace method

Tags:

java

time

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<System> { 
        // 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?

like image 835
Frankie Avatar asked Aug 14 '13 18:08

Frankie


People also ask

What does system currentTimeMillis() return in Java?

currentTimeMillis() method returns the current time in milliseconds. The unit of time of the return value is a millisecond, the granularity of the value depends on the underlying operating system and may be larger. For example, many operating systems measure time in units of tens of milliseconds.

How does nanoTime work Java?

nanoTime. Returns the current value of the running Java Virtual Machine's high-resolution time source, in nanoseconds. This method can only be used to measure elapsed time and is not related to any other notion of system or wall-clock time.

Is system currentTimeMillis expensive?

Put another way: there's nothing inherently costly about System. currentTimeMillis(). It's pretty fast, especially compared to the 5-second wait you're attempting to generate.

What does system nanoTime return?

nanoTime() method returns the current value of the most precise available system timer, in nanoseconds. The value returned represents nanoseconds since some fixed but arbitrary time (in the future, so values may be negative) and provides nanosecond precision, but not necessarily nanosecond accuracy.


1 Answers

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
    }
}
like image 138
Nándor Előd Fekete Avatar answered Oct 01 '22 19:10

Nándor Előd Fekete