7 ms·
> Computation overhead > NullPointerExceptions are thrown frequently. "Frequently" is obviously a relative term, but are NullPointerExceptions really common en
by evancox100 8y ago
> Computation overhead
> NullPointerExceptions are thrown frequently.
"Frequently" is obviously a relative term, but are NullPointerExceptions really common enough to be a performance concern? It's good that they are taking performance overhead into consideration of course, I'm just surprised it's even an issue.
- idbentley 8y agoI've worked with developers who use this pattern frequently for code execution. try{ .. business logic .. } catch (NullPointerException e) { .. else .. } Rather than a null guard. That's what occurred to me.
- AaronFriel 8y agoThis is arguably more robust, because "foo.bar.quux.doTheThing()" is three potential null pointer exceptions in a row, and the code to do consecutive testing is ugly and verbose.
- arethuza 8y agoHaving a try..catch round such code would seem sensible but to rely on that over normal checking seems spectacularly horrible.
- DC-3 8y agoThis is why Rust's '?' operator for error propagation is quite nice.
- hamandcheese 8y agoIt’s a code smell if you are calling a method chain that long at all.
- laythea 8y agoCannot agree with you more. I personally hate chained expressions. Awful for debugging too.
- wtetzner 8y agoIt's only awful for debugging because the tools are awful.
- laythea 8y agoThe tools for Java are greate (try C++ if you disagree). It's the code that is the problem here.
- wtetzner 8y agoThe tools for Java are much better than those for C++. However, claiming the code is the problem is silly. I'm not going to introduce a bunch of local variables just to appease a debugger. If splitting on separate lines makes code more readable, then sure, do that. But often it just makes the code longer and harder to follow.
- xxs 8y agoJava debugging tools are beyond excellent for debugging such code (not that it should be written that way)
- laythea 8y agoI still have to select the sub-expression whose value I wish to inspect. This involves precisely aiming the cursor at text, which is a lot of mental burden (x millions). A task I thank the developer who creates a variable to hold such a reference, for it creates a much better experience.
- xxs 8y agoI guess there are extremely few people in the topic who understand how NPE works internally. There is no null check in the generated assembly code, when a null dereference occurs - it's an effective kernel trap (as 0 is not mapped to the process). The latter uses the code execution pointer to understand what has been attempted to execute and throws the exception. This may or may not involve stack crawl (which is very expensive) depending on JIT ability to prove if the stack would be unused. Nulls should be avoided, all fields should be initialized, etc. Nulls are great for =very= high performance code as null checks are virtually free.
- arethuza 8y agoI remember seeing sample code from WebLogic that returned values from methods using exceptions. Mind you this was in documentation rather than in production code - but hardly a good example to follow!
- int_19h 8y agoI've seen a horrifying adaptation of this pattern in C++, where a piece of code was using catch(...) to detect dereferencing an invalid (not even necessarily null, just an object that's gone!) pointer.
- lultimouomo 8y agoThat's strange, as dereferencing an invalid pointer in C++ will not cause anything to be thrown. In the best case you immediately get a segfault; if you're unlucky the code just goes on reading random data from memory and crashing some time after that.
- marshray 8y agohttps://docs.microsoft.com/en-us/cpp/build/reference/eh-exception-handling-model?view=vs-2017 https://docs.microsoft.com/en-us/cpp/build/reference/eh-exce...
- int_19h 8y agoThe standard is U.B., so throwing is a valid response. On Win32, a segfault / access violation - and similar low-level errors, like division by zero - is represented as something called "structured exception". These have a standard OS ABI such that they can be caught, and stack can be unwound, across different languages. In MSVC, normally, they are not treated as C++ exceptions for the purpose of catching them, although it will still participate in stack unwinding (if something else below is catching them). However, there is an opt-in compiler switch that does make them look like C++ exceptions in a sense that catch(...) will catch them. It's not something you'll see in most code written in the past 15 years or so, for obvious reasons.
- bhauer 8y agoAgreed. I feel the key word in dealing with exceptions is "exception," meaning something uncommon, which is a foreign concept in some codebases, where exceptions are used as routine flow-control. Throwing an exception in Java is a non-trivial expense since the constructor for Throwable populates a stack-trace structure for the current thread. If you're using exceptions as a routine flow-control mechanism, you're incurring that cost too frequently. Like you said, sure, tune the performance of this new feature because it's part of the standard library and should be reasonably well-tuned. But if people are frequently throwing NPEs, they should consider alternatives such as simple null checks.
- xkr 8y ago> exceptions are used as routine flow-control Unfortunately, this approach is encouraged by some popular frameworks, for example a ResponseStatusException in Spring 5
- bunderbunder 8y agoAnd even the JDK itself. java.lang.InterruptedException comes to mind.
- xxs 8y agoInterruptedException is sort of necessary evil, esp. when it comes to concurrent data structures. InterruptedException are rare (very) and used mostly to signal termination attempt. LockSupport.parkNanos doesn't throw the exception (unlike sleep, and sleep should never be used in code) but the interruption signal/flag has to be respected somehow. Most of the time is rethrow in library code or bailing out with IllegalStateException in 'userspace'
- bunderbunder 8y agoI think that it could be done better. .NET's CancellationTokens are a step in the right direction, though sadly just one step. You can check if cancellation is requested, but there's also a method for asking the token to throw a CancellationException if cancellation has been requested, and this is how all the abstractions around threading do it. But it's reasonably easy to imagine ways to produce an API that only uses tokens like that instead of using exceptions to signal cancellation/termination requests. And I suspect, given how many bits have been spilled trying to explain to people just how they're supposed to deal with InterruptedExceptions, that the resulting system would have better ergonomics. Long story short, I don't know that it's that InterruptedException was a necessary evil so much as that people were still fairly new to this whole exceptions thing when Java came out, and it's really hard to get subtle things like this right on the first try.
- liveoneggs 8y agoI've seen one dev manager (out of many) who failed code that threw NPEs. Every other one let them slide unabated. They are super common.
- paulmd 8y agoA lot of those NullExceptions (and a lot of boilerplate code) could be linted away if Java gave compiler-level semantics to @NotNull annotations. Letting null values propagate through your program is frequently a code smell, you want to constrain it at the boundaries of your program logic if possible. Unfortunately, Java does not have a semantic way to do this, just documentation and discipline.
- mrighele 8y agoChecker framework [1] can be used to add compile time checks on such annotations. Unfortunately I found it non trivial to setup (that was some time ago though, I'll have to check again). I noticed also that a recent version of Wildfly application server can do those check at runtime, but I haven't investigated it enough to see if it is configurable and the performance impact of the checks [1] https://checkerframework.org https://checkerframework.org
- joe_fishfish 8y agoKotlin is amazing for this.
- pron 8y agoAs Java supports pluggable type systems, this can be achieved by one: https://checkerframework.org/manual/#nullness-checker https://checkerframework.org/manual/#nullness-checker
- needusername 8y agoWell there is an JVM optimization (OmitStackTraceInFastThrow, which is on by default) which optimizes "built in" exceptions that are thrown frequently enough to be cached and have to stack trace. So somebody at one point thought that was a worthwhile optimization and allocated engineering resources to it. https://www.oracle.com/technetwork/java/javase/relnotes-139183.html https://www.oracle.com/technetwork/java/javase/relnotes-1391...