These are exceptions which are preallocated on the start of JVM.
Preallocated exceptions should be implicit: they are thrown by JVM, not by throw new ...
when unexpected condition occurs: dereferencing null pointer, accessing array with negative index etc.
When method starts to throw (implicitly) one of these exceptions too frequently, JVM will notice that and replace allocation of exception on every throw with throwing already preallocated exception without stacktrace.
This mechanism is implementation dependent, so if we're talking about hotspot you can find the list of these exceptions in graphKit.cpp:
NullPointerException
ArithmeticException
ArrayIndexOutOfBoundsException
ArrayStoreException
ClassCastException
The rationale is pretty simple: the most expensive part of throwing an exception is not an actual throwing and stack unwinding, but creating stacktrace in exception (it's a relatively slow call to the VM and happens in exception constructor via Throwable#fillInStackTrace
). To find concrete numbers and relative cost you can read awesome article by hotspot performance engineer about exceptional performance.
Some people use exceptions for regular control flow (please don't do that) or for performance sake (which is usually incorrect, for example see this kinda popular connection pool framework), so hotspot makes this [probably bad] code a little bit faster via throwing already created exception without stacktrace (so the most expensive part of throwing is eliminated).
Downside of this approach is that now you have stacktraceless exceptions. It's not a big deal: if these implicit exceptions are thrown that frequently, you probably don't use their stacktraces. But if this assumption is incorrect you will have exceptions without traces in your logs. To prevent this you can use -XX:-OmitStackTraceInFastThrow