forked from itwanger/toBeBetterJavaer
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbytecode.html
More file actions
178 lines (173 loc) · 57.5 KB
/
Copy pathbytecode.html
File metadata and controls
178 lines (173 loc) · 57.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
<!DOCTYPE html>
<html lang="zh-CN" data-theme="light">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<meta name="generator" content="VuePress 2.0.0-beta.46" />
<meta name="theme" content="VuePress Theme Hope" />
<meta property="og:url" content="https://tobebetterjavaer.com/jvm/bytecode.html"><meta property="og:site_name" content="Java 程序员进阶之路"><meta property="og:title" content="从javap的角度轻松看懂字节码"><meta property="og:type" content="article"><meta property="og:updated_time" content="2022-05-13T23:14:28.000Z"><meta property="og:locale" content="zh-CN"><meta property="article:tag" content="Java"><meta property="article:modified_time" content="2022-05-13T23:14:28.000Z"><script>
var _hmt = _hmt || [];
(function() {
var hm = document.createElement("script");
hm.src = "https://hm.baidu.com/hm.js?5230ac143650bf5eb3c14f3fb9b1d3ec";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(hm, s);
})();
</script><link rel="stylesheet" href="//at.alicdn.com/t/font_3180624_7cy10l7jqqh.css"><link rel="icon" href="/favicon.ico"><link rel="icon" href="/assets/icon/chrome-mask-512.png" type="image/png" sizes="512x512"><link rel="icon" href="/assets/icon/chrome-mask-192.png" type="image/png" sizes="192x192"><link rel="icon" href="/assets/icon/chrome-512.png" type="image/png" sizes="512x512"><link rel="icon" href="/assets/icon/chrome-192.png" type="image/png" sizes="192x192"><link rel="manifest" href="/manifest.webmanifest" crossorigin="use-credentials"><meta name="theme-color" content="#46bd87"><link rel="apple-touch-icon" href="/assets/icon/apple-icon-152.png"><meta name="apple-mobile-web-app-capable" content="yes"><meta name="apple-mobile-web-app-status-bar-style" content="black"><meta name="msapplication-TileImage" content="/assets/icon/ms-icon-144.png"><meta name="msapplication-TileColor" content="#ffffff"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover"><title>从javap的角度轻松看懂字节码 | Java 程序员进阶之路</title><meta name="description" content="一份通俗易懂、风趣幽默的Java学习指南,内容涵盖Java基础、Java并发编程、Java虚拟机、Java企业级开发、Java面试等核心知识点。学Java,就认准Java程序员进阶之路">
<style>
:root {
--bg-color: #fff;
}
html[data-theme="dark"] {
--bg-color: #1d2025;
}
html,
body {
background-color: var(--bg-color);
}
</style>
<script>
const userMode = localStorage.getItem("vuepress-theme-hope-scheme");
const systemDarkMode =
window.matchMedia &&
window.matchMedia("(prefers-color-scheme: dark)").matches;
if (userMode === "dark" || (userMode !== "light" && systemDarkMode)) {
document.querySelector("html").setAttribute("data-theme", "dark");
}
</script>
<link rel="stylesheet" href="/assets/style.c081fa20.css">
<link rel="modulepreload" href="/assets/app.41bad062.js"><link rel="modulepreload" href="/assets/bytecode.html.581d7a60.js"><link rel="modulepreload" href="/assets/plugin-vue_export-helper.21dcd24c.js"><link rel="modulepreload" href="/assets/bytecode.html.ba8f00b6.js">
</head>
<body>
<div id="app"><!--[--><!--[--><!--[--><span tabindex="-1"></span><a href="#main-content" class="skip-link sr-only">Skip to content</a><!--]--><div class="theme-container has-toc"><!--[--><!--[--><header class="navbar"><div class="navbar-left"><button class="toggle-sidebar-button" title="Toggle Sidebar"><span class="icon"></span></button><!----><a href="/" class="brand"><img class="logo" src="http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/logo-02.png" alt="Java 程序员进阶之路"><!----><span class="site-name hide-in-pad">Java 程序员进阶之路</span></a><!----></div><div class="navbar-center"><!----><nav class="nav-links"><div class="nav-item hide-in-mobile"><a href="/blog.html" class="nav-link" aria-label="博客"><span class="icon iconfont icon-gaishu" style=""></span>博客<!----></a></div><div class="nav-item hide-in-mobile"><a href="/home.html" class="nav-link" aria-label="进阶之路"><span class="icon iconfont icon-lujing" style=""></span>进阶之路<!----></a></div><div class="nav-item hide-in-mobile"><a href="/zhishixingqiu/" class="nav-link" aria-label="知识星球"><span class="icon iconfont icon-Artboard" style=""></span>知识星球<!----></a></div><div class="nav-item hide-in-mobile"><a href="/xuexiluxian/" class="nav-link" aria-label="学习路线"><span class="icon iconfont icon-luxian" style=""></span>学习路线<!----></a></div><div class="nav-item hide-in-mobile"><div class="dropdown-wrapper"><button class="dropdown-title" type="button" aria-label="珍藏资源"><span class="title"><span class="icon iconfont icon-youzhi" style=""></span>珍藏资源</span><span class="arrow"></span><ul class="nav-dropdown"><li class="dropdown-item"><a href="/download/java.html" class="nav-link" aria-label="电子书下载"><span class="icon iconfont icon-java" style=""></span>电子书下载<!----></a></li><li class="dropdown-item"><a href="/sidebar/sanfene/nixi.html" class="nav-link" aria-label="面渣逆袭"><span class="icon iconfont icon-zhunbei" style=""></span>面渣逆袭<!----></a></li><li class="dropdown-item"><a href="/download/nicearticle.html" class="nav-link" aria-label="优质文章"><span class="icon iconfont icon-youzhi" style=""></span>优质文章<!----></a></li><li class="dropdown-item"><a href="/download/history.html" class="nav-link" aria-label="网络日志"><span class="icon iconfont icon-rizhi" style=""></span>网络日志<!----></a></li><li class="dropdown-item"><a href="/nice-article/itmind/" class="nav-link" aria-label="破解合集"><span class="icon iconfont icon-zhongyaotishi" style=""></span>破解合集<!----></a></li></ul></button></div></div><div class="nav-item hide-in-mobile"><a href="https://space.bilibili.com/513340480" rel="noopener noreferrer" target="_blank" aria-label="B站视频" class="nav-link"><span class="icon iconfont icon-bzhan" style=""></span>B站视频<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span><!----></a></div></nav><!----></div><div class="navbar-right"><!----><div class="nav-item"><!----></div><div class="nav-item"><a class="repo-link" href="https://github.com/itwanger/toBeBetterJavaer" target="_blank" rel="noopener noreferrer"><svg xmlns="http://www.w3.org/2000/svg" class="icon github-icon" viewbox="0 0 1024 1024" fill="currentColor" aria-label="github icon" style="width:1.25rem;height:1.25rem;vertical-align:middle;"><path d="M511.957 21.333C241.024 21.333 21.333 240.981 21.333 512c0 216.832 140.544 400.725 335.574 465.664 24.49 4.395 32.256-10.07 32.256-23.083 0-11.69.256-44.245 0-85.205-136.448 29.61-164.736-64.64-164.736-64.64-22.315-56.704-54.4-71.765-54.4-71.765-44.587-30.464 3.285-29.824 3.285-29.824 49.195 3.413 75.179 50.517 75.179 50.517 43.776 75.008 114.816 53.333 142.762 40.79 4.523-31.66 17.152-53.377 31.19-65.537-108.971-12.458-223.488-54.485-223.488-242.602 0-53.547 19.114-97.323 50.517-131.67-5.035-12.33-21.93-62.293 4.779-129.834 0 0 41.258-13.184 134.912 50.346a469.803 469.803 0 0 1 122.88-16.554c41.642.213 83.626 5.632 122.88 16.554 93.653-63.488 134.784-50.346 134.784-50.346 26.752 67.541 9.898 117.504 4.864 129.834 31.402 34.347 50.474 78.123 50.474 131.67 0 188.586-114.73 230.016-224.042 242.09 17.578 15.232 33.578 44.672 33.578 90.454v135.85c0 13.142 7.936 27.606 32.854 22.87C862.25 912.597 1002.667 728.747 1002.667 512c0-271.019-219.648-490.667-490.71-490.667z"></path></svg></a></div><div class="nav-item hide-in-mobile"><button id="appearance-switch"><svg xmlns="http://www.w3.org/2000/svg" class="icon auto-icon" viewbox="0 0 1024 1024" fill="currentColor" aria-label="auto icon" style="display:block;"><path d="M512 992C246.92 992 32 777.08 32 512S246.92 32 512 32s480 214.92 480 480-214.92 480-480 480zm0-840c-198.78 0-360 161.22-360 360 0 198.84 161.22 360 360 360s360-161.16 360-360c0-198.78-161.22-360-360-360zm0 660V212c165.72 0 300 134.34 300 300 0 165.72-134.28 300-300 300z"></path></svg><svg xmlns="http://www.w3.org/2000/svg" class="icon dark-icon" viewbox="0 0 1024 1024" fill="currentColor" aria-label="dark icon" style="display:none;"><path d="M524.8 938.667h-4.267a439.893 439.893 0 0 1-313.173-134.4 446.293 446.293 0 0 1-11.093-597.334A432.213 432.213 0 0 1 366.933 90.027a42.667 42.667 0 0 1 45.227 9.386 42.667 42.667 0 0 1 10.24 42.667 358.4 358.4 0 0 0 82.773 375.893 361.387 361.387 0 0 0 376.747 82.774 42.667 42.667 0 0 1 54.187 55.04 433.493 433.493 0 0 1-99.84 154.88 438.613 438.613 0 0 1-311.467 128z"></path></svg><svg xmlns="http://www.w3.org/2000/svg" class="icon light-icon" viewbox="0 0 1024 1024" fill="currentColor" aria-label="light icon" style="display:none;"><path d="M952 552h-80a40 40 0 0 1 0-80h80a40 40 0 0 1 0 80zM801.88 280.08a41 41 0 0 1-57.96-57.96l57.96-58a41.04 41.04 0 0 1 58 58l-58 57.96zM512 752a240 240 0 1 1 0-480 240 240 0 0 1 0 480zm0-560a40 40 0 0 1-40-40V72a40 40 0 0 1 80 0v80a40 40 0 0 1-40 40zm-289.88 88.08-58-57.96a41.04 41.04 0 0 1 58-58l57.96 58a41 41 0 0 1-57.96 57.96zM192 512a40 40 0 0 1-40 40H72a40 40 0 0 1 0-80h80a40 40 0 0 1 40 40zm30.12 231.92a41 41 0 0 1 57.96 57.96l-57.96 58a41.04 41.04 0 0 1-58-58l58-57.96zM512 832a40 40 0 0 1 40 40v80a40 40 0 0 1-80 0v-80a40 40 0 0 1 40-40zm289.88-88.08 58 57.96a41.04 41.04 0 0 1-58 58l-57.96-58a41 41 0 0 1 57.96-57.96z"></path></svg></button></div><div id="docsearch-container"></div><!----><button class="toggle-navbar-button" aria-label="Toggle Navbar" aria-expanded="false" aria-controls="nav-screen"><span class="button-container"><span class="button-top"></span><span class="button-middle"></span><span class="button-bottom"></span></span></button></div></header><!----><!--]--><!----><div class="toggle-sidebar-wrapper"><span class="arrow left"></span></div><aside class="sidebar"><!--[--><!----><!--]--><ul class="sidebar-links"><li><!--[--><a href="/home.html" class="nav-link sidebar-link sidebar-page" aria-label="一、前言"><!---->一、前言<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable active"><!----><span class="title">二、Java核心</span><span class="arrow down"></span></button><ul class="sidebar-links"><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">2.1 Java概述</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">2.2 Java语法基础</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">2.3 数组&字符串</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">2.4 面向对象编程</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">2.5 集合框架(容器)</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">2.6 IO</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">2.7 异常处理</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">2.8 常用工具类</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">2.9 Java新特性</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">2.10 Java重要知识点</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">2.11 并发编程</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable active"><!----><span class="title">2.12 JVM</span><span class="arrow down"></span></button><ul class="sidebar-links"><li><!--[--><a href="/jvm/what-is-jvm.html" class="nav-link sidebar-link sidebar-page" aria-label="JVM到底是什么?"><!---->JVM到底是什么?<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/jvm/how-run-java-code.html" class="nav-link sidebar-link sidebar-page" aria-label="JVM到底是如何运行Java代码的"><!---->JVM到底是如何运行Java代码的<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/jvm/class-load.html" class="nav-link sidebar-link sidebar-page" aria-label="类加载机制"><!---->类加载机制<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/jvm/class-file-jiegou.html" class="nav-link sidebar-link sidebar-page" aria-label="详解Java的类文件结构"><!---->详解Java的类文件结构<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a aria-current="page" href="/jvm/bytecode.html" class="router-link-active router-link-exact-active nav-link active sidebar-link sidebar-page active" aria-label="从javap的角度轻松看懂字节码"><!---->从javap的角度轻松看懂字节码<!----></a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a aria-current="page" href="/jvm/bytecode.html#_01、字节码" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="01、字节码"><!---->01、字节码<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/jvm/bytecode.html#_02、反编译字节码文件" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="02、反编译字节码文件"><!---->02、反编译字节码文件<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/jvm/bytecode.html#_03、常量池" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="03、常量池"><!---->03、常量池<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/jvm/bytecode.html#_04、字段表集合" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="04、字段表集合"><!---->04、字段表集合<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/jvm/bytecode.html#_05、方法表集合" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="05、方法表集合"><!---->05、方法表集合<!----></a><ul class="sidebar-sub-headers"></ul></li></ul><!--]--></li><li><!--[--><a href="/jvm/zijiema-zhiling.html" class="nav-link sidebar-link sidebar-page" aria-label="字节码指令详解"><!---->字节码指令详解<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/jvm/how-jvm-run-zijiema-zhiling.html" class="nav-link sidebar-link sidebar-page" aria-label="虚拟机是如何执行字节码指令的"><!---->虚拟机是如何执行字节码指令的<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/jvm/hsdb.html" class="nav-link sidebar-link sidebar-page" aria-label="HSDB(Hotspot Debugger)"><!---->HSDB(Hotspot Debugger)<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/jvm/asm.html" class="nav-link sidebar-link sidebar-page" aria-label="史上最通俗易懂的ASM教程"><!---->史上最通俗易懂的ASM教程<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/jvm/compile-jdk.html" class="nav-link sidebar-link sidebar-page" aria-label="自己编译JDK"><!---->自己编译JDK<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/jvm/neicun-jiegou.html" class="nav-link sidebar-link sidebar-page" aria-label="深入理解JVM的内存结构"><!---->深入理解JVM的内存结构<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/jvm/whereis-the-object.html" class="nav-link sidebar-link sidebar-page" aria-label="Java 创建的对象到底放在哪"><!---->Java 创建的对象到底放在哪<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/jvm/gc.html" class="nav-link sidebar-link sidebar-page" aria-label="从头到尾说一次Java垃圾回收"><!---->从头到尾说一次Java垃圾回收<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/jvm/tujie-gc.html" class="nav-link sidebar-link sidebar-page" aria-label="图解Java的垃圾回收机制"><!---->图解Java的垃圾回收机制<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/jvm/problem-tools.html" class="nav-link sidebar-link sidebar-page" aria-label="Java问题诊断和排查工具"><!---->Java问题诊断和排查工具<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/jvm/jit.html" class="nav-link sidebar-link sidebar-page" aria-label="JIT原理解析及实践"><!---->JIT原理解析及实践<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/jvm/oom.html" class="nav-link sidebar-link sidebar-page" aria-label="内存溢出排查优化实战"><!---->内存溢出排查优化实战<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/jvm/cpu-percent-100.html" class="nav-link sidebar-link sidebar-page" aria-label="CPU 100% 排查优化实践"><!---->CPU 100% 排查优化实践<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/jvm/zongjie.html" class="nav-link sidebar-link sidebar-page" aria-label="JVM 核心知识点总结"><!---->JVM 核心知识点总结<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li></ul></section><!--]--></li></ul></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">三、Java企业级开发</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">四、数据库</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">五、计算机基础</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">六、求职面试</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">七、学习资源</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">八、学习建议</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">九、知识库搭建</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">十、联系作者</span><span class="arrow right"></span></button><!----></section><!--]--></li></ul><!--[--><!----><!--]--></aside><!--[--><main class="page" id="main-content"><!--[--><!----><nav class="breadcrumb disable"></nav><div class="page-title"><h1><!---->从javap的角度轻松看懂字节码</h1><div class="page-info"><span class="author-info" aria-label="作者🖊" data-balloon-pos="down" isoriginal="false" pageview="false"><svg xmlns="http://www.w3.org/2000/svg" class="icon author-icon" viewbox="0 0 1024 1024" fill="currentColor" aria-label="author icon"><path d="M649.6 633.6c86.4-48 147.2-144 147.2-249.6 0-160-128-288-288-288s-288 128-288 288c0 108.8 57.6 201.6 147.2 249.6-121.6 48-214.4 153.6-240 288-3.2 9.6 0 19.2 6.4 25.6 3.2 9.6 12.8 12.8 22.4 12.8h704c9.6 0 19.2-3.2 25.6-12.8 6.4-6.4 9.6-16 6.4-25.6-25.6-134.4-121.6-240-243.2-288z"></path></svg><span><a class="author-item" href="/about-the-author/" target="_blank" rel="noopener noreferrer">沉默王二</a></span><span property="author" content="沉默王二"></span></span><!----><span class="date-info" aria-label="写作日期📅" data-balloon-pos="down" isoriginal="false" pageview="false"><svg xmlns="http://www.w3.org/2000/svg" class="icon calendar-icon" viewbox="0 0 1024 1024" fill="currentColor" aria-label="calendar icon"><path d="M716.4 110.137c0-18.753-14.72-33.473-33.472-33.473-18.753 0-33.473 14.72-33.473 33.473v33.473h66.993v-33.473zm-334.87 0c0-18.753-14.72-33.473-33.473-33.473s-33.52 14.72-33.52 33.473v33.473h66.993v-33.473zm468.81 33.52H716.4v100.465c0 18.753-14.72 33.473-33.472 33.473a33.145 33.145 0 01-33.473-33.473V143.657H381.53v100.465c0 18.753-14.72 33.473-33.473 33.473a33.145 33.145 0 01-33.473-33.473V143.657H180.6A134.314 134.314 0 0046.66 277.595v535.756A134.314 134.314 0 00180.6 947.289h669.74a134.36 134.36 0 00133.94-133.938V277.595a134.314 134.314 0 00-133.94-133.938zm33.473 267.877H147.126a33.145 33.145 0 01-33.473-33.473c0-18.752 14.72-33.473 33.473-33.473h736.687c18.752 0 33.472 14.72 33.472 33.473a33.145 33.145 0 01-33.472 33.473z"></path></svg><span>2022年3月27日</span><meta property="datePublished" content="2022-03-27T04:07:13.000Z"></span><span class="category-info" aria-label="分类🌈" data-balloon-pos="down" isoriginal="false" pageview="false"><svg xmlns="http://www.w3.org/2000/svg" class="icon category-icon" viewbox="0 0 1024 1024" fill="currentColor" aria-label="category icon"><path d="M148.41 106.992h282.176c22.263 0 40.31 18.048 40.31 40.31V429.48c0 22.263-18.047 40.31-40.31 40.31H148.41c-22.263 0-40.311-18.047-40.311-40.31V147.302c0-22.263 18.048-40.31 40.311-40.31zM147.556 553.478H429.73c22.263 0 40.311 18.048 40.311 40.31v282.176c0 22.263-18.048 40.312-40.31 40.312H147.555c-22.263 0-40.311-18.049-40.311-40.312V593.79c0-22.263 18.048-40.311 40.31-40.311zM593.927 106.992h282.176c22.263 0 40.31 18.048 40.31 40.31V429.48c0 22.263-18.047 40.31-40.31 40.31H593.927c-22.263 0-40.311-18.047-40.311-40.31V147.302c0-22.263 18.048-40.31 40.31-40.31zM730.22 920.502H623.926c-40.925 0-74.22-33.388-74.22-74.425V623.992c0-41.038 33.387-74.424 74.425-74.424h222.085c41.038 0 74.424 33.226 74.424 74.067v114.233c0 10.244-8.304 18.548-18.547 18.548s-18.548-8.304-18.548-18.548V623.635c0-20.388-16.746-36.974-37.33-36.974H624.13c-20.585 0-37.331 16.747-37.331 37.33v222.086c0 20.585 16.654 37.331 37.126 37.331H730.22c10.243 0 18.547 8.304 18.547 18.547 0 10.244-8.304 18.547-18.547 18.547z"></path></svg><ul class="categories-wrapper"><li class="category category0 clickable" role="navigation">Java核心</li><li class="category category1 clickable" role="navigation">JVM</li><meta property="articleSection" content="Java核心,JVM"></ul></span><span aria-label="标签🏷" data-balloon-pos="down" isoriginal="false" pageview="false"><svg xmlns="http://www.w3.org/2000/svg" class="icon tag-icon" viewbox="0 0 1024 1024" fill="currentColor" aria-label="tag icon"><path d="M939.902 458.563L910.17 144.567c-1.507-16.272-14.465-29.13-30.737-30.737L565.438 84.098h-.402c-3.215 0-5.726 1.005-7.634 2.913l-470.39 470.39a10.004 10.004 0 000 14.164l365.423 365.424c1.909 1.908 4.42 2.913 7.132 2.913s5.223-1.005 7.132-2.913l470.39-470.39c2.01-2.11 3.014-5.023 2.813-8.036zm-240.067-72.121c-35.458 0-64.286-28.828-64.286-64.286s28.828-64.285 64.286-64.285 64.286 28.828 64.286 64.285-28.829 64.286-64.286 64.286z"></path></svg><ul class="tags-wrapper"><li class="tag tag4 clickable" role="navigation">Java</li></ul><meta property="keywords" content="Java"></span><span class="reading-time-info" aria-label="阅读时间⌛" data-balloon-pos="down" isoriginal="false" pageview="false"><svg xmlns="http://www.w3.org/2000/svg" class="icon timer-icon" viewbox="0 0 1024 1024" fill="currentColor" aria-label="timer icon"><path d="M799.387 122.15c4.402-2.978 7.38-7.897 7.38-13.463v-1.165c0-8.933-7.38-16.312-16.312-16.312H256.33c-8.933 0-16.311 7.38-16.311 16.312v1.165c0 5.825 2.977 10.874 7.637 13.592 4.143 194.44 97.22 354.963 220.201 392.763-122.204 37.542-214.893 196.511-220.2 389.397-4.661 5.049-7.638 11.651-7.638 19.03v5.825h566.49v-5.825c0-7.379-2.849-13.981-7.509-18.9-5.049-193.016-97.867-351.985-220.2-389.527 123.24-37.67 216.446-198.453 220.588-392.892zM531.16 450.445v352.632c117.674 1.553 211.787 40.778 211.787 88.676H304.097c0-48.286 95.149-87.382 213.728-88.676V450.445c-93.077-3.107-167.901-81.297-167.901-177.093 0-8.803 6.99-15.793 15.793-15.793 8.803 0 15.794 6.99 15.794 15.793 0 80.261 63.69 145.635 142.01 145.635s142.011-65.374 142.011-145.635c0-8.803 6.99-15.793 15.794-15.793s15.793 6.99 15.793 15.793c0 95.019-73.789 172.82-165.96 177.093z"></path></svg><span>大约 11 分钟</span><meta property="timeRequired" content="PT11M"></span></div><hr></div><div class="toc-place-holder"><aside id="toc"><div class="toc-header">此页内容</div><div class="toc-wrapper"><ul class="toc-list"><!--[--><li class="toc-item"><a aria-current="page" href="/jvm/bytecode.html#_01、字节码" class="router-link-active router-link-exact-active toc-link level3">01、字节码</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/jvm/bytecode.html#_02、反编译字节码文件" class="router-link-active router-link-exact-active toc-link level3">02、反编译字节码文件</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/jvm/bytecode.html#_03、常量池" class="router-link-active router-link-exact-active toc-link level3">03、常量池</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/jvm/bytecode.html#_04、字段表集合" class="router-link-active router-link-exact-active toc-link level3">04、字段表集合</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/jvm/bytecode.html#_05、方法表集合" class="router-link-active router-link-exact-active toc-link level3">05、方法表集合</a></li><!----><!--]--></ul></div></aside></div><!----><div class="theme-hope-content"><h1 id="从javap的角度轻松看懂字节码" tabindex="-1"><a class="header-anchor" href="#从javap的角度轻松看懂字节码" aria-hidden="true">#</a> 从javap的角度轻松看懂字节码</h1><h3 id="_01、字节码" tabindex="-1"><a class="header-anchor" href="#_01、字节码" aria-hidden="true">#</a> 01、字节码</h3><p>计算机比较“傻”,只认 0 和 1,这意味着我们编写的代码最终都要编译成机器码才能被计算机执行。Java 在诞生之初就提出了一个非常著名的宣传口号: "<strong>一次编写,处处运行</strong>"。</p><blockquote><p><strong>Write Once, Run Anywhere.</strong></p></blockquote><p>为了这个口号,Java 的亲妈 Sun 公司以及其他虚拟机提供商发布了许多可以在不同平台上运行的 Java 虚拟机,而这些虚拟机都拥有一个共同的功能,那就是可以载入和执行同一种与平台无关的字节码(Byte Code)。</p><p>有了 Java 虚拟机的帮助,我们编写的 Java 源代码不必再根据不同平台编译成对应的机器码了,只需要生成一份字节码,然后再将字节码文件交由运行在不同平台上的 Java 虚拟机读取后执行就可以了。</p><p>如今的 Java 虚拟机非常强大,不仅支持 Java 语言,还支持很多其他的编程语言,比如说 Groovy、Scala、Koltin 等等。</p><p><img src="http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/jvm/bytecode-dd31bbd6-c75c-4426-9437-c0f57ea3b86f.png" alt=""></p><p>来看一段代码吧。</p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Main</span> <span class="token punctuation">{</span>
<span class="token keyword">private</span> <span class="token keyword">int</span> age <span class="token operator">=</span> <span class="token number">18</span><span class="token punctuation">;</span>
<span class="token keyword">public</span> <span class="token keyword">int</span> <span class="token function">getAge</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> age<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>编译生成 Main.class 文件后,可以在命令行使用 <code>xxd Main.class</code> 打开 class 文件(我用的是 Intellij IDEA,在 macOS 环境下)。</p><p><img src="http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/jvm/bytecode-bd941085-ff0e-4abf-a5f9-afb0493bfed7.png" alt=""></p><p>对于这些 16 进制内容,除了开头的 cafe babe,剩下的内容大致可以翻译成:啥玩意啊这......</p><p>同学们别慌,就从"cafe babe"说起吧,这 4 个字节称之为<strong>魔数</strong>,也就是说,只有以"cafe babe"开头的 class 文件才能被 Java 虚拟机接受,这 4 个字节就是字节码文件的身份标识。</p><p>目光右移,0000 是 Java 的次版本号,0037 转化为十进制是 55,是主版本号,Java 的版本号从 45 开始,每升一个大版本,版本号加 1,大家可以启动福尔摩斯模式,推理一下。</p><p>再往后面就是字符串常量池。《<a href="https://mp.weixin.qq.com/s/uMEZ2Xwctx4n-_8zvtDp5A" target="_blank" rel="noopener noreferrer">class 文件<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span></a>》那一篇我是顺着十六进制内容往下分析的,可能初学者看起来比较头大,这次我们换一种更容易懂的方式。</p><h3 id="_02、反编译字节码文件" tabindex="-1"><a class="header-anchor" href="#_02、反编译字节码文件" aria-hidden="true">#</a> <strong>02、反编译字节码文件</strong></h3><p>Java 内置了一个反编译命令 javap,可以通过 <code>javap -help</code> 了解 javap 的基本用法。</p><p><img src="http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/jvm/bytecode-84b7af5c-93b1-4f63-bb30-946ab3d7e98c.png" alt=""></p><p>OK,我们输入命令 <code>javap -v -p Main.class</code> 来查看一下输出的内容。</p><div class="language-text ext-text line-numbers-mode"><pre class="language-text"><code>Classfile /Users/maweiqing/Documents/GitHub/TechSisterLearnJava/codes/TechSister/target/classes/com/itwanger/jvm/Main.class
Last modified 2021年4月15日; size 385 bytes
SHA-256 checksum 6688843e4f70ae8d83040dc7c8e2dd3694bf10ba7c518a6ea9b88b318a8967c6
Compiled from "Main.java"
public class com.itwanger.jvm.Main
minor version: 0
major version: 55
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #3 // com/itwanger/jvm/Main
super_class: #4 // java/lang/Object
interfaces: 0, fields: 1, methods: 2, attributes: 1
Constant pool:
#1 = Methodref #4.#18 // java/lang/Object."<init>":()V
#2 = Fieldref #3.#19 // com/itwanger/jvm/Main.age:I
#3 = Class #20 // com/itwanger/jvm/Main
#4 = Class #21 // java/lang/Object
#5 = Utf8 age
#6 = Utf8 I
#7 = Utf8 <init>
#8 = Utf8 ()V
#9 = Utf8 Code
#10 = Utf8 LineNumberTable
#11 = Utf8 LocalVariableTable
#12 = Utf8 this
#13 = Utf8 Lcom/itwanger/jvm/Main;
#14 = Utf8 getAge
#15 = Utf8 ()I
#16 = Utf8 SourceFile
#17 = Utf8 Main.java
#18 = NameAndType #7:#8 // "<init>":()V
#19 = NameAndType #5:#6 // age:I
#20 = Utf8 com/itwanger/jvm/Main
#21 = Utf8 java/lang/Object
{
private int age;
descriptor: I
flags: (0x0002) ACC_PRIVATE
public com.itwanger.jvm.Main();
descriptor: ()V
flags: (0x0001) ACC_PUBLIC
Code:
stack=2, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_0
5: bipush 18
7: putfield #2 // Field age:I
10: return
LineNumberTable:
line 6: 0
line 7: 4
LocalVariableTable:
Start Length Slot Name Signature
0 11 0 this Lcom/itwanger/jvm/Main;
public int getAge();
descriptor: ()I
flags: (0x0001) ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: getfield #2 // Field age:I
4: ireturn
LineNumberTable:
line 9: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lcom/itwanger/jvm/Main;
}
SourceFile: "Main.java"
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>睁大眼睛瞧过去,感觉内容挺多的。同学们不要着急,我们来一行一行分析。</p><p>第 1 行:</p><div class="language-text ext-text line-numbers-mode"><pre class="language-text"><code>Classfile /Users/maweiqing/Documents/GitHub/TechSisterLearnJava/codes/TechSister/target/classes/com/itwanger/jvm/Main.class
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><p>字节码文件的位置。</p><p>第 2 行:</p><div class="language-text ext-text line-numbers-mode"><pre class="language-text"><code>Last modified 2021年4月15日; size 385 bytes
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><p>字节码文件的修改日期、文件大小。</p><p>第 3 行:</p><div class="language-text ext-text line-numbers-mode"><pre class="language-text"><code>SHA-256 checksum 6688843e4f70ae8d83040dc7c8e2dd3694bf10ba7c518a6ea9b88b318a8967c
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><p>字节码文件的 SHA-256 值。</p><p>第 4 行:</p><div class="language-text ext-text line-numbers-mode"><pre class="language-text"><code>Compiled from "Main.java"
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><p>说明该字节码文件编译自 Main.java 源文件。</p><p>第 5 行:</p><div class="language-text ext-text line-numbers-mode"><pre class="language-text"><code>public class com.itwanger.jvm.Main
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><p>字节码文件的类全名。</p><p>第 6 行 <code>minor version: 0</code>,次版本号。</p><p>第 7 行 <code>major version: 55</code>,主版本号。</p><p>第 8 行:</p><div class="language-text ext-text line-numbers-mode"><pre class="language-text"><code>flags: (0x0021) ACC_PUBLIC, ACC_SUPER
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><p>类访问标记,一共有 8 种。</p><p><img src="http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/jvm/bytecode-d12d6983-f427-40d2-bb4b-3a2c6c4c7806.png" alt=""></p><p>表明当前类是 <code>ACC_PUBLIC | ACC_SUPER</code>。位运算符 <code>|</code> 的意思是如果相对应位是 0,则结果为 0,否则为 1,所以 <code>0x0001 | 0x0020</code> 的结果是 <code>0x0021</code>(需要转成二进制进行运算)。</p><p>第 9 行:</p><div class="language-text ext-text line-numbers-mode"><pre class="language-text"><code>this_class: #3 // com/itwanger/jvm/Main
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><p>当前类的索引,指向常量池中下标为 3 的常量,可以看得出当前类是 Main 类。</p><p>第 10 行:</p><div class="language-text ext-text line-numbers-mode"><pre class="language-text"><code>super_class: #4 // java/lang/Object
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><p>父类的索引,指向常量池中下标为 6 的常量,可以看得出当前类的父类是 Object 类。</p><p>第 11 行:</p><div class="language-text ext-text line-numbers-mode"><pre class="language-text"><code>interfaces: 0, fields: 1, methods: 2, attributes: 1
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><p>当前类有 0 个接口,1 个字段(age),2 个方法(<code>write()</code>方法和缺省的默认构造方法),1 个属性(该类仅有的一个属性是 SourceFIle,包含了源码文件的信息)。</p><h3 id="_03、常量池" tabindex="-1"><a class="header-anchor" href="#_03、常量池" aria-hidden="true">#</a> 03、常量池</h3><p>接下来是 Constant pool,也就是字节码文件最重要的常量池部分。可以把常量池理解为字节码文件中的资源仓库,主要存放两大类信息。</p><p>1)字面量(Literal),有点类似 Java 中的常量概念,比如文本字符串,final 常量等。</p><p>2)符号引用(Symbolic References),属于编译原理方面的概念,包括 3 种:</p><ul><li>类和接口的全限定名(Fully Qualified Name)</li><li>字段的名称和描述符(Descriptor)</li><li>方法的名称和描述符</li></ul><p>Java 虚拟机是在加载字节码文件的时候才进行的动态链接,也就是说,字段和方法的符号引用只有经过运行期转换后才能获得真正的内存地址。当 Java 虚拟机运行时,需要从常量池获取对应的符号引用,然后在类创建或者运行时解析并翻译到具体的内存地址上。</p><p>当前字节码文件中一共有 21 个常量,它们之间是有链接的,逐个分析会比较乱,我们采用顺藤摸瓜的方式,从上依次往下看,那些被链接的常量我们就点到为止。</p><p><em>注</em>:</p><ul><li><p><code>#</code> 号后面跟的是索引,索引没有从 0 开始而是从 1 开始,是因为设计者考虑到,“如果要表达不引用任何一个常量的含义时,可以将索引值设为 0 来表示”(《深入理解 Java 虚拟机》描述的)。</p></li><li><p><code>=</code> 号后面跟的是常量的类型,没有包含前缀 <code>CONSTANT_</code> 和后缀 <code>_info</code>。</p></li><li><p>全文中提到的索引等同于下标,为了灵活描述,没有做统一。</p></li></ul><hr><p>第 1 个常量:</p><div class="language-text ext-text line-numbers-mode"><pre class="language-text"><code>#1 = Methodref #4.#18 // java/lang/Object."<init>":()V
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><p>类型为 Methodref,表明是用来定义方法的,指向常量池中下标为 4 和 18 的常量。</p><p>第 4 个常量:</p><div class="language-text ext-text line-numbers-mode"><pre class="language-text"><code>#4 = Class #21 // java/lang/Object
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><p>类型为 Class,表明是用来定义类(或者接口)的,指向常量池中下标为 21 的常量。</p><p>第 21 个常量:</p><div class="language-text ext-text line-numbers-mode"><pre class="language-text"><code>#21 = Utf8 java/lang/Object
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><p>类型为 Utf8,UTF-8 编码的字符串,值为 <code>java/lang/Object</code>。</p><p>第 18 个常量:</p><div class="language-text ext-text line-numbers-mode"><pre class="language-text"><code>#18 = NameAndType #7:#8 // "<init>":()V
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><p>类型为 NameAndType,表明是字段或者方法的部分符号引用,指向常量池中下标为 7 和 8 的常量。</p><p>第 7 个常量:</p><div class="language-text ext-text line-numbers-mode"><pre class="language-text"><code>#7 = Utf8 <init>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><p>类型为 Utf8,UTF-8 编码的字符串,值为 <code><init></code>,表明为构造方法。</p><p>第 8 个常量:</p><div class="language-text ext-text line-numbers-mode"><pre class="language-text"><code>#8 = Utf8 ()V
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><p>类型为 Utf8,UTF-8 编码的字符串,值为 <code>()V</code>,表明方法的返回值为 void。</p><p>到此为止,第 1 个常量算是摸完了。组合起来的意思就是,Main 类使用的是默认的构造方法,来源于 Object 类。</p><hr><p>第 2 个常量:</p><div class="language-text ext-text line-numbers-mode"><pre class="language-text"><code>#2 = Fieldref #3.#19 // com/itwanger/jvm/Main.age:I
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><p>类型为 Fieldref,表明是用来定义字段的,指向常量池中下标为 3 和 19 的常量。</p><p>第 3 个常量:</p><div class="language-text ext-text line-numbers-mode"><pre class="language-text"><code>#3 = Class #20 // com/itwanger/jvm/Main
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><p>类型为 Class,表明是用来定义类(或者接口)的,指向常量池中下标为 20 的常量。</p><p>第 19 个常量:</p><div class="language-text ext-text line-numbers-mode"><pre class="language-text"><code>#19 = NameAndType #5:#6 // age:I
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><p>类型为 NameAndType,表明是字段或者方法的部分符号引用,指向常量池中下标为 5 和 6 的常量。</p><p>第 5 个常量:</p><div class="language-text ext-text line-numbers-mode"><pre class="language-text"><code>#5 = Utf8 age
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><p>类型为 Utf8,UTF-8 编码的字符串,值为 <code>age</code>,表明字段名为 age。</p><p>第 6 个常量:</p><div class="language-text ext-text line-numbers-mode"><pre class="language-text"><code>#6 = Utf8 I
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><p>类型为 Utf8,UTF-8 编码的字符串,值为 <code>I</code>,表明字段的类型为 int。</p><p>关于字段类型的描述符映射表如下图所示。</p><p><img src="http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/jvm/bytecode-cbf16ce9-7853-4050-a1c0-8b874f3b0c1e.png" alt=""></p><p>到此为止,第 2 个常量算是摸完了。组合起来的意思就是,声明了一个类型为 int 的字段 age。</p><hr><h3 id="_04、字段表集合" tabindex="-1"><a class="header-anchor" href="#_04、字段表集合" aria-hidden="true">#</a> 04、字段表集合</h3><p>字段表用来描述接口或者类中声明的变量,包括类变量和成员变量,但不包含声明在方法中局部变量。</p><p>字段的修饰符一般有:</p><ul><li>访问权限修饰符,比如 public private protected</li><li>静态变量修饰符,比如 static</li><li>final 修饰符</li><li>并发可见性修饰符,比如 volatile</li><li>序列化修饰符,比如 transient</li></ul><p>然后是字段的类型(可以是基本数据类型、数组和对象)和名称。</p><p>在 Main.class 字节码文件中,字段表的信息如下所示。</p><div class="language-text ext-text line-numbers-mode"><pre class="language-text"><code>private int age;
descriptor: I
flags: (0x0002) ACC_PRIVATE
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>表明字段的访问权限修饰符为 private,类型为 int,名称为 age。</p><p>字段的访问标志和类的访问标志非常类似。</p><p><img src="http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/jvm/bytecode-5f328e11-3486-4eb4-8fa9-5c5febfab894.png" alt=""></p><h3 id="_05、方法表集合" tabindex="-1"><a class="header-anchor" href="#_05、方法表集合" aria-hidden="true">#</a> <strong>05、方法表集合</strong></h3><p>方法表用来描述接口或者类中声明的方法,包括类方法和成员方法,以及构造方法。方法的修饰符和字段略有不同,比如说 volatile 和 transient 不能用来修饰方法,再比如说方法的修饰符多了 synchronized、native、strictfp 和 abstract。</p><p><img src="http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/jvm/bytecode-fd434d5c-ffc6-4a24-9787-98e573035068.png" alt=""></p><p>下面这部分为构造方法,返回类型为 void,访问标志为 public。</p><div class="language-text ext-text line-numbers-mode"><pre class="language-text"><code> public com.itwanger.jvm.Main();
descriptor: ()V
flags: (0x0001) ACC_PUBLIC
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>来详细看一下其中 Code 属性。</p><div class="language-text ext-text line-numbers-mode"><pre class="language-text"><code> Code:
stack=2, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_0
5: bipush 18
7: putfield #2 // Field age:I
10: return
LineNumberTable:
line 6: 0
line 7: 4
LocalVariableTable:
Start Length Slot Name Signature
0 11 0 this Lcom/itwanger/jvm/Main;
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><ul><li><p>stack 为最大操作数栈,Java 虚拟机在运行的时候会根据这个值来分配栈帧的操作数栈深度。</p></li><li><p>locals 为局部变量所需要的存储空间,单位为槽(slot),方法的参数变量和方法内的局部变量都会存储在局部变量表中。</p></li><li><p>args_size 为方法的参数个数。</p></li></ul><p>为什么 stack 的值为 2,locals 的值为 1,args_size 的值为 1 呢? 默认的构造方法不是没有参数和局部变量吗?</p><p>这是因为有一个隐藏的 this 变量,只要不是静态方法,都会有一个当前类的对象 this 悄悄的存在着。这就解释了为什么 locals 和 args_size 的值为 1 的问题。那为什么 stack 的值为 2 呢?因为字节码指令 invokespecial(调用父类的构造方法进行初始化)会消耗掉一个当前类的引用,所以 aload_0 执行了 2 次,也就意味着操作数栈的大小为 2。</p><p>关于字节码指令,我们后面再详细介绍。</p><ul><li><p>LineNumberTable,该属性的作用是描述源码行号与字节码行号(字节码偏移量)之间的对应关系。</p></li><li><p>LocalVariableTable,该属性的作用是描述帧栈中的局部变量与源码中定义的变量之间的关系。大家仔细看一下,就能看到 this 的影子了。</p></li></ul><p>下面这部分为成员方法 <code>getAge()</code>,返回类型为 int,访问标志为 public。</p><div class="language-text ext-text line-numbers-mode"><pre class="language-text"><code> public int getAge();
descriptor: ()I
flags: (0x0001) ACC_PUBLIC
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>理解了构造方法的 Code 属性后,再看 <code>getAge()</code> 方法的 Code 属性时,就很容易理解了。</p><div class="language-text ext-text line-numbers-mode"><pre class="language-text"><code> Code:
stack=1, locals=1, args_size=1
0: aload_0
1: getfield #2 // Field age:I
4: ireturn
LineNumberTable:
line 9: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lcom/itwanger/jvm/Main;
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>最大操作数栈为 1,局部变量所需要的存储空间为 1,方法的参数个数为 1,是因为局部变量只有一个隐藏的 this,并且字节码指令中只执行了一次 aload_0。</p><hr><p>其实学习是这样的,可以横向扩展,也可以纵向扩展。当我们初学编程的时候,特别想多学一点,属于横向扩展,当有了一定的编程经验后,想更上一层楼,就需要纵向扩展,不断深入地学,连根拔起,从而形成自己的知识体系。</p><p>无论是从十六进制的字节码角度,还是 jclasslib 图形化查看反编译后的字节码的角度,也或者是今天这样从 javap 反编译后的角度,都能窥探出一些新的内容来!</p><p>初学者一开始接触字节码的时候会感觉比较头大,没关系,我当初也是这样,随着时间的推移,经验的积累,慢慢就好了,越往深处钻,就越能体会到那种“技术我有,雄霸天下”的感觉~</p><p><img src="http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/xingbiaogongzhonghao.png" alt=""></p></div><!----><footer class="page-meta"><div class="meta-item edit-link"><a href="https://github.com/itwanger/toBeBetterJavaer/edit/master/docs/jvm/bytecode.md" rel="noopener noreferrer" target="_blank" aria-label="在 GitHub 上编辑此页" class="nav-link label"><!--[--><svg xmlns="http://www.w3.org/2000/svg" class="icon edit-icon" viewbox="0 0 1024 1024" fill="currentColor" aria-label="edit icon"><path d="M430.818 653.65a60.46 60.46 0 0 1-50.96-93.281l71.69-114.012 7.773-10.365L816.038 80.138A60.46 60.46 0 0 1 859.225 62a60.46 60.46 0 0 1 43.186 18.138l43.186 43.186a60.46 60.46 0 0 1 0 86.373L588.879 565.55l-8.637 8.637-117.466 68.234a60.46 60.46 0 0 1-31.958 11.229z"></path><path d="M728.802 962H252.891A190.883 190.883 0 0 1 62.008 771.98V296.934a190.883 190.883 0 0 1 190.883-192.61h267.754a60.46 60.46 0 0 1 0 120.92H252.891a69.962 69.962 0 0 0-69.098 69.099V771.98a69.962 69.962 0 0 0 69.098 69.098h475.911A69.962 69.962 0 0 0 797.9 771.98V503.363a60.46 60.46 0 1 1 120.922 0V771.98A190.883 190.883 0 0 1 728.802 962z"></path></svg><!--]-->在 GitHub 上编辑此页<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span><!----></a></div><div class="meta-item update-time"><span class="label">上次编辑于: </span><span class="info">2022/5/14 上午7:14:28</span></div><div class="meta-item contributors"><span class="label">贡献者: </span><!--[--><!--[--><span class="contributor" title="email: [email protected]">itwanger</span>,<!--]--><!--[--><span class="contributor" title="email: [email protected]">沉默王二</span><!--]--><!--]--></div></footer><nav class="page-nav"><a href="/jvm/class-file-jiegou.html" class="nav-link prev" aria-label="详解Java的类文件结构"><div class="hint"><span class="arrow left"></span>上一页</div><div class="link"><!---->详解Java的类文件结构</div></a><a href="/jvm/zijiema-zhiling.html" class="nav-link next" aria-label="字节码指令详解"><div class="hint">下一页<span class="arrow right"></span></div><div class="link">字节码指令详解<!----></div></a></nav><div class="giscus-wrapper input-top" style="display:block;">Loading...</div><!----><!--]--></main><!--]--><footer class="footer-wrapper"><div class="footer"><a href="https://beian.miit.gov.cn/" target="_blank">豫ICP备2021038026号-1</a><img src="https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/beian.png" height="15px" width="15px" /><a target="_blank" href="http://www.beian.gov.cn/portal/registerSystemInfo?recordcode=41030502000411"><span>豫公网安备 41030502000411号</span></a></div><div class="copyright">Copyright © 2022 沉默王二</div></footer><!--]--></div><!--]--><!----><!----><!--]--></div>
<script type="module" src="/assets/app.41bad062.js" defer></script>
</body>
</html>