jvm比例,jvm简书
看了虚拟机(Java虚拟机的缩写)虚拟机规范,之前看类文件的描述,总是觉得很模糊,这次周末又一次看了一遍,决定写点代码分析一下,甲骨文的爪哇岛开发工具包提供了
javap,参照这个写了简单的分析类,就是为了辅助学习用,因为规范里面都是u类型的,而且是大印第安人,使用数据输入正好符合。
代码很简单,我也没有按照什么面向对象来分析,就是走一步算一步,写到哪算到哪,很多可能都重复了,望见谅,就是个练手。
看代码的时候,请参照虚拟机规范看,其实这个就是个理论,关键还是虚拟机(Java虚拟机的缩写)的实现以及应用程序接口的类库,再一次感慨一下。
注意一下,属性的分析我没写,其实也是分析字节流,实在懒的写的,以后在补上吧。整个代码就是读流,读文件内容按照预先定义的格式进行解析。
导入Java。io。数据输入流;
导入Java。io。io异常;
导入Java。io。inputstream
导入Java。文字。十进制格式;
导入Java。文字。数字格式;
公共类简单分类分析器{
静态数字格式formatter=新的十进制格式(" 00 ");
静态最终int ACC _ PUBLIC=0x0001
静态最终int ACC _ FINAL=0x0010
静态最终int ACC _ SUPER=0x0020
静态最终int ACC _ INTERFACE=0x0200
静态最终int ACC _ ABSTRACT=0x0400
静态最终int ACC _ PRIVATE=0x0002
静态最终int ACC _ PROTECTED=0x0004
静态最终int ACC _ STATIC=0x0008
静态最终int ACC _ VOLATILE=0x0040
静态最终int ACC _ TRANSIENT=0x0080
静态最终int ACC _ SYNCHRONIZED=0x0020
静态最终int ACC _ NATIVE=0x0100
静态最终int ACC _ STRICT=0x0800
静态枚举常量PoolTag {
CONSTANT_Class(7),CONSTANT_Fieldref(9),CONSTANT_Methodref(10),CONSTANT_InterfaceMethodref(
11)、常量字符串(8)、常量整数(3)、常量浮点(4)、常量长整型(
5)、常量_双精度(6)、常量_名称和Type(12)、CONSTANT_Utf8(
1);
私有(同Internationalorganizations)国际组织标记;
ConstantPoolTag(int tagN) {
this.tag=tagN
}
public int getTag() {
返回标签;
}
公共静态ConstantPoolTag getConstantPoolTag(int tagN){
开关(标签){
案例7:
返回常量_类
案例9:
返回常数_字段参考
案例10:
返回常数_方法参考
案例11:
return CONSTANT _ InterfaceMethodref;
案例8:
返回常量字符串
案例三:
返回常数_整数;
案例4:
返回常数_浮点
案例5:
返回常数_ Long
案例6:
返回常数_双精度
案例12:
返回CONSTANT _和Type
案例1:
return CONSTANT _ Utf8
默认值:
返回空
}
}
}
公共静态void main(String[] args) {
InputStream fin=simpleclassanalizer。班级。getResourceAsStream( demo。类’);
数据输入流din=新数据输入流(fin);
印刷魔术(din);
印刷版本(din);
printConstantPool(din);
printAccessFlag(din,true);
printClassName(this ,din);
printClassName(super ,din);
打印接口信息(din);
printFieldInfo(din);
打印方法信息(德国标准);
printClassAttributes(din);
}
私有静态void printClassAttributes(数据输入流din){
尝试{
//符合大印度人
int attriCnt=din。readunsignedshort();
系统。出去。println( Class Attributes: attriCnt );
for(int I=0;我归因于;i ) {
printAttributeInfo(din,I);
}
} catch (IOException e) {
e。printstacktrace();
}
}
私有静态作废打印方法信息(数据输入流din){
尝试{
//符合大印度人
int方法CNT=din。readunsignedshort();
系统。出去。println( method CNT: method CNT );
for(int I=0;一、方法CNTi ) {
printAccessFlag(din,false);
int name _ index=din。readunsignedshort();
int描述符_索引=din。readunsignedshort();
System.out.println(方法名\ t # name _ index);
System.out.println(方法描述符\t# 描述符_索引);
int attributes _ count=dinreadunsignedshort();
系统。出去。println(方法属性计数:属性_计数);
for(int j=0;j属性_计数;j ) {
printAttributeInfo(din,j);
}
}
} catch (IOException e) {
e。printstacktrace();
}
}
私有静态void打印类名(字符串名,DataInputStream din) {
尝试{
//符合大印度人
int index=din。readunsignedshort();
系统。出去。println(名称 \ t # 索引);
} catch (IOException e) {
e。printstacktrace();
}
}
私有静态void printFieldInfo(数据输入流din){
尝试{
//符合大印度人
int字段CNT=din。readunsignedshort();
系统。出去。println( field CNT: field CNT );
for(int I=0;i fieldCnti ) {
printAccessFlag(din,false);
int name _ index=din。readunsignedshort();
int描述符_索引=din。readunsignedshort();
System.out.println(字段名\ t # name _ index);
System.out.println(字段描述符\t# 描述符_索引);
int attributes _ count=dinreadunsignedshort();
系统。出去。println(字段属性计数:属性_计数);
for(int j=0;j属性_计数;j ) {
printAttributeInfo(din,j);
}
}
} catch (IOException e) {
e。printstacktrace();
}
}
//未实现
私有静态void打印属性信息(数据输入流din,int j) {
//方法
尝试{
//符合大印度人
int属性名称索引=din。readunsignedshort();
系统。出去。println( attributename index:# attribute _ name _ index);
//u4 - int可以替换?
int属性长度=din。readint();
字节[] tmp=新字节[属性长度];
晚餐。readly(tmp);
//系统。出去。println(属性信息:新字符串(tmp));
//现在不分析,以后补好
} catch (IOException e) {
e。printstacktrace();
}
}
私有静态作废打印接口信息(数据输入流din){
尝试{
//符合大印度人
int接口中心=din。readunsignedshort();
系统。出去。println(‘接口中心:‘接口中心’);
for(int I=0;一。界面客户端;i ) {
系统。出去。println(接口:\ t # din。readunsignedshort());
}
} catch (IOException e) {
e。printstacktrace();
}
}
私有静态void printAccessFlag(数据输入流din,
布尔类接口){
尝试{
int访问标志=din。readunsignedshort();
系统。出去。print( AccessFlagInfo:);
StringBuilder buf=new StringBuilder();
if ((accessFlag ACC_FINAL) 0) {
buf。append(“Final”);
}
if (classOrInterface) {
if ((accessFlag ACC_SUPER) 0) {
//设置
buf。追加( Super );
}
if((访问标志ACC _ INTERFACE)0){
buf。append(“接口”);
}否则{
buf。append( Class );
}
}
if ((accessFlag ACC_ABSTRACT) 0) {
buf。append(“Abstract”);
}
//字段/方法/类必须是以下之一
if ((accessFlag ACC_PUBLIC) 0) {
buf。append(“Public”);
} else if((访问标志ACC _ PRIVATE)0){
buf。append(“Private”);
} else if((访问标志ACC _ PROTECTED)0){
buf。追加( Protected );
}否则{
buf。追加( Package );
}
如果(!classOrInterface) {
//字段
if ((accessFlag ACC_STATIC) 0) {
buf。append(“Static”);
}
if ((accessFlag ACC_VOLATILE) 0) {
buf。append( Volatile );
}
if((访问标志ACC _ TRANSIENT)0){
buf。append(“瞬态”);
}
if((访问标志ACC _ SYNCHRONIZED)0){
buf。追加( Synchronized );
}
if ((accessFlag ACC_NATIVE) 0) {
buf。append(“本机”);
}
if ((accessFlag ACC_STRICT) 0) {
buf。append( FP strict );
}
}
系统。出去。println(buf。tostring().trim());
} catch (IOException e) {
e。printstacktrace();
}
}
私有静态void printConstantPool(数据输入流din){
尝试{
//符合大印度人
int poolSize=din。readunsignedshort();
系统。出去。println( ConstantPoolSize: poolSize );
for(int I=0;我池大小-1;i ) {
字节标签=din。读取字节();
readConstPool(constantpooltag。getconstantpooltag(标签),din,
I 1);
if((ConstantPoolTag。getconstantpooltag(tag)==ConstantPoolTag .常数_双精度)
(ConstantPoolTag。getconstantpooltag(tag)==ConstantPoolTag .CONSTANT_Long)) {
我;
}
}
} catch (IOException e) {
e。printstacktrace();
}
}
私有静态void read const pool(ConstantPoolTag ConstantPoolTag,
DataInputStream din,int index) {
//只处理几种情况
尝试{
开关(constantPoolTag) {
情况常量_Class:
int name _ index=din。readunsignedshort();
系统。出去。println( # index = constantPoolTag
\ t名称索引:# name _ index);
打破;
案例常量_Utf8:
//readUtf也读取长度
系统。出去。println( # index = constantPoolTag \ t
晚餐。read utf());
打破;
案例常数_和类型:
名称索引=din。readunsignedshort();
int描述符_索引=din。readunsignedshort();
系统。出去。println( # index = constantPoolTag \ t
# 名称索引:# 描述符索引);
打破;
案例常量_字符串:
名称索引=din。readunsignedshort();
系统。出去。println( # index = constantPoolTag \ t
# 名称索引);
打破;
case CONSTANT_Methodref:
案例常量_Fieldref:
情况常量_InterfaceMethodref:
名称索引=din。readunsignedshort();
描述符索引=din。readunsignedshort();
系统。出去。println( # index = constantPoolTag \ t
# 名称索引:# 描述符索引);
打破;
情况常量_整数:
int val=din。readint();
系统。出去。println( # index = constantPoolTag \ t
v= val);
打破;
案例常量_浮点:
浮点fval=din。读取float();
系统。出去。println( # index = constantPoolTag \ t
Fv= fval);
打破;
情况常量_Double:
double dval=din。read double();
系统。出去。println( # index = constantPoolTag \ t
dv= dval);
打破;
情况常量_Long:
long lval=din。read long();
系统。出去。println( # index = constantPoolTag \ t
LV= lval);
打破;
默认值:
返回;
}
} catch (IOException e) {
e。printstacktrace();
}
}
私有静态作废打印版本(数据输入流din){
尝试{
int版本=din。readint();
系统。出去。打印(版本:);
for(int I=2;我我- ) {
系统输出打印(格式化程序。格式((版本(2-I)* 16)0x ffff));
System.out.print(i==2?.: );
}
系统。出去。println();
} catch (IOException e) {
e。printstacktrace();
}
}
私有静态void print magic(数据输入流din){
尝试{
int magic=din。readint();
System.out.print(魔串:);
for(int I=0;i i ) {
系统输出打印(整数。toHexString((magic(3-I)* 8)0x ff));
}
系统。出去。println();
} catch (IOException e) {
e。printstacktrace();
}
}
}
写完之后,我发现谷歌上一个国人写的分析常量池的代码,当然是他整体代码的一部分,我觉得写的很好,好在结构很清晰,其实思路都是一样,所以说当思路一样的时候,人的解决方案建模能力能够看出人的水平,我还是建模和模式能力差啊。代码也附上,有兴趣的可以看看,版权不在我,望周知:
导入Java。io。数据输入流;
导入Java。util。ArrayList
导入Java。util。hashmap
publicsclassconsantpool {
静态int count=0;
静态intindex=1;
staticArrayList对象l=新数组列表对象
staticbytetag _ main
publicstaticHashMap Integer,String consant pool=new hashmap Integer,String
publistativoidparseconstant _ pool(int count 2,DataInputStreamin)
抛出异常{
计数=计数2-1;
系统。出去。println( startparsecount= count);
while(count - 0){
tag _ main=in。读取字节();
CONSTANT _ clasc=new CONSTANT _ Class();
CONSTANT _ Utf8 _ infou=new CONSTANT _ Utf8 _ info();
CONSTANT _ field ref _ infof=new CONSTANT _ field ref _ info();
CONSTANT _ method ref _ infom=new CONSTANT _ method ref _ info();
CONSTANT _ InterfaceMethodref _ info itf=new CONSTANT _ InterfaceMethodref _ info();
CONSTANT _ String _ infos=new CONSTANT _ String _ info();
CONSTANT _ Integer _ infoi=new CONSTANT _ Integer _ info();
CONSTANT _ Float _ infofl=new CONSTANT _ Float _ info();
CONSTANT _ Long _ infol=new CONSTANT _ Long _ info();
CONSTANT _ Double _ infod=new CONSTANT _ Double _ info();
CONSTANT _ name and type _ infon=new CONSTANT _ name and type _ info();
c。解析(in);
你。解析(in);
f。解析(in);
m。解析(in);
itf。解析(in);
s。解析(in);
I .解析(in);
fl。解析(in);
我。解析(in);
d。解析(in);
不知道。解析(in);
}
}
}
interfaceconstant{
void parse(data inputstreamin)引发异常;
}
类constant _ class实现常量{
staticbytetag=0x07
简称_索引;
@覆盖
publicvoidparse(数据输入流)抛出异常{
if(tag==ConsantPool.tag_main){
name _ index=in。read short();
ConsantPool.l.add(这个);
系统。出去。打印(consant池。索引“”);
系统。出去。println( parse constant _ class name _ index=
name _ index);
}
}
}
类constant _ Utf8 _ info实现常量{
staticbytetag=0x01
短长度;
串值
@覆盖
publicvoidparse(数据输入流)抛出异常{
if(tag==ConsantPool.tag_main){
长度=英寸。read short();
byte[]b=新字节[长度];
英寸改为(b);
value=新字符串(b);
康森特游泳池。康森特游泳池。放(康桑池。指数,数值);//添加到常量池
系统。出去。打印(consant池。索引“”);
系统。出去。println( parse constant _ Utf8 _ info= value);
}
}
}
类constant _ String _ info实现常量{
staticbytetag=0x08
短字符串索引
@覆盖
publicvoidparse(数据输入流)抛出异常{
if(tag==ConsantPool.tag_main){
string _ index=inread short();
系统。出去。打印(consant池。索引“”);
系统。出去。println( parse constant _ String _ info String _ index=
string _ index);
}
}
}
类constant _ field ref _ info实现常量{
staticbytetag=0x9
shortclass _索引
简称和类型索引;
@覆盖
publicvoidparse(数据输入流)抛出异常{
if(tag==ConsantPool.tag_main){
class _ index=in。read short();
名称和类型索引=in。read short();
系统。出去。打印(consant池。索引“”);
系统。出去。println( parse constant _ field ref _ info class _ index=
class _ index name _ and _ type _ index=
名称和类型索引);
}
}
}
类constant _ method ref _ info实现常量{
staticbytetag=0x0A
shortclass _索引
简称和类型索引;
@覆盖
publicvoidparse(数据输入流)抛出异常{
if(tag==ConsantPool.tag_main){
class _ index=in。read short();
名称和类型索引=in。read short();
系统。出去。打印(consant池。索引“”);
系统。出去。println( parse constant _ method ref _ info class _ index=
class _ index name _ and _ type _ index=
名称和类型索引);
}
}
}
类constant _ interface方法ref _ info实现常量{
staticbytetag=0x0B
shortclass _索引
简称和类型索引;
@覆盖
publicvoidparse(数据输入流)抛出异常{
if(tag==ConsantPool.tag_main){
class _ index=in。read short();
名称和类型索引=in。read short();
系统。出去。打印(consant池。索引“”);
System.out。println( parse constant _ interface method ref _ info class _ index=
类别索引
名称和类型索引=
名称和类型索引);
}
}
}
类constant _ Integer _ info实现常量{
staticbytetag=0x03
intbytes
@覆盖
publicvoidparse(数据输入流)抛出异常{
if(tag==ConsantPool.tag_main){
字节=英寸。readint();
系统。出去。打印(consant池。索引“”);
系统。出去。println( parse constant _ Integer _ info int= bytes);
}
}
}
类constant _ Float _ info实现常量{
staticbytetag=0x04
浮动字节;
@覆盖
publicvoidparse(数据输入流)抛出异常{
if(tag==ConsantPool.tag_main){
字节=英寸。读取float();
系统。出去。打印(consant池。索引“”);
系统。出去。println( parse constant _ Float _ info Float= bytes);
}
}
}
类constant _ Long _ info实现常量{
staticbytetag=0x05
纵向的
@覆盖
publicvoidparse(数据输入流)抛出异常{
if(tag==ConsantPool.tag_main){
l=英寸。read long();
系统。出去。打印(consant池。索引“”);
系统。出去。println( parse constant _ Long _ infolong= l);
}
}
}
类constant _ Double _ info实现常量{
staticbytetag=0x06
双值
@覆盖
publicvoidparse(数据输入流)抛出异常{
if(tag==ConsantPool.tag_main){
值=英寸。read double();
系统。出去。打印(consant池。索引“”);
系统。出去。println( parse constant _ Double _ info Double= value);
}
}
}
类constant _ name和type _ info实现常量{
staticbytetag=0x0C
简称_索引;
短描述符_索引;
@覆盖
publicvoidparse(数据输入流)抛出异常{
if(tag==ConsantPool.tag_main){
name _ index=in。read short();
描述符索引=in。read short();
系统。出去。打印(consant池。索引“”);
系统。出去。println( parse constant _ name and type _ infoname _ index=
name _ index descriptor _ index= descriptor _ index);
}
}
}
具体大家可以google Java ConstantPool就能在第一页看见这个代码,托管在谷歌代码下面的。
附注:修改了几个Bug,添加了对所有常量池的支持,另外我贴的别人的代码,貌似和我之前的代码犯一个毛病,就是解析长的和两倍时候,没有增加常量池索引。
所有的8字节常量在类文件的常量池表中占据两个条目。如果常数_长信息或常数双精度信息结构是常量池表中索引n处的项,则池中的下一个可用项位于索引氮气处常量池索引n 1必须有效,但被认为是不可用的。2
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。