本文 的 原文 地址
原始的内容,请参考 本文 的 原文 地址
尼恩说在前面
在45岁老架构师 尼恩的读者交流群(50+)中,最近有小伙伴拿到了一线互联网企业如得物、阿里、滴滴、极兔、有赞、希音、百度、网易、美团的面试资格,遇到很多很重要的面试题:
-
什么是 JIT,JIT什么优势?什么是 类的生命周期七个阶段 ?
-
什么是 字节码增强?
最近有小伙伴在面试京东、 阿里、希音等大厂,又遇到了相关的面试题。 小伙伴 没系统梳理, 支支吾吾的说了几句,面试官不满意, 挂了。
针对上面的面试题, 接下来 尼恩结合互联网上的一些实际案例, 大家做一下系统化、体系化的梳理。 使得大家内力猛增,可以充分展示一下大家雄厚的 “技术肌肉”,让面试官爱到 “不能自已、口水直流”,然后实现”offer直提”。
一、字节码文件
1、什么是字节码?
在Java之前, 跨平台 是一个难题。 而 Java 跨平台 的优势: “一次编译,到处运行” 。
构成 Java 生态 跨平台 的基石—— Java 字节码。
无论在何种环境下编译,Java 源代码都能生成标准格式的字节码(.class 文件),由 JVM 解释执行。
为啥要从 字节码入手。
对开发者而言,了解字节码有助于更深入、直观地理解 Java 语言的底层机制。
例如,通过查看字节码,可以清楚地看到
volatile关键字是如何生效的。例如,字节码增强技术在 Spring AOP、ORM 框架及热部署等领域应用广泛,掌握其原理对我们大有裨益。
还有,由于 JVM 规范的标准性,任何能生成符合规范的字节码的程序都可以在 JVM 上运行,因此像 Scala、Groovy、Kotlin 等 JVM 语言也有机会扩展 Java 不具备的特性或实现更友好的语法糖。
从字节码的视角学习这些语言,往往能够更深刻地理解其设计思路。
我们通常使用 javac命令将 .java源文件编译为字节码文件
字节码文件由十六进制数值构成,JVM 按一组两个十六进制值(即一个字节)为单位进行读取。

2、字节码文件的结构
.java文件经 javac编译后生成 .class文件。
编译后得到的 ByteCodeDemo.class文件以十六进制形式打开后,表现形式如下:

JVM 规范要求字节码文件必须按以下十部分顺序构成:

(1)魔数(Magic Number)
每个 .class文件的前 4 个字节是固定的魔数值:0xCAFEBABE。
JVM 通过该标志,快速判断文件是否为可能有效的字节码文件。
有趣的是,魔数“CAFEBABE”由 Java 之父 James Gosling 指定,意为“Cafe Babe”(咖啡宝贝),而 Java 的图标正是一杯咖啡。
(2)版本号
魔数之后的 4 个字节是版本号信息:前 2 个字节表示次版本号(Minor Version),后 2 个字节表示主版本号(Major Version)。
例如 00 00 00 34表示次版本号为 0,主版本号为 52(十六进制 0x34),对应 Java 8。
(3)常量池(Constant Pool)
版本号之后是常量池,它是字节码文件中的资源仓库,主要存放两大类常量:
- 字面量:如
final修饰的常量值、文本字符串等; - 符号引用:包括类/接口的全限定名、字段名称与描述符、方法名称与描述符等。
常量池的结构分为两部分:
- 常量池计数器(constant_pool_count):2 个字节,表示常量池中的常量数量(实际数量为
计数值 - 1); - 常量池数据区:由多个
cp_info表项组成,每个cp_info对应一个常量。

JVM 共定义了 14 种 cp_info类型,其通用结构如下:
cp_info {
u1 tag; // 常量类型标识
u2 info_length; // 后续信息长度(视类型而定)
u1 bytes[info_length]; // 具体数据内容
}

通过 javap -verbose ByteCodeDemo可查看反编译后的常量池内容,更直观易懂:

最低0.47元/天 解锁文章

被折叠的 条评论
为什么被折叠?



