6 ms·
[author here] Very interesting, do you have a reference on how Java implements this? I just poked at v8 a bit and they seem to have an explicit 'null' object i
by evmar 4y ago
[author here] Very interesting, do you have a reference on how Java implements this?
I just poked at v8 a bit and they seem to have an explicit 'null' object in the VM, though I don't know a lot about so it's possible it works as you suggest.
It seems it might be hard to distinguish language-level null pointers from null pointers within the VM implementation. E.g. v8 runs within a Chrome process that is processing HTML and other things, so if v8 had some special signal handling of null pointers it'd need to be able to distinguish those from HTML processing bugs etc., which I think you might only be able to do by examining the stack? I haven't thought this through but it seems difficult.
- ArchOversight 4y agov8 is JavaScript, which is not a JVM. They are two very different beasts.
- evmar 4y agoThe comment I was replying to made statements about both Java and JavaScript, so my questions were also about both (and whether they were different). I just added a line break to make this clearer.
- ArchOversight 4y agoAh, apologies, it seemed like you were accidentally conflating the two. Thanks for clarifying!
- wahern 4y agoYou can distinguish where a NULL pointer exception occurred by the program counter/instruction pointer. JIT'd code lives in particular memory regions (e.g. those explicitly mmap'd with PROT_EXEC) dynamically managed by the application. From there you may or may not care to examine the stack(s) for more specific details. Alternatively, you could simply only enable NULL pointer handling around specific blocks of code where you're prepared to handle it, and disable it everywhere else (causing the kernel to simply kill the program). I've used this technique to elide explicit array overflow checks in some very performance critical code, dramatically increasing performance (there would have been at least as much overflow checks as semantic operations). None of the critical code used malloc/free or called into any libraries, so on SIGSEGV I would simply longjmp back to a safe place and either grow the data structures and reset the state, or return failed, depending on how large things had grown.[1] The hard part of all of this isn't detecting where or even why a fault occurred--at least presuming you've architected things deliberately--but rather handling asynchronicity. If you have access to mechanisms like userfaultfd it's much easier, but it's doable on most systems. On most Unix systems threading primitives are NOT async-signal safe, but there are plenty of syscalls that are, and at least historically the semantics of Unix signal handlers were carefully defined to permit these sorts of tricks. It's a fine needle that needs to be threaded, but one that can done correctly nonetheless. [1] Note that this wasn't accidental. I wrote the code very carefully this way. I had also worked on at least two projects before where someone tried to get clever and add SIGSEGV handlers to recover from code that was never designed to be recoverable, with predictably horrendous results (e.g. endless, time-wasting bug reports and "fixes").
- gpderetta 4y agoAFAIK, GNAT and GCJ (GCC front ends for Ada And Java respectively, the latter now dead) implement null pointer exceptions by simply raising a language level exception from the SIGSEGV handler (after I assume checking it happened in user code instead of the runtime). Completely non portable of course, but with the help of glibc, the Itanium ABI exception support and non-call-exceptions it can evidently be made to work reliably, at least on Linux.
- evmar 4y agoThank you for explaining! I think the piece I was missing is that the sigint handler is passed the instruction pointer of the faulting instruction.
- layer8 4y agoSee the links to the OpenJDK implementation in this blog post: https://shipilev.net/jvm/anatomy-quarks/25-implicit-null-checks/ https://shipilev.net/jvm/anatomy-quarks/25-implicit-null-che...