Static membershard5-8 years

A reporting service declares `private static final SimpleDateFormat FMT = new SimpleDateFormat("yyyy-MM-dd HH:mm")` and reuses it across every request. It passes every test. Under 200 concurrent requests in production, about one row in a thousand carries a date from a *different* request, and occasionally a `NumberFormatException` comes out of `parse`. What's actually happening, and why is `static` — not `SimpleDateFormat` alone — the other half of the bug?

SimpleDateFormat keeps its working state — a Calendar it fills in during format() and reads during parse() — in its own instance fields, and it's documented as not synchronised: it was never designed to be called from two threads at once. static final makes exactly one FMT instance shared by every thread that formats or parses a date, which is precisely the setup that exposes that lack of synchronisation — if FMT were static but the class were thread-safe (like DateTimeFormatter), sharing would be fine, and if FMT were a fresh, non-shared SimpleDateFormat created per call, its own lack of internal synchronisation would never matter because nothing else would ever touch the same instance concurrently. It takes both halves together — a genuinely mutable, non-thread-safe class, made static and therefore shared by every concurrent caller — to produce the bug; either half alone is safe.

The lesson behind it →
More on Static members