Java 、Idea、Android Studio 用户请暂缓升级到 macOS 14.4

337 天前
 codehz
https://blogs.oracle.com/java/post/java-on-macos-14-4
省流:果子改了受保护页面的默认处理方式,之前是发 sigsegv 现在直接 sigkill ,而 java 从很早的版本(已知 8 )开始就在滥用这个特性来将 null 检测改为捕获 sigsegv 信号,包括用户主动写的 if == null 也会在 jit 的帮助下被转换,这在新版本 mac 里会直接触发错误。
建议有 java 需求或依赖基于 java 的 ide 的 mac 用户暂缓升级
15125 次点击
所在节点    Apple
109 条回复
iseki
337 天前
@felixlong apple 这个只是一个很 corner case 的场景,到不好说会不会改回去,也许就让大家吃了。
CFM880
337 天前
@ShadowPower windows Android Studio 也有 bug ,一个陈年老 bug https://issuetracker.google.com/issues/167701947 ,特别恶心,我基本新加一个包,再新建包下面新建一个类文件,必出这个 bug
wpei
337 天前
@meloyang05
@ychost
我一直以为是我的 usb hub 坏了,没想到是苹果的问题...
seanxx
336 天前
mac 已经不是原本的 mac 了,充斥着烂臭咖喱味,能用就不会升级
ShadowPower
336 天前
@CFM880 好吧,我已经 3 年没有做 Android/iOS 相关的工作了……
2kCS5c0b0ITXE5k2
336 天前
@Rorysky java8 就开始用了. 苹果为什么突然修改? 而且问题是 rc 版都没问题. 正式版就修改 那测试版是来用干什么的?
felixlong
336 天前
@codehz 应该不是你说的那个检测 NullPointerException 的优化导致的。那个行为影响太大了,而且那是 Posix 的标准行为,Apple 应该没有改变。
好像与 Mac 在 M 系列处理器引入的新的 pthread_jit_write_protect_np 有关系。Apple 确实只说了用 MAP_JIT mmap 出来的 region 要么只能 write ,要么只能 executable ,从来没提过 read 会发生什么事情,以前是在 write protect on/off 都发送 SIG_BUS, 14.4 改成了 write protect on 的时候发 SIG_BUS ,write protect off 的时候发 SIG_KILL,真是迷惑行为。不知道为啥 JDK 生成的 jit code 需要 read 自己?
codehz
336 天前
@felixlong 上面我发了复现代码了,可能确实不是 0 页面的访问,但 mmap 只是去申请了一个权限为 0 的页面,然后去访问,正常情况只会触发 sigbus ,但 14.4 结合 write protection 后会直接 sigkill
这里不涉及任何真正的 jit 只是单纯的开一个页面当做 guard page
ShadowPower
336 天前
@codehz 这是不是意味着 macOS 已经破坏了 POSIX 兼容
Jirajine
336 天前
这是依赖 UB 的特性,也不是关键特性,当然可以 break 。为使用 UB 特性、未定义接口的程序做兼容才是万恶之源。
这里的问题是依赖这个 UB 的程序( jvm )被广泛部署,而这项改动在推送前没有充分测试。
fredweili
336 天前
升级过了,还没遇到问题
codehz
336 天前
@Jirajine 首先这不是 ub ,是标准允许的做法,其次虽然可能不是 null 的那个问题,但另一个 guard page 更是这个 api 的原本目的,不然为何提供 mmap PROT NONE 这个选项
parthenon2007
336 天前
@seanxx #64 说得对,苹果总是犯一些低级错误。我甚至怀疑他们内部程序员为了刷 KPI ,喜欢把之前的功能反复拿出来重构。苹果通过破坏兼容性得以抛弃的历史包袱并没有能提升他们的代码质量。
codehz
336 天前
@felixlong
测试了一下,访问 null 也真的会导致 sigkill (去掉 pthread_jit_write_protect_np(0)这句就 SIGSEGV)
#include <pthread.h>

int main() {
pthread_jit_write_protect_np(0);
return *((int *)NULL);
}
fantaxi
336 天前
Only apple can do !
felixlong
336 天前
@codehz 哈哈,估计 Apple 认为在 write_protect disable 模式下这个线程就只应该运行生成 JIT 代码的代码,不能干其它的事。也许 Apple 认为生成 JIT 代码的代码本身不会有这些骚操作。
daveh
336 天前
@codehz OpenJDK 已经改了,JRE 自己屎山代码的问题,为之前 Solaris 做的一个优化,还需要 Solaris 专有 API 配合才行,然后 Solaris 死了十几年了,这个却作为垃圾代码一直残留下来。
直到在最新 macOS 下帮发现了问题,OP 自己去看下 OpenJDK 的修改记录,不要在这瞎猜。

JB 已经有测试 JBR 发布,可以自己临时规避一下。

Apple 可改可不改,如果是安全原因不一定会改,但老版 JRE 使用也挺多,问题报多了可能也会改回去。
codehz
336 天前
@daveh 这个问题就是苹果的错误,就算 JRE 触发是一个意外,也不能改变它就是苹果的错误,因为这个行为( pthread_jit_write_protect_np 0 的时候 SIGSEGV 和 SIGBUS 变为 SIGKILL )没有任何文档提及,也没在更新日志里包含,乃至专门介绍安全性的更新内容( https://support.apple.com/zh-cn/HT214084 )的文档也没有说有这个变更
OpenJRE 自己去 workaround 这个问题,和苹果意外搞出的错误没有任何关系
codehz
336 天前
@daveh 此外 pthread_jit_write_protect_np 是只有 macOS 给 apple sillicon 提供的功能,solaris 根本就没这个 api ,何来的十几年的垃圾代码
daveh
336 天前
@codehz #79 都说了你去看 OpenJDK 的修改,删了一拖屎山。不要在这瞎猜,如果你真对这个问题感兴趣的话。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1024389

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX