本文来自http://blog.csdn.net/liuxian13183/ ,引用必须注明出处!
Java的类结构是对变量,各种访问标记,接口和继承,同步、枚举,注解,内部类,异常、方法等的组合
类文件是以8个字节为基础单位的二进制流
类文件和图片都有魔数,用来标识它可以被虚拟机接受,即0xCafeBabe-全大写,只是为了方便大家记忆;在很多地方都有应用,因为文件后缀名可以改变,而它不能改变。
Java类文件的前4位代表它是否能被虚拟机接受,之后是版本号,5和6代表次版本号,7和8代表主版本号
紧接下来的是常量,大概有11种表结构,除了常见的String,Integer,Float,Double,Long以外,还有Class,Utf-8,Field,Method,InterfaceMethod,NameAndType类型,数量不确定
接着是访问标志有8种,public,final,abstract,interface,super,enum,annotation,synthetic(非用户代码产生的类)
接着是“继承”索引,this索引和super索引,除Object以外,其他索引值均不为0,代表有父类;索引集合描述这个类实现了哪些接口,从左到右按顺序排列,有几个计数器值为几
再接下来是字段表集合,描述所有的变量(如作用范围-public,并变性-final,并发可见-volatile等)和返回值(基本数据类型和类),基本数据类型的全限定名,开头都是其英文大写,如'[()V; '和'[[Ljava/lang/String';前者代表一个空返回值,后者代表一个String二维数组,类都以L开头作表示;全限定名可以理解为对象的地址。
接下来到方法表集合了,跟字段表一样,但某些访问控制答不能修饰方法,如volatile和transient关键字,方法名加尖括号表示,如<init>-指实例构造器,<cinit>-指类构造器,编译后的代码存在一个"Code"的属性里
属性表,类、方法体、常量表中都有属性表
1、Code属性指编译后的字节码,还有它的长度,栈的最大深度,最大存储空间,一个方法编译后不允许超过65535个字节码指令,一个指令=1Slot=32位,这是最小的存储单位,而float和int都是32位;一般还可以分为源码和元数据(即对源码的描述,如类,字段,方法等)
public static int getFinally() { int a = 1; try { a = 2; return a; } catch (Exception e) { // TODO: handle exception a = 3; return a; } finally { a = 4; } }上面是用一段源码,来对字节码指令进行分析,很多人看见后,都很想对照自己的结果,准确答案是 2
跟你的结果是否一致,为什么是2而不是4呢?
这段代码可以分为三层来分析:
第一层如果try没有任何问题,则执行a=2 return a
第二层,如果try出错,则执行finally,再执行catch语句,a=3 return a
第三层,如果try无错,catch无错,而出现了其他error,则直接执行finally语句的a=4
这个地方可以这样理想,按照正常的Java指令没有打乱的情况下,先执行try return时已经执行a的write方法,则finally中仅执行了a的assign方法,此时a已经为2。不懂变量加载过程的,可以查看:Java高级之内存模型分析
2、Exceptions属性 列举出可检查出的异常如catch语句后和throws的异常
3、LineNumberTable属性 描写源码行号与字节码行号的关系,即这段代码位于哪一行,用于异常抛出时定位
4、LocalVariableTable属性 定义后别人引用,不会产生参数是arg0,arg1的情况
5、SourceFile属性,用于记录Class源码文件名称,主要异常抛出时可以定位是哪个文件
6、ConstantValue属性,通知虚拟机自动定义为静态变量,只能为基本数据类型和String类型
7、InnerClasses属性 显然定义内部类的,数量位置等
8、Deprecated及Synthetic 前者是定义废弃类,方法,变量等,后者指非源码产生由编译器自动加的东西。
Class文件是虚拟机解释的入口,了解其内部结构,有助于对代码进行分析定位错误,以及热加载等其他功能的理解。
以下是拓展知识
1位=1bit 最小的计算机单位,指0和1
byte=8bit 字节 取值范围 -2^8到2^7 记忆技巧 2^字节次方
char =2byte 0到2^16 Unicode
short=2byte -2^15到2^15-1
int =4byte -2^31到2^31-1
float=4byte
long=8byte -2^63到2^63-1
double=8byte
boolean 无意义
一个汉字是2位,一个英文字母1位
虚拟机的存存储区域,一般常说的有栈和堆,栈放指针和基本数据类型,而堆放对象,还有一种需要熟悉的是常量存储,就是存代码内部(方法里的);还有两种拓展了解:寄存器位于处理器内部,极少,处理极快;非RAM存储,如持久化对象和流对象,特指数据流传输和硬盘对象。除了常量存储存在只读存储器(ROM-Only)和寄存器,其他都存在随机访问存储器(RAM-Acess)里。
位操作介绍四种,位与(&),位或(|),位否(~)和异或(^)
位与,同为1则为1,否则为0
位或,有一个1则为1,否同为0
位否,1变0,0变1 计算方式~x=-(x+1)
异或,不同则为1,相同则为0
int a = 0x010101; int b = 0x110100; System.out.println(a & b); System.out.println("位于操作:"+0x010100); System.out.println(a | b); System.out.println("位或操作:"+0x110101); System.out.println(a ^ b); System.out.println("异或操作:"+0x100001);结果
65792
位于操作:65792
1114369
位或操作:1114369
1048577
异或操作:1048577
Tips:负数操作 要先获得补码再操作,然后变源码+1操作
图片的大小=图片width*height*颜色深度
格式有四种(A-Alpha不透明度 R-Red G-Green B-Blue)
ALPHA_8格式 8位=1byte
ARGB_4444格式 16位=4+4+4+4=2byte
RGB_565格式 16位=5+6+5=2byte
ARGB_8888格式 32位=8+8+8+8=4byte
借用格式来压缩图片是一种不错的办法。
以下是摘抄的图片魔数
图像文件头
1)1-2:(这里的数字代表的是"字",即两个字节,下同)图像文件头。0x4d42='BM',表示是Windows支持的BMP格式。(注意:查ascii表B 0x42,M0x4d,bfType 为两个字节,B为low字节,M为high字节所以bfType=0x4D42,而不是0x424D,但注意)
2)3-6:整个文件大小。4690 0000,为00009046h=36934。
3)7-8:保留,必须设置为0。
4)9-10:保留,必须设置为0。
5)11-14:从文件开始到位图数据之间的偏移量(14+40+4*(2^biBitCount))。4600 0000,为00000046h=70,上面的文件头就是35字=70字节。
位图信息头
6)15-18:位图图信息头长度。
7) 19-22:位图宽度,以像素为单位。8000 0000,为00000080h=128。
8)23-26:位图高度,以像素为单位。9000 0000,为00000090h=144。
9)27-28:位图的位面数,该值总是1。0100,为0001h=1。
10)29-30:每个像素的位数。有1(单色),4(16色),8(256色),16(64K色,高彩色),24(16M色,真彩色),32(4096M色,增强型真彩色)。1000为0010h=16。
11)31-34:压缩说明:有0(不压缩),1(RLE 8,8位RLE压缩),2(RLE 4,4位RLE压缩,3(Bitfields,位域存放)。RLE简单地说是采用像素数+像素值的方式进行压缩。T408采用的是位域存放方式,用两个字节表示一个像素,位域分配为r5b6g5。图中0300 0000为00000003h=3。
12)35-38:用字节数表示的位图数据的大小,该数必须是4的倍数,数值上等于(≥位图宽度的最小的4的倍数)×位图高度×每个像素位数。0090 0000为00009000h=80×90×2h=36864。
13)39-42:用象素/米表示的水平分辨率。A00F 0000为0000 0FA0h=4000。
14)43-46:用象素/米表示的垂直分辨率。A00F 0000为0000 0FA0h=4000。
15)47-50:位图使用的颜色索引数。设为0的话,则说明使用所有调色板项。
16)51-54:对图象显示有重要影响的颜色索引的数目。如果是0,表示都重要。