欢迎来到天天文库
浏览记录
ID:30778695
大小:144.81 KB
页数:10页
时间:2019-01-03
《jvm之用java解析class文件》由会员上传分享,免费在线阅读,更多相关内容在工程资料-天天文库。
1、JVM之用Java解析class文件■■11■■刖台:身为一个Java程序员,怎么能不了解JVM呢,倘若想学习JVM,那就又必须要了解Class文件,Class之于虚拟机,就如鱼之于水,虚拟机因为Class而有了生命。《深入理解java虚拟机》中花了一整个章节来讲解Class文件,可是看完后,一直都还是迷迷糊糊,似懂非懂。正好前段时间看见一本书很不错:《自己动手写Java虚拟机》,作者利用go语言实现了一个简单的JVM,虽然没有完整实现JVM的所有功能,但是对于一些对JVM稍感兴趣的人来说,可读性还是很高的。作者讲解的很详细,每
2、个过程都分为了一章,其中一部分就是讲解如何解析Class文件。这本书不太厚,很快就读完了,读完后,收获颇丰。但是纸上得来终觉浅,绝知此事要躬行,我便尝试着自己解析Class文件。go语言虽然很优秀,但是终究不熟练,尤其是不太习惯其把类型放在变量之后的语法,还是老老实实用java吧。话不多说,先贴出项目地址:https://github.com/HalfStackDeveloper/ClassReaderClass文件什么是Class文件?java之所以能够实现跨平台,便在于其编译阶段不是将代码直接编译为平台相关的机器语言,而是先
3、编译成二进制形式的java字节码,放在Class文件之中,虚拟机再加载Class文件,解析出程序运行所需的内容。每个类都会被编译成一个单独的class文件,内部类也会作为一个独立的类,生成自己的class.基本结构随便找到一个class文件,用SublimeText打开是这样的:是不是一脸懵逼,不过java虚拟机规范中给出了class文件的基本格式,只要按照这个格式去解析就可以了:ClassFile{u4magic;u2minor_version;u2major_version;u2constant_pool_count;cp_
4、infoconstant_pool[constant_pool_count-1];u2access_flags;u2this_class;u2superclass;u2interfaces_count;u2interfaces[interfaces_count];u2fields_count;field_infofields[fields_count];u2methods_count;method_infomethods[methods_count];u2attributes_count;attribute_infoattrib
5、utes[attributes_count];}~"ClassFile中的字段类型有ul、u2、u4,这是什么类型呢?其实很简单,就是分别表示1个字节,2个字节和4个字节。开头四个字节为:magic,是用来唯一标识文件格式的,一般被称作magicnumber(魔数)这样虚拟机才能识别出所加载的文件是否是class格式‘class文件的魔数为cafebabe。不只是class文件,基本上大部分文件都有魔数,用来标识自己的格式。接下来的部分主要是class文件的一些信息,如常量池、类访问标志、父类、接口信息、字段、方法等,具体的信息
6、可参考《Java虚拟机规范》。解析字段类型上面说到ClassFile中的字段类型有ul、u2、u4,分别表示1个字节,2个字节和4个字节的无符号整数。java中short、int、long分别为2、4、8个字节的有符号整数,去掉符号位,刚好可以用来表示ul.u2、u4opublicclassU1{publicstaticshortread(InputStreaminputstream){byte[]bytes=newbyte[l];try{inputstrearn・read(bytes);}catch(IOExceptione)
7、{e.printStackTrace();}shortvalue=(short)(bytes[0]&0xFF);returnvalue;}}publicclassU2{publicstaticintread(InputStrearninputstream){byte[]bytes=newbyte[2];try{inputstrearn・read(bytes);}catch(IOExceptione){e.printStackTrace();}intnum=0;for(inti=0;i8、<=8;num9、=(bytes[i]&0xff);}returnnum;}}publicclassU4{publicstaticlongread(InputStreaminputStream){byte[]bytes=newbyte[4];try{inputst
8、<=8;num
9、=(bytes[i]&0xff);}returnnum;}}publicclassU4{publicstaticlongread(InputStreaminputStream){byte[]bytes=newbyte[4];try{inputst
此文档下载收益归作者所有