我们都知道JAVA是一种解析型说话,这就抉择JAVA文件编译后不是机械码,而是一个字节码文件,也就是CLASS文件。而这样的文件是存在纪律的,经由反编译工具是可以还原回来的。例如Decafe、FrontEnd,YingJAD和Jode等等软件。下面是《Nokia中Short数组转换算法》 类中Main函数的ByteCode:7 ?0 B8 F& K- ?
0 ldc #16. o/ r4 U1 p; L* n1 s7 g8 h
2 invokestatic #181 V$ i+ N8 C! ?7 D7 D
5 astore_1) }2 e% {- \: P' x$ V# O8 ^8 J
6 return4 p( h7 F' Z5 E/ @
其源代码是:short [] pixels = parseImage("/ef1s.png");; d& J, o, q) ?) d+ L4 A
我们经由过程反编译工具是可以还原出以上源代码的。而经由过程简单的剖析,我们也能自己写出源代码的。" y1 D& ^0 z' Q$ Y S
第一行:ldc #16, W; K9 a, F% Q" d: @$ F7 k
ldc为虚拟机的指令,浸染是:压入常量池的项,形式如下
# `; G: _$ y* n7 g ldc index: h2 S' x) a, d( o" O, i H# e1 c! O: ^) K
这个index就是膳缦沔的16,也就是在常量池中的有用索引,当我们去看常量池的时辰,我们就会找到index为16的值为String_info,琅缦沔存了/ef1s.png.
/ I0 t# J7 U+ _1 O% G$ V1 C" {5 { 所以这行的意思就是把/ef1s.pn作为一个String存在常量池中,其有用索引为16。
* b: v" s5 V; g 第二行:2 invokestatic #18/ Q' Y/ ]/ P; \! N4 h/ V
invokestatic为虚拟机指令,浸染是:挪用类(static)体例,形式如下& t# u+ v4 Z; s5 J
invokestatic indexbyte1 indexbyte2
# _7 k! |" o' N" H* L# T4 b 其中indexbyte1和indexbyte2必需是在常量池中的有用索引,而是指向的类型必需有Methodref标识表记标帜,对类名,体例名和体例的描述符的引用。* ?6 ^) K y7 s3 p
所以当我们看常量池中索引为18的处所,我们就会获得以下信息:
9 N" S: f- H5 V% F8 _- B% c" } Class Name : cp_info#1* w% c& o% i- \: p: _, |) P
Name Type : cp_info#19
$ D" \* [; A3 A7 T 1 和19都是常量池中的有用索引,值就是右边中的值,再往下跟踪我就不多说了,有乐趣的伴侣可以去JAVA虚拟机规范。0 c" @! G r: C& y3 A
这里我简单介绍一下parseImage(Ljava/lang/String;)[S 的意思。' g" y# x- m6 R; Z- Z7 b$ I/ ?
这就是parseImage这个函数的运行,我们反过来看看parseImage的原型就年夜白了
; Z# N# h% N$ `! c9 Y, E0 o. Z short [] parseImage(String)# X7 N. v% F& t5 @2 m9 g
& l. t. y9 Z) c) |' w
那么Ljava/lang/String;就是说需要传入一个String对象,而为什么前面要有一个L呢,这是JAVA虚拟机用来暗示这是一个Object。如不美观是根基类型,这里就不需要有L了。然后返回为short的一维数组,也就是对应的[S。是不是很有意思,S对应着Short类型,而 “[”对应一维数组,那有些伴侣要问了,两维呢,那就“[[”,呵呵,是不是很有意思。 |