能介绍一下StackMapTable属性网红经济的运作原理理吗

在写本文之前,本人对java字节码文件结构只是有一个大致的了解
然而,有一天我突然想要细致的研究一下class文件的内部结构,于是我就真这么做了,最终的后果是浪费了周六和周天的大好时光,才将一个及其简单的类的class文件给手工翻译成字节码
今天的博客目的就是把我一个字节一个字节的翻译那个class文件的过程粘贴出来,希望对某些想要了解java字节码结构的人有用,注意:我只是简单的翻译了一下,其中涉及的java虚拟机规范等背景知识还是需要大家有一个了解,否则,看本文真是没有大多的意义。
另外,我想说的是对于CSDN博客的排版一直是一个让我头疼的问题,要是谁有好的排版方式,麻烦指导一下!!!
首先,本人把我用于翻译字节码的那个类的源码粘贴出来,一般有个对应,然而,考虑到源代码的行号会在java的字节码中有所体现,为了不破坏这种行号关系,所以,源码我就以图片的形式粘贴出来吧,这样可能会更好,so, 源码看下图吧:
对于Beast.java对应的字节码文件Beast.class,本人是用WinHex打开的,打开后的每个字节都采用16进制表示,就像下图所示的这个样子:
上图中,Beast.class通过WinHex打开之后,每一个字节都以16进制展示出来了,其中的内容以 n * 16列的形式呈现,当然上图只是一个截图,内容还不够全面,所以,为了便于copy,接下来本人以文本的形式给出该字节码文件中的所有内容。
接下来,就是关键部分,一步一步展示了上述的16进制文本如何一一对应到相应的字节码上去:
BE 表示字节码的魔数,java语言的名称与咖啡有渊源,cafebabe大概有咖啡宝贝的意思
表示小版本号是0
表示大版本号是52,根据小版本和大版本号,可以知道该类是由jdk 1.8编译的
至此,java的版本信息翻译完毕!!!
=============================================================================
常量池大小,这里显示大小为52,但实际上只有51个常量
第1个常量类型是 CONSTANT_Class
02 第1个常量表示的类的类名由常量池第2个常量指定
第2个常量类型是 CONSTANT_Utf8
0E 第2个常量表示是字符串,一共有14个字节
74 第2个常量的内容,翻译过来就是bytecode/Beast
07 第3个常量类型是类,
04 第3个常量代表的类的类名由第4个常量指定
01 第4个常量的类型是CONSTANT_Utf8
10 第4个常量表示字符串,长度由后续的16个字节组成
74 第4个常量的内容,翻译过来就是:
java/lang/Object
01 第5个常量的类型是CONSTANT_Utf8
04 第5个常量表示字符串,长度由后续4个字节组成
65 第五个常量的内容,翻译过来就是:name
01 第6个常量的类型是CONSTANT_Utf8
12 第六个常量代表字符串,长度由后续的18个字节组成
3B 第6个常量的内容,翻译过来就是:
Ljava/lang/S
01 第7个常量类型是CONSTANT_Utf8
03 第7个常量是字符串,内容由后续的3个字符组成
65 第7个常量的内容,翻译过来就是age
01 第8个常量类型是CONSTANT_Utf8
01 第8个常量是字符串。内容由后续1个字节指定
第8个常量的内容,翻译过来就是I
01 第9个常量类型是CONSTANT_Utf8
06 第9个常量是字符串,内容由后续6个字节组成
3E 第9个常量的内容,翻译过来是&init&
01 第10个常量类型是 CONSTANT_Utf8
03 第10个常量内容由后续3个字节组成
第10个常量的内容是 ()V
第11个常量的类型是 CONSTANT_Utf8
04 第11个常量的内容由后续的4个字节组成
65 第11个常量的内容, 翻译过来就是:Code
0A 第12个常量的类型是CONSTANT_Methodref
第12个常量代表方法,方法所属类型由第3个常量指定,也即:java/lang/Object
0D 第12个常量的名字和签名由第13个常量指定,也即&init& : ()V
0C 第13个常量的类型是CONSTANT_NameAndType
09 表示第13个常量的名称由第9个常量指定,也即&init&
0A 表示第13个常量的类型描述由第10个常量指定,也即()V
表示第14个常量的类型是CONSTANT_String
0F 表示第14个常量的内容由第15个常量指定,根据后文可知是monkey
01 第15个常量的类型是CONSTANT_Utf8
06 第15个常量的内容由后续的6个字节指定
79 表示第15个常量的内容,翻译过来就是 monkey
表示第16个常量的类型是CONSTANT_Fieldref
01 表示第16个常量表示字段,字段的类型名由第1个常量指定,也即bytecode/Beast
11 表示第16个常量的名称和类型索引由第17个常量指定,根据下文可知是:name : Ljava/lang/S
0C 表示第17个常量的类型是 CONSTANT_NameAndType
05 表示第17个常量的名称由第5个常量指定,也即:name
06 表示第17个常量的描述由第6个常量指定,也即:Ljava/lang/S
表示第18个常量的类型是CONSTANT_Fieldref
01 表示第18个常量表示字段,字段所属类型信息由第一个常量指定,为bytecode/Beast
13 表示第18个常量的名称和类型索引由第19个常量指定
0C 表示第19个常量的类型是CONSTANT_NameAndType
07 表示第19个常量的名称由第7个常量指定,也即age
08 表示第19个常量的类型由第8个常量指定,也即I,表示类型是一个整型
01 表示第20个常量的类型是CONSTANT_Utf8
表示第20个常量的内容由后续15个字节指定
65 表示第20个常量的内容,翻译过来就是:
LineNumberTable
01 表示第21个常量的类型是CONSTANT_Utf8
12 表示第21个常量的内容由后续的18个字节指定
65 表示第21个常量的内容,翻译过来就是:
LocalVariableTable
表示第22个常量的类型是CONSTANT_Utf8
04 表示第22个常量的内容由后续4个字节指定
73 表示第22个常量的内容,翻译过来就是this
01 表示第23个常量的类型是CONSTANT_Utf8
10 表示第23个常量的内容由后续的16个字节指定
3B 表示第23个常量的内容,翻译过来就是:
Lbytecode/B
表示第24个常量类型是CONSTANT_Utf8
04 表示第24个常量的内容由后续的4个字节指定
65 第24个常量的内容,翻译过来就是rage
01 表示第25个常量的类型是CONSTANT_Utf8
04表示第25个常量的内容由后续的4个字节指定
56 表示第25个常量的内容,翻译过来就是 (I)V
09 表示第26个常量的类型是CONSTANT_Fieldref
1B 表示第26个常量的名称由第27个常量指定,也即:java/lang/System
1D表示第26个常量的名称和类型由第29个常量指定,也即 out : Ljava/io/PrintS
07 表示第27个常量的类型是CONSTANT_Class
1C 表示第27个常量的类型由第28个常量指定,也即:java/lang/System
01 表示第28个常量的类型是CONSTANT_Utf8
10 表示第28个常量的内容由后续的16个字节指定
6D表示第28个常量的内容, 翻译过来就是
java/lang/System
0C 表示第29个常量的类型是CONSTANT_NameAndType
1E 表示的29个常量的名称由第30个常量指定,根据下文可以知道是out
1F 表示第29个常量的类型由第31个常量指定,根据下文可以知道是Ljava/io/PrintS
01 表示第30个常量的类型是CONSTANT_Utf8
03 表示第30个常量的内容由后续的三个字节指定
74 表示第30个常量的内容是:out
01 表示第31个常量的类型是CONSTANT_Utf8
表示第31个常量的内容由后续的21个字节指定
61 6D 3B 表示第31个字节的内容,翻译
过来就是:Ljava/io/PrintS
08 表示第32个常量的类型是CONSTANT_String
21 表示第32个常量的内容由第33个常量指定
01 表示第33个常量的类型是CONSTANT_Utf8
17 表示第33个常量的内容由后续的23个字节指定
6E 67 20 21 21
21 表示第33个常量的内容
,翻译过来就是:the beast is raging !!!
表示第34个常量的类型是CONSTANT_Methodref
23 表示第34个常量的所示方法的类型由第35个常量指定,根据下文可以知道是java/io/PrintStream
25 表示第34个常量的名称和类型由第37个常量指定,也即:println : (Ljava/lang/String)V
表示第35个常量的类型是CONSTANT_Class
24 表示第35个常量的名称由第36个常量指定,根据下文可以知道是:java/io/PrintStream
01 表示第36个常量的类型是CONSTANT_Utf8
13 表示第36个常量的内容由后续的19个字节指定
6D 表示第36个常量的内容,翻译出来就
是:java/io/PrintStream
0C 表示第37个常量的类型是CONSTANT_NameAndType
26表示第37个常量的名称由第38个常量指定,根据下文可知是:println
27 表示第37个常量的类型由第39个常量指定,根据下文可知是:(Ljava/lang/S)V
表示第38个常量的类型是CONSTANT_Utf8
07 表示第38个常量的内容由后续的7个字节指定
6E 表示第38个常量的内容是:println
01 表示第39个常量的类型是CONSTANT_Utf8
15 表示第39个常量的内容由后续的21个字节指定
29 56 表示第39个常量的内容,翻译
过来是:(Ljava/lang/S)V
0A 表示第40个常量的类型是CONSTANT_Methodref
01 表示第40个常量表示的方法所属的类名称由第1个常量指定,也即bytecode/Beast
29 表示第40个常量的名称和类型由第41个常量指定,也即:
rage : (I)V
0C 表示第41个常量的类型是CONSTANT_NameAndType
18 表示第41个常量的名称由第24个常量指定,根据前文可以知道是rage
19 表示的41个常量的类型由第25个常量指定,根据前文可知是(I)V
01 表示第42个常量的类型是CONSTANT_Utf8
01 表示第42个常量的内容由后面一个字节指定
69 表示的42个常量的内容是: i
01 表示第43个常量的类型是CONSTANT_Utf8
0D 表示第43个常量的内容由后续的13个字节组成
65 表示第43个常量的内容,翻译过来是:StackMapTable
01 表示第44个常量的类型是CONSTANT_Utf8
04 表示第44个常量的内容由后续的4个字节组成
6E 表示第44个常量的内容,翻译出来是: main
01 表示第45个常量的类型是CONSTANT_Utf8
16 表示第45个常量的内容由后续的22个字节组成
6E 67 3B 29 56 表示第45个常量的内容, 翻
译出来是: (Ljava/lang/S)V
0A 表示第46个常量的类型是CONSTANT_Methodref
01 表示第46个常量所属方法的类名由第一个常量指定,根据前文可知是: bytecode/Beast
0D 表示第46个常量表示的方法的名称和类型由第13个常量指定,根据前文可知: &init& : ()V
01 表示第47个常量的类型是CONSTANT_Utf8
04 表示第47个常量的内容由后续的4个字节指定
73 表示第47个常量的内容,翻译出来是:ags
01 表示第48个常量的类型是CONSTANT_Utf8
13 表示第48个常量的内容由后续的19个字节指定
3B 表示第48个常量的内容,翻译出来是
: [Ljava/lang/S
01 表示第49个常量的类型是CONSTANT_Utf8
01 表示第49个常量的内容由后续的1个字节指定
62 表示第49个常量的内容,也即:
01 表示第50个常量的类型是CONSTANT_Utf8
0A 表示第50个常量的内容由后续的10个字节指定
65 表示第50个常量的内容,翻译过来是: SourceFile
01 表示第51个常量的类型是CONSTANT_Utf8
0A 表示第51个常量的内容由后续的10个字节指定
61 表示第51个常量的内容,翻译过来就是: Beast.java
至此,常量池内容翻译完毕!!!
=============================================================================
表示类的访问标记是: 该类为public, 并且ACC_SUPER标记被设置为1
01 表示当前类,指向常量池的第1个常量,也即: bytecode/Beast
03 表示父类, 指向常量池的第3个常量,也即: java/lang/Object
00 表示接口数目为 0
至此,当前类、父类、接口翻译完毕!!!
=============================================================================
02 表示类的字段个数为 2
02 表示第1个字段的访问标记为 private
05 表示第1个字段的名称由常量池第5个常量指定,根据前文可知是:name
06 表示第:1个字段的类型描述由常量池中第6个常量指定,根据前文可以知道是:Ljava/lang/S
00 表示第1个字段的属性数目是0
02 表示第二个字段的访问标记为private
07 表示第二个字段的名称由第7个常量执行,根据前文可以知道是:age
08表示第二个字段的类型描述由常量池第8个常量指定,根据前文可以知道是I, 表示整形
00 表示第二个变量的属性数为0
至此,Class文件中的字段信息翻译完毕!!!
=============================================================================
表示该类的方法个数是3
01 表示第一个方法的访问属性是public
09 表示第一个方法的名称由第9个常量指定,根据前文可以知道是:&init&,该方法由编译器自动产生,也即构造函数
0A 表示第一个方法的描述信息由第10个常量指定,根据前文可知是:()V
01表示该方法的属性数目是1,这个唯一的属性也即方法的Code属性
0B 表示第一个方法的Code属性的名字由后续第11个常量指定,根据前文可以知道是Code,事实上所有方法的Code属性名都
是一样的,都为:Code
47表示当前Code属性的剩余长度为71,也即后续的71个字节进一步描述了Code属性
方法一的进一步描述Code属性的71个字节合起来写就是:
0C2A120EBAB00A0
接下来分析这71个字节:
02 表示操作数栈的最大深度是 2
01 表示局部变量表的最大值是 1
表示方法一的字节码的长度是由后续17个字节描述。
2A 表示字节码指令:(0x2a)aload_0,
0C 这里的0xb7也即 invokespecial, 后续的00
0C 表示该指令的参数是第12个常量,根据前文可以知道是:
java/lang/Object.&init&, 完整指令是: invokespecial
2A 表示字节码指令(0x2a):aload_0
这里12也即0x12,表示字节码指令idc, 0E表示第14个常量,完整指令也即 idc #14
10 这里,B5也0xb5,表示指令putfield, 00
10 表示常量池中的第16个常量:byte/Beast.name,完整指令可以表
表示节码指令(0x2a):aload_0
0A 这里10也即0x10,对应指令:bipush, 完整指令就是: bipush 10
这里,B5也即:0xb5,表示指令putfield, 00
12 表示常量池中的第18个常量,该常量表示变量:
bytecode/Beast.age,完整指令可以表述为:
也即0xb1,对应return指令
00 表示异常表项为0, 应为该构造方法中没有抛出或捕捉任何异常
02 表示 Code属性又拥有2个子属性
14 表示 Code属性的第一个子属性的名字索引是20,也即第20个常量,根据前文可以知道是:LineNumberTable
表示LineNumberTable属性的长度是18,也即后续的18个字节,这18个字节合起来写就是00 04 00 00 00 03
00 04 00 06 00 0A 00 07 00 10 00 03
接下来分析这18个字节:
04 表中一共有四对行号映射 LineNumberTable
前两个字节是0后两个为3, 表示字节码偏移量为0,行号是3
前两个字节是4后两个为6, 表示字节码偏移量为4,行号是6
前两个字节是10后两个为7, 表示字节码偏移量为10,行号是7
前两个字节是16后两个为3, 表示字节码偏移量为16,行号是3
表示 Code属性的第二个属性的名字索引是21,也即第21个常量,根据前文可以知道是:LocalVariableTable
0C 表示后续的12个字节长度进一步描述LocalVariableTable, 这12个字节合起来写是00 01 00 00 00 11 00
16 00 17 00 00, 接下来解释这12个字节
01 表示仅有1个局部变量
该局部变量的开始位置0
表示该局部变量的结束位置是17
该局部变量的Index,也即曹位是0
16 该局部变量的名字由常量池第22项指定,根据前文可以知道是:this
17 是对该局部变量的描述,由常量池第23个常量指定,也即: Lbytecode/Beast
表示该方法的StackMapTable的长度是0
至此,第一个方法,也即编译自动生成的&init&方法翻译完毕!!!。
=============================================================================
剩余的内容合起来写就是:
0001000B1B04B1B028B400000
C002DEBB2E4C2B03B00E0
接下来继续分析余下的内容:
01 表示第二个方法的访问标记是public
18 第二个方法的名字由第24个常量指定,根据前文可知是: rage
19 第二个方法的描述有第25个常量指定,根据前文可以知道是: (I)V,表示参数是一个整数,方法无返回值
01 表示该方法有一个属性(也即Code属性),
0B 表示该方法Code属性的名字由第11个常量指定,根据前文可以知道是:Code,事实上所有方法Code属性的名字都恒定为
64 表示后续的100个字节用于进一步描述code属性,这100个字节合起来是:
06A1AA1BB00B90
00F002AB09
接下来进一步描述这100个字节:
00 02 表示操作数栈最大深度是2
00 02 局部变量表最大值是2
17 表示接下来的23个字节用于描述方法2的字节码
1B 也即0x1b, 表示指令:iload_1
01 前面的84也即0x84 对应指令innc, 这三个字节翻译成指令就是是: innc 1 by 1
06 也即0x06,对应指令:iconst_3
A0 00 04 翻译成指令是if_icmpne
9 (+4) ,表示如果条件不成立,则跳转到第9行
B1 也即0xB1, 对应指令return
B2 00 1A 这里B2即0xB2对应getstatic, 00 1A对应第26个常量,表示方法java/lang/System.out,翻译过来就是:
getstatic #26
12 20 这里12也即0x12,对应指令:idc, 20 对应第32个常量,也即: the beast is raging !!!, 该句翻译成指令是:
B6 00 22 这里B6也即0xB6,对应invokevirtual, 00 22 也即第34个常量,表示方法:java/io/PrintStream.println,翻译
过来就是: invokevirtual
2A 也即0x2a, 对应指令:aload_0
1B 也即0x1B, 对应指令:iload_1
B6 00 28 这里B6对应invokevirtual, 00 28对应常量池第40项,表示方法bytecode/Beast.rage, 翻译过来就是:
invokevirtual #40
B1也即0xB1, 对应指令:return
00 00 异常表项的长度,也即该方法没有显式抛出或捕获任何异常
方法二的Code属性又有3个子属性
14 第1个子属性的名字索引,对应常量池第20项,也即:LineNumberTable,
00 00 00 16 表示后续的22个字节描述了行号表,这22个字节合起来是:B
,接下来分析这22个字节
00 05 表示该行号表一共有5项行号映射
00 00 00 0B
前两个字节也即0,后两个字节是11,表示字节码偏移量是0,行号是11
00 08 00 0D
前两个字节也即8,后两个字节是13,表示字节码偏移量是8,行号是13
00 09 00 0F
前两个字节也即9,后两个字节是15,表示字节码偏移量是9,行号是15
00 11 00 10
前两个字节也即17,后两个字节是16,表示字节码偏移量是17,行号是16
00 16 00 12
前两个字节也即22,后两个字节是18,表示字节码偏移量是22,行号是18
第2个子属性的名字索引是第21个常量,也即:LocalVariableTable
00 16 表示后续的22个字节用于描述局部变量表,这22个字节是:
A,接下来分析这22个字节
00 02 表示局部变量表项一共有2项
00 00 局部变量开始位置是0
00 17 局部变量结束位置是23
00 局部变量的Index是0,
16 局部变量的名字由22号常量指定,根据前文可知是:this
00 17 局部变量的描述由第23项指定,根据前文可知是:Lbytecode/Beast
00 00 00 00 第二个局部变量的开始位置是0,这个局部变量的开始位置为什么用了四个字节描述,本人没弄清楚,但只有这样
,后续才能对应得上,求高人指点!!!
00 17 第二个局部变量的结束位置是23
00 第二个局部变量Index是0
2A 第二个局部变量名字由第42个常量指定,根据前文可知是:i
00 08 第二个局部变量类型描述由第8个常量指定,根据前文可知是:I,表示整形
00 01 表示该Code属性还有一个StackMapTable属性
00 2B 表示StackMapTable的名字由第43个常量指定,也即:StackMapTable
00 00 00 03 表示StackMapTable由后面的3个字节描述
00 01 表示StackMapTable仅有一个表项
09 表示StackMapTable仅有的一个表项,也即:same_frame, 表示与上一桢相比,局部变量的数量没有变化,这一桢距离上一
栈桢的偏移量是9
至此, 第二个方法rage(int i)翻译完毕!!!
=============================================================================
剩下的内容合起来是:
0089002C002DEBB2E4C2B03B00E000
接下来分析剩余部分
89 表示第三个方法访问标记是 public static
2C 表示第三个方法的名字由第44个常量指定,根据前文可以知道是:main
2D 表示第三个方法的描述信息由第45个常量指定,根据前文可以知道是:([Ljava/lang/S)V
01 表示第三个方法有一个属性(Code属性)
0B 表示Code属性的名字由第11个常量指定,根据前文可知是Code,注意,任何方法的Code属性的名字都恒定为Code
4A 表示后续的74个字段用于进一步描述该方法的Code属性,这74个字节合起来写是:
000EBB2E4C2B03B00ED0016000
接下来分析这74个字节的内容:
02 表示方法三的操作数栈最大深度是2
00 02 表示方法三的局部变量最大值是2
0E 表示方法三的字节码由后续的14个字节指定
BB 00 01这里,BB也即0xbb,对应指令:new, 00 01指代第一个常量,表示类:bytecode/Beast,翻译过来就是: new #1
59 也即0x59,对应虚拟机指令: dup
B7 00 2E 这了,B7也即0xB7,对应指令是invokespecial , 00 2E对应第46个常量,表示构造函数:bytecode/Beast.&init&
,翻译过来就是: invokespecial #46
4C 也即指令:astore_1
2B 也即指令:aload_1
03 也即指令:iconst_0
B6 00 28 这里, B6对应 invokevirtual , 00
28对应第40项常量,表示方法:bytecode/Beast.rage
翻译过来就是 invokevirtual #40,其实就是调用Beast对象实例的rage方法
B1 对应指令:return
00 00 00 02 这里,表示方法三的Code属性有两个子属性
14 第一个子属性的名字,对应常量池20项,也即:LineNumberTable
00 00 00 0E 表示接下来的14个字节进一步描述LineNumberTable,这14个字节合起来写是D0019,
接下来翻译这14个字节
00 03 表示该方法中行号表的表项为3
00 00 00 16
这里00 00 也即0, 00 16也即22,表示字节码偏移量是0,行号是22
00 08 00 17
这里00 08 也即8, 00 17也即23,表示字节码偏移量是8,行号是23
00 0D 00 19
这里00 0D 也即13,00 19也即25,表示字节码偏移量是13,行号是25
00 15 表示第二个子属性的名字由常量池第21项指定,也即:LocalVariableTable
00 16 表示后续的22个字节进一步描述局部变量表
00 02 第一个局部变量的开始位置是2
00 00 00 0E 第一个局部变量的结束位置是14
第一个局部变量槽位是0
第一个局部变量的名字由第47个常量指定,也即:args
第一个局部变量的类型描述由第48个常量指定,也即[Ljava/lang/S 表示字符串数组
第二个局部变量的开始位置是8
第二个局部变量的结束位置是6
第二个局部变量的槽位是0
第二个局部变量的名字由第49个常量指定,也即: b
17 第二个局部变量的类型描述由第23项指定,也即: Lbytecode/B 表示Beast类型
00 01 表示main方法有一个StackMapTable
至此,第三个方法(main方法)翻译完毕!!!
=============================================================================
此时,整个字节码目前只剩下还没由分析,接下来分析该剩余部分
表示该字节码拥有一个属性,注意,该属性不是方法的属性,而是表示整个class文件的属性,也即SourceFile属性
表示SourceFile属性的名字由第50个常量指定,根据前文可以知道是: SourceFile
表示后续的两个字节用于表述SourceFile属性
33 表述SourceFile属性表示的源代码文件名由第51个常量指定,也即: Beast.java
至此,整个class文件分析完毕,congratulations!!!
注意,上述就是本人纯手工翻译Beast.class字节码文件中内容的过程,短短一小个class文件,翻译过程却几乎耗费了本人两个双休日的时间,不过收获不小哦,并且,亲自翻译过一遍以后,通过jdk自带工具javap查看字节码内容时候,瞬间感觉不再是那么陌生了,相反感觉很亲切,一见如故!古诗云曾经沧海难为水,除去巫山不是云,确有此理!因为自己实践过,所以对class文件结构理解会比以往更加深刻!!!
通常,我们可以通过jdk自带javap命令查看class文件的内容,对于本例,可以使用下述命令查看,也可以参见下图:
javap -verbose Beast.class
最后,向大家推荐一个及其强大和易用的java字节码查看工具,他就是大名鼎鼎的:jClasslib,
事实上,为了验证自己的翻译是否正确,我在写博客之前还把自己翻译的结果和jClasslib翻译的结果做了对照检查!使用jClasslib打开Beast.class文件的截图如下,看!里面的字节码内容特别结构化,层次清晰,一目了然,jClasslib堪称神器!!!
本文已收录于以下专栏:
相关文章推荐
javassist是一个开源的分析、编辑和创建java字节码的类库。不需要了解虚拟机指令,就能动态生成类或者改变类的结构。
(1)下载链接http://www.csg.ci....
查看java字节码 
1 javac –verbose查看运行类是加载了那些jar文件
HelloWorld演示:
javac –verbose HelloWorld.java
可以看到虚拟...
转自1:    http://blog.csdn.net/a/article/details/
转自2:    http://blog.csdn.net/lm23...
1.Class文件基础
(1)文件格式
Class文件的结构不像XML等描述语言那样松散自由。由于它没有任何分隔符号,
所以,以上数据项无论是顺序还是数量都是被严...
闭锁是一次性对象,一旦进入终止状态,就不能被重置,它是用来启动一组相关的操作,或者等待一组相关的操作结束。
栅栏跟闭锁有点类似,它能阻塞一组线程直到某个时间发生,但是这里有个很大的区别,在栅栏里,只有...
Other bytes
[before]→[after]
Description
最近在学习逆向分析和反编译,无意之中了解到了JClassLib。JClassLib不但是一个字节码阅读器而且还包含一个类库允许开发者读取,修改,写入Java Class文件与字节码。其他的用途我就不说...
查看java字节码 
1 javac –verbose查看运行类是加载了那些jar文件
HelloWorld演示:
javac –verbose HelloWorld.java
查看java字节码 
1 javac –verbose查看运行类是加载了jar文件 
HelloWorld演示: 
Java代码  
public class  H...
他的最新文章
讲师:姜飞俊
讲师:汪木铃
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)

我要回帖

更多关于 发动机运作原理 的文章

 

随机推荐