System & Runtime in Java
currentTimeMillis vs nanoTime, getenv, properties, exit codes.
currentTimeMillis() and get a *negative* duration. Did time go backwards? On your server… it actually can.Two clocks
**System.currentTimeMillis() is the wall clock: milliseconds since 1970. It can jump when NTP or a user corrects the clock. System.nanoTime() is a monotonic timer with an arbitrary origin: only the difference between two calls** means anything — never use it as a date.
Timing an operation
long t0 = System.currentTimeMillis();
work();
long ms = System.currentTimeMillis() - t0;If the clock is adjusted mid-way, the result can jump or go negative.
long t0 = System.nanoTime();
work();
long ns = System.nanoTime() - t0;nanoTime never jumps with clock adjustments — the right tool for durations.
Environment vs properties
**System.getenv("HOME") reads an OS environment variable** (null if missing). **System.getProperty("java.version") reads a JVM system property — including ones set with -Dkey=value**. getProperty(key, default) supplies a fallback. Runtime.getRuntime().availableProcessors() tells you the CPU cores.
Missing settings
No -Dapp.color flag was given. What prints?
System.out.println(
System.getProperty("app.color", "blue"));
System.out.println(
System.getenv("SURELY_NOT_SET_123"));null nullblue nullThrows NullPointerException
Show the answer
blue — the default kicks in. null — getenv simply returns null for a variable that doesn't exist.
Exit codes
**System.exit(status) stops the JVM. 0 means success**, any non-zero value means failure — shell scripts and CI pipelines read it to decide what happens next.
Does finally run?
What does this print?
try {
System.out.println("start");
System.exit(0);
} finally {
System.out.println("cleanup");
}start cleanupstartcleanup
Show the answer
Only start. System.exit halts the JVM immediately — the finally block never runs (registered shutdown hooks do).
Config and ops
Containers configure apps through environment variables (DATABASE_URL), tests flip behaviour with -D properties, and CI fails a build when a tool exits non-zero. Timing code with currentTimeMillis produces weird negative latencies in metrics after clock syncs.
Key takeaways
- currentTimeMillis: wall clock, can jump (NTP, user changes)
- nanoTime: for elapsed time only, never as a date
- getenv reads OS variables; getProperty reads JVM -D properties
- System.exit(n) ends the JVM; finally blocks don't run
System.nanoTime() has nanosecond *precision* but not necessarily nanosecond *accuracy* — its Javadoc only promises it's at least as fine as currentTimeMillis.
Practice questions
Why is subtracting two System.currentTimeMillis() values a risky way to time an operation?
- It only has second precision
- The wall clock can be adjusted (e.g. by NTP), so the difference can jump or go negative
- It counts time spent in other processes
- It overflows after 24 days
Check your answer
The wall clock can be adjusted (e.g. by NTP), so the difference can jump or go negative. currentTimeMillis follows the system clock, which can be corrected at any time. nanoTime is monotonic, so it's the right tool for durations.
What does this print?
String mode = System.getProperty("app.mode", "dev");
System.out.println(mode);
System.out.println(System.getenv("NO_SUCH_VAR_42"));- dev null
- null null
- dev
- Throws NullPointerException
Check your answer
dev null. getProperty with a default returns "dev" because no -Dapp.mode was set. getenv simply returns null for a variable that doesn't exist.