为什么是0xCAFEBABE?
摘要
本文内容基于1996年的一次新闻组讨论,探讨了Java类文件魔数0xCAFEBABE的起源和原因。
<p><a href="https://lobste.rs/s/2ym3yg/why_0xcafebabe">评论</a></p>
查看缓存全文
缓存时间: 2026/09/22 02:32
# 为何是 CAFEBABE?
来源:https://www.artima.com/insidejvm/whyCAFEBABE.html
为何是 CAFEBABE?——来自 comp.lang.java 新闻组的讨论帖
1996年5月,当我正在撰写第二篇 JavaWorld 文章《类文件的生活方式》时,我对 Java 类文件的魔数 `0xCAFEBABE` 产生了好奇。每个 Java 类文件的前四个字节被指定为 `0xCAFEBABE`,这个魔数可以帮助工具快速区分可能的类文件与非类文件。我好奇这个值背后是否隐藏着深刻含义,便向 `comp.lang.java` 新闻组提出了以下问题。
每个 Java 类文件的前四个字节都包含魔数值 0xCAFEBABE。我很好奇。有人知道这个值是怎么选定的吗?有没有不了解的人想大胆猜测一下?
提前感谢。
bv
---
本页下方展示了所有引发我这个问题的回复。
我以前似乎听说过原因,但答案可能早已从我的电子邮件存档中删除了。我也很想知道为什么。为什么呢?
matt
---
Bill Venners 写道:
> 每个 Java 类文件的前四个字节都包含魔数值 0xCAFEBABE。我很好奇。有人知道这个值是怎么选定的吗?有没有不了解的人想大胆猜测一下?
嗯,他们大概必须选择一个特定的魔数来标识类文件,而只用 A-F 这几个字母能组成的 Java 或咖啡相关词汇实在有限。:-)
\-Rolf
---
Matthew Travis 写道:
> 我以前似乎听说过原因,但答案可能早已从我的电子邮件存档中删除了。我也很想知道为什么。为什么呢?matt
嗯,文件总得以某个魔数(或字符串)开头,以便轻松识别为有效的类文件而非其他东西。
至于为什么魔数是 3405691582(0xCAFEBABE),我的猜测是:(a)32位魔数更容易处理且更可能唯一,(b)Java 团队希望选一个与 Java-咖啡比喻相关的东西,由于十六进制中没有字母 'J' 或 'V',于是选了个包含 CAFE 的词。我猜他们觉得“CAFE BABE”比什么“A FAB CAFE”或“CAFE FACE”更性感,而且肯定不喜欢“CAFE A FAD”(或者更糟,“A BAD CAFE”)的含义。
:-)
\-\- Alastair
(顺便说一句,当然他们远非第一个在魔数中用十六进制数字拼出有意义单词的。二十多年前,Burroughs B6700 就把其“未初始化”的 48 位字内存初始化为 0xBADBADBADBAD。)
---
Alastair Mayer 写道:
> \[此处略去引用内容\] 我猜他们觉得“CAFE BABE”比什么“A FAB CAFE”或“CAFE FACE”更性感,而且肯定不喜欢“CAFE A FAD”(或者更糟,“A BAD CAFE”)的含义。:-)
不知为何我之前没注意到,他们*本可以*使用数字 12648430,如果你选择将十六进制的零视为字母 'O' 的话。这样你就得到 0xC0FFEE,或者用 0x00C0FFEE 来表示完整的 32 位。OO COFFEE?当然是面向对象……:-)
\-\- Alastair
---
Alastair Mayer 写道:
> 嗯,文件总得以某个魔数(或字符串)开头,以便轻松识别为有效的类文件而非其他东西。至于为什么魔数是 3405691582(0xCAFEBABE),我的猜测是:(a)32位魔数更容易处理且更可能唯一,(b)Java 团队希望选一个与 Java-咖啡比喻相关的东西,由于十六进制中没有字母 'J' 或 'V',于是选了个包含 CAFE 的词。我猜他们觉得“CAFE BABE”比什么“A FAB CAFE”或“CAFE FACE”更性感,而且肯定不喜欢“CAFE A FAD”(或者更糟,“A BAD CAFE”)的含义。:-) \-\- Alastair (顺便说一句,当然他们远非第一个在魔数中用十六进制数字拼出有意义单词的。二十多年前,Burroughs B6700 就把其“未初始化”的 48 位字内存初始化为 0xBADBADBADBAD。)
当我还是个孩子时,曾帮助一位数值分析员调试程序。S/360 的核心转储(还记得十六进制矩阵吗!)最终揪出了元凶:一个严重越界的浮点值。
其前三位数字是 0xBAD。
我费了好大劲才让那家伙相信这只是纯粹的巧合!
Dave
---
David N. Smith 写道:
> 当我还是个孩子时,曾帮助一位数值分析员调试程序。S/360 的核心转储(还记得十六进制矩阵吗!)最终揪出了元凶:一个严重越界的浮点值。其前三位数字是 0xBAD。我费了好大劲才让那家伙相信这只是纯粹的巧合!
一个标准(即明确在《新黑客词典》中提及的)“伪造值”,常被放在需要易识别的伪造值的地方,是 0xDEADBEEF。
在没有保护内存的 Macintosh 上,流行做法是在地址 0 放置某个魔数,这样解引用空指针或句柄会立即崩溃。很久以前,我一个朋友用 'NIL!' 的 ASCII 值达到这个目的,但后来经过一些真正的思考,认为在 Mac 上什么是更好的值,最终选择了 0x50FFC001。这个值能完美导致 Mac 崩溃(至少有三个原因,留给读者作为练习),但不幸的是它不是一个酷炫且易读的值。 \-\-
---
我最初是在 NeXTSTEP 中看到 0xCAFEBABE 作为魔数。NX 使用“胖二进制文件”,本质上是把不同平台的二进制文件捆绑在一个可执行文件中。如果你在 NX Intel 上运行,它会运行 Intel 二进制;如果在 HP 上运行,它会运行 HP 二进制。0xCAFEBABE 是用于区分 Intel 或 Motorola 二进制文件的魔数(具体是哪个记不清了)。
看来 Sun 沿用了这个传统……
---
Vivian Man Cheng 写道:
> 我最初是在 NeXTSTEP 中看到 0xCAFEBABE 作为魔数。
奇怪但属实……0xfeedface 用于摩托罗拉,0xcafebabe 用于英特尔。那 Sun 和 HP 呢?
你觉得这会被 NeXT 版权所有或注册商标吗?:-)
David
---
由于“babe”一词基本与“chick”同义,我怀疑这里面有什么**深奥**的含义。当我听到“CafeBabe”时,我想到的是典型的咖啡女郎:鼻环,至少一个纹身,染成黑色的头发,憎恨世界、政府和父母,而且在一种病态的意义上相当有吸引力。
但这是我个人的理解。也可能是为了向在他们最喜欢的咖啡店服务 Sun Java 团队的女服务员致敬。或者,也许这是他们能用 A-F 字母拼出的少数词之一,而 CAFEBEEF 或 DEADCAFE 听起来远不如 CAFEBABE 顺耳。
谁知道呢。你可以写信问他们。
---
> (顺便说一句,当然他们远非第一个在魔数中用十六进制数字拼出有意义单词的。二十多年前,Burroughs B6700 就把其“未初始化”的 48 位字内存初始化为 0xBADBADBADBAD。)
也别忘了旧的 IBM 机器曾用 0xDEADBEEF 达到同样目的。在某些圈子里(至少在还记得此事的程序员中),使用未初始化内存仍被称为“死牛肉错误”。
---
Lee Crocker 写道:
> > (顺便说一句,当然他们远非第一个在魔数中用十六进制数字拼出有意义单词的。二十多年前,Burroughs B6700 就把其“未初始化”的 48 位字内存初始化为 0xBADBADBADBAD。)也别忘了旧的 IBM 机器曾用 0xDEADBEEF 达到同样目的。在某些圈子里(至少在还记得此事的程序员中),使用未初始化内存仍被称为“死牛肉错误”。
RS6000 上的 AIX 仍使用 0xdeadbeef 表示未初始化存储。
Vasili N. Galchin
---
这个回复才是真正问题的答案,由 Patrick Naughton 提供,他是最终开发出 Java 的团队的原始成员之一。我在 JavaWorld 文章中引用了 Patrick 的话。
Bill Venners 写道:
> 每个 Java 类文件的前四个字节都包含魔数值 0xCAFEBABE。我很好奇。有人知道这个值是怎么选定的吗?有没有不了解的人想大胆猜测一下?
说来也巧,.class 文件的魔数早在“Java”这个名字被用来指代这门语言之前就已经选定了。我们当时在寻找一些有趣、独特且容易记住的东西。0xcafebabe 比第二名候选 0xdeadbabe 更好。:-)
至于它隐晦地提到了 Peet's Coffee 的可爱咖啡师,那只是巧合,并预示了后来的 Java 之名。
---
Patrick Naughton 写道:
> 说来也巧,.class 文件的魔数早在“Java”这个名字被用来指代这门语言之前就已经选定了。我们当时在寻找一些有趣、独特且容易记住的东西。0xcafebabe 比第二名候选 0xdeadbabe 更好。:-)
0xdeadbabe 用于所有 IRIX arena 文件的开头!所以幸好你们没用它!;-)
---
Simon Bennett 写道:
> 0xdeadbabe 用于所有 IRIX arena 文件的开头!所以幸好你们没用它!;-)
还有一个调试用的 Solaris 内核会把 0xCAFEFEED 放入所有 kmemfree() 块中。 \-\-b
相似文章
字节码虚拟机在意外场景中的应用 (2024)
本文探讨了字节码虚拟机的出人意料的应用,特别是Linux内核中的eBPF以及编译后二进制文件中用于调试信息的DWARF表达式。
破解'nameOf'
本文解释了如何通过StackWalker和ClassFile API在运行时内省字节码,实现C#的nameof表达式的Java等价物,从而能够检索参数名称以用于异常消息。
关于滥用Windows窗口类额外字节的兼容性说明
Raymond Chen 讨论了一个历史性的 Windows 兼容性问题,其中一些 16 位程序滥用窗口类额外字节来存储私有数据,以及微软如何在保持向后兼容性的同时,对 32 位和 64 位程序堵住了这个漏洞。
这段代码是CRAP (2011)
作者强调Crap4J是一个有价值的工具,用于在Java项目中识别危险代码且没有误报,赞扬其与Jenkins的集成,并指出它与Java 7不兼容。
10 REM"_(C2SLFF4
一篇文章调查了1980年BASIC游戏《The Wizard's Castle》开头的神秘REM语句,发现它是编码的机器码,通过USR和POKE调用为随机数生成器提供种子。