From this Oracle blog:
System.currentTimeMillis()is implemented using the
GetSystemTimeAsFileTime method, which essentially just reads the low
resolution time-of-day value that Windows maintains. Reading this
global variable is naturally very quick – around 6 cycles according to
System.nanoTime()is implemented using the
QueryPerformanceCounter/ QueryPerformanceFrequency API(if available,
else it returns
QueryPerformanceCounter(QPC)is implemented in different ways
depending on the hardware it’s running on. Typically it will use
either the programmable-interval-timer (PIT), or the ACPI power
management timer (PMT), or the CPU-level timestamp-counter (TSC).
Accessing the PIT/PMT requires execution of slow I/O port instructions
and as a result the execution time for QPC is in the order of
microseconds. In contrast reading the TSC is on the order of 100 clock
cycles (to read the TSC from the chip and convert it to a time value
based on the operating frequency).
Perhaps this answer the question. The two methods use different number of clock cycles, thus resulting in slow speed of the later one.
Further in that blog in the conclusion section:
If you are interested in measuring/calculating elapsed time, then always use System.nanoTime(). On most systems it will give a resolution on the order of microseconds. Be aware though, this call can also take microseconds to execute on some platforms.