Live data from Hacker News

macOS 14.4 causes JVM crashes

blogs.oracle.com

41–50 of 160 posts

Re: macOS 14.4 causes JVM crashes

#41

Earlier quoted context omitted.

All system idiosyncrasies are APIs in the long run ;)

The change of a SIGSEGV to a SIGKILL, seriously?

And, why not? macOS is Apple’s IP and they have all rights to do with it as they want. Buy the way, Chrome/Node.js JavaScript engine uses JIT compilation too. Are they affected?

Re: macOS 14.4 causes JVM crashes

#42
“The Java Virtual Machine […] leverages the protected memory access signal mechanism both for correctness (e.g., to handle the truncation of memory mapped files) and for performance.”

Where by “protected memory access signal mechanism”, they mean SIGBUS/SIGSEGV, i.e., a segfault.

This is probably because the JVM is doing “zero cost access checks”, which is where you do the moral equivalent of:

    try {
      writeToFile()
    } catch(err) {
      if (err == SYSTEM_CRASH_IMMINENT) {
        changeFilePermissions()
        retry
      }
    }
…because it’s faster than checking file permissions before every write. (It’s a common pattern in systems programming, so it’s not quite as crazy as it sounds.)

I guess my opinion on this is that if you write your program to intentionally trigger and ignore kill(10) / kill(11) from the host OS, for the sake of a speed boost, you can’t really get too mad when the host OS gets fed up and starts sending kill(9) instead.

I also wonder what happens in the (extremely rare) case where the signal the JVM is trapping is a real segfault, and not an operating system signal.

Re: macOS 14.4 causes JVM crashes

#43
post #42

“The Java Virtual Machine […] leverages the protected memory access signal mechanism both for correctness (e.g., to handle the truncation of memory mapped files) and for performance.” Where by “protected memory access signal mechanism”, they mean SIGBUS/SIGSEGV, i.e., a segfault. This is probably because the JVM is doing “zero cost access checks”, which is where you do the moral equivalent of: try { writeToFile() } c…

This isn't about files, this is about plain pages of RAM[0]. It is a basic CPU operation to trap on unmapped pages, and OSes rightfully expose this useful feature (in addition to using it themselves), allowing processes to do many things, from lazily-computed memory regions to removing significant amounts of overhead doing a thing the CPU will inevitably do itself anyway.

I believe the "the truncation of memory mapped files" section is for when the Java process memory-maps a file (as Java provides memory-mapping operations in its standard library, and probably also uses them itself), and afterwards some other unrelated process truncates the file, resulting in the OS quietly making (parts of) the mappings inaccessible. Here the process couldn't even check the permissions before reading (never mind how utterly hilariously inefficient that would be, defeating the purpose of memory-mapping) as the mappings could change between the check and subsequent read anyway.

[0]: https://bugs.java.com/bugdatabase/view_bug?bug_id=8327860, "I've managed to narrow this down to this small reproducer:" section

Re: macOS 14.4 causes JVM crashes

#44
post #43
post #42

“The Java Virtual Machine […] leverages the protected memory access signal mechanism both for correctness (e.g., to handle the truncation of memory mapped files) and for performance.” Where by “protected memory access signal mechanism”, they mean SIGBUS/SIGSEGV, i.e., a segfault. This is probably because the JVM is doing “zero cost access checks”, which is where you do the moral equivalent of: try { writeToFile() } c…

This isn't about files, this is about plain pages of RAM[0]. It is a basic CPU operation to trap on unmapped pages, and OSes rightfully expose this useful feature (in addition to using it themselves), allowing processes to do many things, from lazily-computed memory regions to removing significant amounts of overhead doing a thing the CPU will inevitably do itself anyway. I believe the "the truncation of memory mappe…

You are of course completely correct.

However, I still stand by my pseudocode - I claim that it will give a fairly accurate impression of the basic concept of zero-cost access checks to a reader who isn’t familiar with low-level systems programming. (That said, I have updated my comment to make it clear it’s more of a metaphor than a literal description.)

Re: macOS 14.4 causes JVM crashes

#45
post #43
post #42

“The Java Virtual Machine […] leverages the protected memory access signal mechanism both for correctness (e.g., to handle the truncation of memory mapped files) and for performance.” Where by “protected memory access signal mechanism”, they mean SIGBUS/SIGSEGV, i.e., a segfault. This is probably because the JVM is doing “zero cost access checks”, which is where you do the moral equivalent of: try { writeToFile() } c…

This isn't about files, this is about plain pages of RAM[0]. It is a basic CPU operation to trap on unmapped pages, and OSes rightfully expose this useful feature (in addition to using it themselves), allowing processes to do many things, from lazily-computed memory regions to removing significant amounts of overhead doing a thing the CPU will inevitably do itself anyway. I believe the "the truncation of memory mappe…

And it's worth noting that while man mmap on macOS doesn't indicate what happens when the protections are violated (that is, if you try to read, write, or execute in violation of the set protections) the related function mprotect has this to say in macOS 14.3 (what I have available):

> When a program violates the protections of a page, it gets a SIGBUS or SIGSEGV signal.

(The Linux man pages for mmap and mprotect indicates SIGSEGV would be signaled.)

So the past use and assumption (SIGSEGV or SIGBUS) are consistent with the expectations of mmap and mprotect given the documentation provided.

Re: macOS 14.4 causes JVM crashes

#46

Earlier quoted context omitted.

The change of a SIGSEGV to a SIGKILL, seriously?

And, why not? macOS is Apple’s IP and they have all rights to do with it as they want. Buy the way, Chrome/Node.js JavaScript engine uses JIT compilation too. Are they affected?

This breaks POSIX compatibility, which is basically saying FU to how a lot of developers expect to interact with an operating system for decades now.

Re: macOS 14.4 causes JVM crashes

#47
> macOS on Apple silicon processors (M1, M2, and M3) includes a feature which controls how and when dynamically generated code can be either produced (written) or executed on a per-thread basis. […] With macOS 14.4, when a thread is operating in the write mode, if a memory access to a protected memory region is attempted, macOS will send the signal SIGKILL instead.

This isn’t just any old thread triggering SIGKILL, it’s the JIT thread privileged to write to executable pages that is performing illegal memory accesses. That’s typically a sign of a bug, and allowing a thread with write access to executable pages to continue executing after that is a security risk.

But I know of other language runtimes that take advantage of installing signal handlers for SIGBUS/SIGSEGV to detect when they overflow a page so they can allocate more memory, etc. This saves from having to do an explicit overflow check on every allocation. Those threads aren’t given privilege to write to executable memory, so they’re not seeing this issue…

So this sounds like a narrow design problem the JVM is facing with their JIT thread. This blog doesn’t explain why their JIT thread needs to make illegal memory accesses instead of an explicit check.

Re: macOS 14.4 causes JVM crashes

#48
post #3

> "As a normal part of the just-in-time compile and execute cycle, processes running on macOS may access memory in protected memory regions." I'm just a lowly JavaScript/TypeScript/PHP programmer, but what is the Very Good Reason that Java trying to access other processes' memory?

Accessing such areas is sometimes done deliberately since programmers could rely on the OS telling them what just happened using signals instead of nuking the process wholesale. Doing it without signals is usually slow and/or clunky (null-pointer checks, read/write permissions, existence of pages), or straight out impossible.

Accessing other processes' memory is not the concern since virtual memory provides each process the illusion of having the entire address space for itself.

Re: macOS 14.4 causes JVM crashes

#50
post #43
post #42

“The Java Virtual Machine […] leverages the protected memory access signal mechanism both for correctness (e.g., to handle the truncation of memory mapped files) and for performance.” Where by “protected memory access signal mechanism”, they mean SIGBUS/SIGSEGV, i.e., a segfault. This is probably because the JVM is doing “zero cost access checks”, which is where you do the moral equivalent of: try { writeToFile() } c…

This isn't about files, this is about plain pages of RAM[0]. It is a basic CPU operation to trap on unmapped pages, and OSes rightfully expose this useful feature (in addition to using it themselves), allowing processes to do many things, from lazily-computed memory regions to removing significant amounts of overhead doing a thing the CPU will inevitably do itself anyway. I believe the "the truncation of memory mappe…

A talk at FOSDEM this year [0] describes how the OpenJDK JVM relies on triggering SIGSEGVs in order to efficiently implement thread-local safepoint checks - I wonder if that would also be affected?

[0]: https://mostlynerdless.de/blog/2023/07/31/the-inner-workings...

Post reply on HN