They basically have to be thread safe, because they're globally accessible. If you can't control access to a call that isn't thread safe, then you can't call it safely at all if there's any code in your process that you don't control (like, say, third-party libraries, or even first-party libraries).
I think it's reasonable to assume that any documented API must at least be callable.
Indeed it must be so -- at least it would be very strange to have a thread-unsafe static method where the documentation doesn't spell out how to use it safely[1]. Even in that case it would be a weird thing to even have a thread-unsafe static method (except accidentally, of course).
[1] The JDK documentation is pretty good on spelling out such caveats, IME.
The `volatile_var = local_var = X` seems safe - even if you break it into two assignments it only uses the local var afterward, so SecureRandom should be fully initialized in that thread. And though SecureRandom is non-final, it does look safe to use with double-initialization - it self-seeds if not explicitly seeded (it's not in this case), so even double-init shouldn't repeat a value (which is as strong of a statement as SecureRandom allows here - no idea if it makes that claim!).
So I'd think it only matters if `volatile` doesn't guarantee that non-final object fields are fully initialized... and I can't find anything that explicitly states one way or another, so I'm not sure. If it doesn't make that guarantee, then yeah - this could publish a partly-initialized SecureRandom without a generator, which would probably crash. But the contents of https://docs.oracle.com/javase/specs/jls/se8/html/jls-17.htm... imply to me that write-then-read is equivalent to a synchronized block or any other monitor sequence (and in the method they only use the local var, so it doesn't matter for the creator-thread), so I suspect it's fine. Just can't claim any further.
@exabrial: care to elaborate? What's unsafe / have you seen crashes due to uninitialized SecureRandom?
Keep in mind that data races in Java are not undefined behaviour. There are quite a few places where authors of standard library deliberately left out synchronization, for example in String.hashCode.
EDIT: In this case numberGenerator is volatile so it introduces happens-before relations between write and read.
Another great failure is UUID.generateRandomUUID(); One would think that's thread safe... [maybe it's fixed now]