Chinaunix首页 | 论坛 | 博客
  • 博客访问: 107544
  • 博文数量: 14
  • 博客积分: 10
  • 博客等级: 民兵
  • 技术积分: 184
  • 用 户 组: 普通用户
  • 注册时间: 2011-03-01 23:15
个人简介

我只是一个喜欢开发的测试,喜欢测试的开发,喜欢每天都知道得更多一些,更深入一些的感觉。。。。。

文章分类

全部博文(14)

文章存档

2015年(5)

2014年(2)

2013年(7)

分类: Java

2013-08-30 07:43:10

随便拿了一个之前写自定义MBean例子时HelloWorldMBean的实现类HelloWorld编译后的class文件HelloWorld.class。先把HelloWorld.java代码罗列一下,以便我们之后对照着看。

 

嗯,非常简单,网上到处是这样的例子代码。好了,让我们开始吧!

 

HelloWorld.class拉到UltraEdit里面,是下面这样的:




对于class文件结构,首先要知道以下几点:

1)   Class文件中所有数据项紧密排列,各数据项之间不存在任何分隔符或填充对齐符;

2)   各个数据项长度,要么是固定的,要么就是在其之前有个固定长度的项指定该项的长度;

3)   Class文件中只有两种数据类型:无符号数和表;

4)   Class文件可以按数据项内容分为8个部分。

先知道这么多吧,下面我们从头开始,一个数据项一个数据项来分析。


1.    魔数(Magic)

class文件的头4个字节0xCAFEBABE,魔数,身份的标志,我是class文件,与生俱来,血统纯正!


2.   版本信息(minor_version & major_version)

56两个字节是次版本,此为0x0000,即0

78两个字节是主版本,此为0x0032,即50JDK1.145,之后每次升级加1,因此(1.1+(50-45)*0.1)=1.6,而我所使用的正是jdk1.6.0_31


3.   常量池(constant_pool)

910两个字节是常量表长度,0x003654,即53个常量。

class文件中的常量除了字面量,如代码中的“Hello World, ”,以及声明为final的常量外,还包括符号引用,诸如类/接口的全限定名、字段/方法的名称及描述符,之所以包括这些,是因为需要在JVM运行的时候,根据这些信息动态连接到内存中的类。

常量表开始,读取第一个表项,class文件中一共有11种类型的常量表表项,每种表项的第一个字节都是一个标志字段tag,用来标识是什么类型的表项,然后根据不同的类型来解析接下来的字节,因为每种表项的结构是不尽相同的。

11字节为0x07,表示该表项是个类/接口符号引用,该类型的结构为第23两个字节为索引值,此为0x0002,即指向常量池中第二个表项。

我们来看第二个表项,首先tag0x01UTF-8字符串类型,因此其后两个字节0x0020是字符串长度,内容即紧接下来的32字节“com/momo/javatips/jmx/
HelloWorld
”。

对照源代码,除了包名和关键字之外,首先出现的HelloWorld类,其全限定名正是“com.momo.javatips.jmx.HelloWorld”。



通过以上对第一、二两个表项的详细说明,我们已经对怎么解析常量表表项有所了解,接下来对其余的表项就不再一一这样详细地分析了,我只将每个表项的原始值及分析结果在下表中列出: 

表项编号

偏移量

原始值

分析结果

#1


 

0000 000a

0x07

类符号引用

0000 000b

0x0002

指向第2个表项——其全限定名com/momo/javatips/jmx/HelloWorld

#2


 

0000 000d

0x01

UTF-8字符串

0000 000e

0x0020

长度32字节

0000 0010

0x63 6F……6C 64

com/momo/javatips/jmx/HelloWorld

#3


 

0000 0030

0x07

类符号引用

0000 0031

0x0004

指向第4个表项——其全限定名java/lang/Object

#4


 

0000 0033

0x01

UTF-8字符串

0000 0034

0x0010

长度16字节

0000 0036

0x6A 61……63 74

java/lang/Object

#5


 

0000 0046

0x07

接口符号引用

0000 0047

0x0006

指向第6个表项——其全限定名com/momo/javatips/jmx/HelloWorldMBean

#6


 

0000 0049

0x01

UTF-8字符串

0000 004a

0x0025

长度37字节

0000 004c

0x63 6F……61 6E

com/momo/javatips/jmx/HelloWorldMBean

#7


 

0000 0071

0x01

UTF-8字符串

0000 0072

0x0004

长度4字节

0000 0074

0x6E 61 6D 65

name

#8


 

0000 0078

0x01

UTF-8字符串

0000 0079

0x0012

长度18字节

0000 007b

0x4C 6A…… 67 3B

Ljava/lang/String;

#9


 

0000 008d

0x01

UTF-8字符串

0000 008e

0x0006

长度6字节

0000 0090

0x3C 69…… 74 3E

#10


 

0000 0096

0x01

UTF-8字符串

0000 0097

0x0003

长度3字节 

0000 0099

0x28 29 56

()V

#11


 

0000 009c

0x01

UTF-8字符串

0000 009d

0x0004 

长度4字节

0000 009f

0x43 6F 64 65

Code

#12


 

0000 00a3

0x0A

方法符号引用

0000 00a4

0x0003

指向第3个表项——其所属类Object

0000 00a6

0x000D

指向第13个表项——其符号引用

#13


 

0000 00a8

0x0C

方法名称及描述符符号引用

0000 00a9

0x0009

指向第9个表项——其名称常量

0000 00ab

0x000A

指向第10个表项——其描述符常量()V

#14


 

0000 00ad

0x01

UTF-8字符串

0000 00ae

0x000F

长度15字节

0000 00b0

0x4C 69…… 6C 65

LineNumberTable

#15


 

0000 00bf

0x01

UTF-8字符串

0000 00c0

0x0012

长度18字节

0000 00c2

0x4C 6F…… 6C 65

LocalVariableTable

#16


 

0000 00d4

0x01

UTF-8字符串

0000 00d5

0x0004

长度4字节

0000 00d7

0x74 68 69 73

this

#17


 

0000 00db

0x01

UTF-8字符串

0000 00dc

0x0022

长度34字节

0000 00de

0x4C 63……64 3B

Lcom/momo/javatips/jmx/HelloWorld;

#18


 

0000 0100

0x01

UTF-8字符串

0000 0101

0x0007

长度7字节

0000 0103

0x67 65……6D 65

getName

#19


 

0000 010a

0x01

UTF-8字符串

0000 010b

0x0014

长度20字节

0000 010d

0x28 29……67 3B

()Ljava/lang/String;

#20


 

0000 0121

0x09

字段符号引用 

0000 0122 

0x0001 

指向第1个表项——所属类HelloWorld 

0000 0124 

0x0015 

指向第21个表项——其描述符 

#21


 

0000 0126 

0x0C 

方法名称及描述符符号引用 

0000 0127 

0x0007 

指向第7个表项——其名称常量name 

0000 0129 

0x0008 

指向第8个表项——其描述符常量 

Ljava/lang/String; 

#22


 

0000 012b 

0x01 

UTF-8字符串 

0000 012c 

0x0007 

长度7字节 

0000 012e 

0x73 65……6D 65 

setName 

#23


 

0000 0135 

0x01 

UTF-8字符串 

0000 0136 

0x0015 

长度21字节 

0000 0138 

0x28 4C……29 56 

(Ljava/lang/String;)V 

#24


 

0000 014d 

0x01 

UTF-8字符串 

0000 014e 

0x000A 

长度10字节 

0000 0150 

0x70 72……6C 6F 

printHello 

#25


 

0000 015a 

0x09 

字段符号引用 

0000 015b 

0x001A 

指向第26个表项——所属类System 

0000 015d 

0x001C 

指向第28个表项——其描述符 

#26


 

0000 015f 

0x07 

类符号引用 

0000 0160 

0x001B 

指向第27个表项——其全限定名java/lang/System

#27


 

0000 0162 

0x01 

UTF-8字符串 

0000 0163 

0x0010 

长度16字节 

0000 0165 

0x6A 61……65 6D 

java/lang/System 

#28


 

0000 0175 

0x0C 

字段名称及描述符符号引用 

0000 0176 

0x001D 

指向第29个表项——其名称常量out 

0000 0178 

0x001E 

指向第30个表项——其描述符常量Ljava/io/PrintStream;

#29


 

0000 017a

0x01

UTF-8字符串

0000 017b 

0x0003 

长度3字节 

0000 017d 

0x6F 75 74 

out 

#30


 

0000 0180

0x01

UTF-8字符串

0000 0181

0x0015

长度21字节

0000 0183 

0x4C 6A……6D 3B 

Ljava/io/PrintStream; 

#31


 

0000 0198 

0x07 

类符号引用 

0000 0199 

0x0020 

指向第32个表项——其全限定名java/lang/StringBuilder

#32


 

0000 019b 

0x01 

UTF-8字符串

0000 019c 

0x0017 

长度23字节 

0000 019e

0x6A 61……65 72 

java/lang/StringBuilder 

#33


 

0000 01b5 

0x08 

字符串类型字面量 

0000 01b6 

0x0022 

指向第34个表项——其值Hello World,  

#34


 

0000 01b8 

0x01 

UTF-8字符串 

0000 01b9 

0x000D 

长度13字节 

0000 01bb 

0x48 65……2C 20 

Hello World,  

#35


 

0000 01c8 

0x0A 

方法符号引用 

0000 019 

0x001F 

指向第31个表项——其所属类StringBuilder 

0000 01b 

0x0024 

指向第36个表项——其符号引用 

#36


 

0000 01cd 

0x0C 

方法名称及描述符符号引用 

0000 01ce 

0x0009 

指向第9个表项——其名称常量 

0000 01d0 

0x0017 

指向第23个表项——其描述符常量

(Ljava/lang/String;)V 

#37


 

0000 01d2 

0x0A 

方法符号引用 

0000 01d3 

0x001F 

指向第31个表项——其所属类StringBuilder

0000 01d5 

0x0026 

指向第38个表项——其符号引用 

#38


 

0000 01d7

0x0C 

方法名称及描述符符号引用

0000 01d8

0x0027

指向第39个表项——其名称常量append

0000 01da 

0x0028 

指向第40个表项——其描述符常量(Ljava/lang/String;)Ljava/lang/StringBuilder;

#39


 

0000 01dc

0x01

UTF-8字符串

0000 01dd 

0x0006 

长度6字节 

0000 01df 

0x61 70……6E 64 

append 

#40


 

0000 01e5 

0x01 

UTF-8字符串 

0000 01e6 

0x002D 

长度45字节 

0000 01e8 

0x28 4C……72 3B 

(Ljava/lang/String;)Ljava/lang/StringBuilder; 

#41


 

0000 0215

0x0A 

方法符号引用

0000 0216

0x001F

指向第31个表项——其所属类StringBuilder

0000 0218

0x002A

指向第42个表项——其符号引用

#42


 

0000 021a

0x0C 

方法名称及描述符符号引用

0000 021b

0x002B

指向第43个表项——其名称常量toString

0000 021d

0x0013

指向第19个表项——其描述符常量()Ljava/lang/String;

#43


 

0000 021f

0x01

UTF-8字符串

0000 0220 

0x0008

长度8字节

0000 0222 

0x74 6F……6E 67 

toString 

#44


 

0000 022a 

0x0A 

方法符号引用

0000 022b

0x002D

指向第45个表项——其所属类PrintStream

0000 022d

0x002F

指向第47个表项——其符号引用

#45


 

0000 022f

0x07

类符号引用

0000 0230

0x002E

指向第46个表项——其全限定名java/io/PrintStream

#46


 

0000 0232

0x01

UTF-8字符串

0000 0233

0x0013

长度19字节

0000 0235

0x6A 61……61 6D

java/io/PrintStream

#47


 

0000 0248

0x0C

方法名称及描述符符号引用

0000 0249

0x0030

指向第48个表项——其名称常量println

0000 024b 

0x0017 

指向第23个表项——其描述符常量 

(Ljava/lang/String;)V 

#48


 

0000 024d 

0x01 

UTF-8字符串 

0000 024e 

0x0007 

长度7字节 

0000 0250

0x70 72……6C 6E 

println

#49


 

0000 0257

0x08

字符串类型字面量

0000 0258

0x0032

指向第50个表项——其值Hello ,

#50


 

0000 025a

0x01

UTF-8字符串

0000 025b

0x0008

长度8字节

0000 025d

0x48 65……2C 20 

Hello ,

#51


 

0000 0265

0x01

UTF-8字符串

0000 0266

0x0007

长度7字节

0000 0268

0x77 68……6D 65

whoName

#52


 

0000 026f

0x01

UTF-8字符串

0000 0270

0x000A

长度10字节

0000 0272

0x53 6F……6C 65

SourceFile

#53


 

0000 027c

0x01

UTF-8字符串

0000 027d

0x000F

长度15字节

0000 027f

0x48 65……76 61

HelloWorld.java


在我们这个
HelloWorld.class文件的常量表中只涉及到了UTF-8字符串(0x01)、类或接口(0x07)、字符串类型字面量(0x08)、字段符号引用(0x09)、方法符号引用(0x0A)、方法或字段名称及描述符符号引用(0x0C)6种常量类型,其余的5种等以后涉及了再讨论。





阅读(1815) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~