package sun.tools.javap;
import java.util.*;
import java.io.*;
/**
* Central data repository of the Java Disassembler.
* Stores all the information in java class file.
*
* @author Sucheta Dambalkar (Adopted code from jdis)
*/
public class ClassData implements RuntimeConstants {
private int magic;
private int minor_version;
private int major_version;
private int cpool_count;
private Object cpool[];
private int access;
private int this_class = 0;;
private int super_class;
private int interfaces_count;
private int[] interfaces = new int[0];;
private int fields_count;
private FieldData[] fields;
private int methods_count;
private MethodData[] methods;
private InnerClassData[] innerClasses;
private int attributes_count;
private AttrData[] attrs;
private String classname;
private String superclassname;
private int source_cpx=0;
private byte tags[];
private Hashtable indexHashAscii = new Hashtable();
private String pkgPrefix="";
private int pkgPrefixLen=0;
/**
* Read classfile to disassemble.
*/
public ClassData(InputStream infile){
try{
this.read(new DataInputStream(infile));
}catch (FileNotFoundException ee) {
error("cant read file");
}catch (Error ee) {
ee.printStackTrace();
error("fatal error");
} catch (Exception ee) {
ee.printStackTrace();
error("fatal exception");
}
}
/**
* Reads and stores class file information.
*/
public void read(DataInputStream in) throws IOException {
// Read the header
magic = in.readInt();//先读取魔法数,值为0xcafebabe,以此来区分是否为java class文件
if (magic != JAVA_MAGIC) {
throw new ClassFormatError("wrong magic: " +
toHex(magic) + ", expected " +
toHex(JAVA_MAGIC));
}
minor_version = in.readShort();
major_version = in.readShort();
if (major_version != JAVA_VERSION) {//class文件版本号,现在我的jdk版本里面配置的是45,JAVA_MINOR_VERSION为3
}
// Read the constant pool
readCP(in);//读取常量池
access = in.readUnsignedShort();//访问标识字段,标识是否为public,final,abstract等很多访问控制
this_class = in.readUnsignedShort();//类的常量池索引项
super_class = in.readUnsignedShort();//父类的常量池索引项
//Read interfaces.
interfaces_count = in.readUnsignedShort();//接口个数
if(interfaces_count > 0){
interfaces = new int[interfaces_count];
}
for (int i = 0; i < interfaces_count; i++) {
interfaces[i]=in.readShort();//每个接口的常量池索引项
}
// Read the fields
readFields(in);//读取类字段
// Read the methods
readMethods(in);//读取类的方法信息
// Read the attributes
attributes_count = in.readUnsignedShort(); //读取类的属性信息
attrs=new AttrData[attributes_count];
for (int k = 0; k < attributes_count; k++) {
int name_cpx=in.readUnsignedShort();
if (getTag(name_cpx)==CONSTANT_UTF8
&& getString(name_cpx).equals("SourceFile")
){ if (in.readInt()!=2)
throw new ClassFormatError("invalid attr length");
source_cpx=in.readUnsignedShort();
AttrData attr=new AttrData(this);
attr.read(name_cpx);
attrs[k]=attr;
} else if (getTag(name_cpx)==CONSTANT_UTF8
&& getString(name_cpx).equals("InnerClasses")
){ int length=in.readInt();
int num=in.readUnsignedShort();
if (2+num*8 != length)
throw new ClassFormatError("invalid attr length");
innerClasses=new InnerClassData[num];
for (int j = 0; j < num; j++) {
InnerClassData innerClass=new InnerClassData(this);
innerClass.read(in);
innerClasses[j]=innerClass;
}
AttrData attr=new AttrData(this);
attr.read(name_cpx);
attrs[k]=attr;
} else {
AttrData attr=new AttrData(this);
attr.read(name_cpx, in);
attrs[k]=attr;
}
}
in.close();
} // end ClassData.read()
/**
* Reads and stores constant pool info.
*/
void readCP(DataInputStream in) throws IOException {
cpool_count = in.readUnsignedShort();
tags = new byte[cpool_count];
cpool = new Object[cpool_count];
for (int i = 1; i < cpool_count; i++) {
byte tag = in.readByte();
switch(tags[i] = tag) {
case CONSTANT_UTF8:
String str=in.readUTF();
indexHashAscii.put(cpool[i] = str, new Integer(i));
break;
case CONSTANT_INTEGER:
cpool[i] = new Integer(in.readInt());
break;
case CONSTANT_FLOAT:
cpool[i] = new Float(in.readFloat());
break;
case CONSTANT_LONG:
cpool[i++] = new Long(in.readLong());
break;
case CONSTANT_DOUBLE:
cpool[i++] = new Double(in.readDouble());
break;
case CONSTANT_CLASS:
case CONSTANT_STRING:
cpool[i] = new CPX(in.readUnsignedShort());
break;
case CONSTANT_FIELD:
case CONSTANT_METHOD:
case CONSTANT_INTERFACEMETHOD:
case CONSTANT_NAMEANDTYPE:
cpool[i] = new CPX2(in.readUnsignedShort(), in.readUnsignedShort());
break;
case 0:
default:
throw new ClassFormatError("invalid constant type: " + (int)tags[i]);
}
}
}
/**
* Reads and strores field info.
*/
protected void readFields(DataInputStream in) throws IOException {
int fields_count = in.readUnsignedShort();
fields=new FieldData[fields_count];
for (int k = 0; k < fields_count; k++) {
FieldData field=new FieldData(this);
field.read(in);
fields[k]=field;
}
}
/**
* Reads and strores Method info.
*/
protected void readMethods(DataInputStream in) throws IOException {
int methods_count = in.readUnsignedShort();
methods=new MethodData[methods_count];
for (int k = 0; k < methods_count ; k++) {
MethodData method=new MethodData(this);
method.read(in);
methods[k]=method;
}
}
/**
* get a string
*/
public String getString(int n) {
return (n == 0) ? null : (String)cpool[n];
}
/**
* get the type of constant given an index
*/
public byte getTag(int n) {
try{
return tags[n];
} catch (ArrayIndexOutOfBoundsException e) {
return (byte)100;
}
}
static final String hexString="0123456789ABCDEF";
public static char hexTable[]=hexString.toCharArray();
static String toHex(long val, int width) {
StringBuffer s = new StringBuffer();
for (int i=width-1; i>=0; i--)
s.append(hexTable[((int)(val>>(4*i)))&0xF]);
return "0x"+s.toString();
}
static String toHex(long val) {
int width;
for (width=16; width>0; width--) {
if ((val>>(width-1)*4)!=0) break;
}
return toHex(val, width);
}
static String toHex(int val) {
int width;
for (width=8; width>0; width--) {
if ((val>>(width-1)*4)!=0) break;
}
return toHex(val, width);
}
public void error(String msg) {
System.err.println("ERROR:" +msg);
}
/**
* Returns the name of this class.
*/
public String getClassName() {
String res=null;
if (this_class==0) {
return res;
}
int tcpx;
try {
if (tags[this_class]!=CONSTANT_CLASS) {
return res; //"<CP["+cpx+"] is not a Class> ";
}
tcpx=((CPX)cpool[this_class]).cpx;
} catch (ArrayIndexOutOfBoundsException e) {
return res; // "#"+cpx+"// invalid constant pool index";
} catch (Throwable e) {
return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
}
try {
return (String)(cpool[tcpx]);
} catch (ArrayIndexOutOfBoundsException e) {
return res; // "class #"+scpx+"// invalid constant pool index";
} catch (ClassCastException e) {
return res; // "class #"+scpx+"// invalid constant pool reference";
} catch (Throwable e) {
return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
}
}
/**
* Returns the name of class at perticular index.
*/
public String getClassName(int cpx) {
String res="#"+cpx;
if (cpx==0) {
return res;
}
int scpx;
try {
if (tags[cpx]!=CONSTANT_CLASS) {
return res; //"<CP["+cpx+"] is not a Class> ";
}
scpx=((CPX)cpool[cpx]).cpx;
} catch (ArrayIndexOutOfBoundsException e) {
return res; // "#"+cpx+"// invalid constant pool index";
} catch (Throwable e) {
return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
}
res="#"+scpx;
try {
return (String)(cpool[scpx]);
} catch (ArrayIndexOutOfBoundsException e) {
return res; // "class #"+scpx+"// invalid constant pool index";
} catch (ClassCastException e) {
return res; // "class #"+scpx+"// invalid constant pool reference";
} catch (Throwable e) {
return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
}
}
/**
* Returns true if it is a class
*/
public boolean isClass() {
if((access & ACC_INTERFACE) == 0) return true;
return false;
}
/**
* Returns true if it is a interface.
*/
public boolean isInterface(){
if((access & ACC_INTERFACE) != 0) return true;
return false;
}
/**
* Returns true if this member is public, false otherwise.
*/
public boolean isPublic(){
return (access & ACC_PUBLIC) != 0;
}
/**
* Returns the access of this class or interface.
*/
public String[] getAccess(){
Vector v = new Vector();
if ((access & ACC_PUBLIC) !=0) v.addElement("public");
if ((access & ACC_FINAL) !=0) v.addElement("final");
if ((access & ACC_ABSTRACT) !=0) v.addElement("abstract");
String[] accflags = new String[v.size()];
v.copyInto(accflags);
return accflags;
}
/**
* Returns list of innerclasses.
*/
public InnerClassData[] getInnerClasses(){
return innerClasses;
}
/**
* Returns list of attributes.
*/
public AttrData[] getAttributes(){
return attrs;
}
/**
* Returns true if superbit is set.
*/
public boolean isSuperSet(){
if ((access & ACC_SUPER) !=0) return true;
return false;
}
/**
* Returns super class name.
*/
public String getSuperClassName(){
String res=null;
if (super_class==0) {
return res;
}
int scpx;
try {
if (tags[super_class]!=CONSTANT_CLASS) {
return res; //"<CP["+cpx+"] is not a Class> ";
}
scpx=((CPX)cpool[super_class]).cpx;
} catch (ArrayIndexOutOfBoundsException e) {
return res; // "#"+cpx+"// invalid constant pool index";
} catch (Throwable e) {
return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
}
try {
return (String)(cpool[scpx]);
} catch (ArrayIndexOutOfBoundsException e) {
return res; // "class #"+scpx+"// invalid constant pool index";
} catch (ClassCastException e) {
return res; // "class #"+scpx+"// invalid constant pool reference";
} catch (Throwable e) {
return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
}
}
/**
* Returns list of super interfaces.
*/
public String[] getSuperInterfaces(){
String interfacenames[] = new String[interfaces.length];
int interfacecpx = -1;
for(int i = 0; i < interfaces.length; i++){
interfacecpx=((CPX)cpool[interfaces[i]]).cpx;
interfacenames[i] = (String)(cpool[interfacecpx]);
}
return interfacenames;
}
/**
* Returns string at prticular constant pool index.
*/
public String getStringValue(int cpoolx) {
try {
return ((String)cpool[cpoolx]);
} catch (ArrayIndexOutOfBoundsException e) {
return "//invalid constant pool index:"+cpoolx;
} catch (ClassCastException e) {
return "//invalid constant pool ref:"+cpoolx;
}
}
/**
* Returns list of field info.
*/
public FieldData[] getFields(){
return fields;
}
/**
* Returns list of method info.
*/
public MethodData[] getMethods(){
return methods;
}
/**
* Returns constant pool entry at that index.
*/
public CPX2 getCpoolEntry(int cpx){
return ((CPX2)(cpool[cpx]));
}
public Object getCpoolEntryobj(int cpx){
return (cpool[cpx]);
}
/**
* Returns index of this class.
*/
public int getthis_cpx(){
return this_class;
}
public String TagString (int tag) {
String res=Tables.tagName(tag);
if (res==null) return "BOGUS_TAG:"+tag;
return res;
}
/**
* Returns string at that index.
*/
public String StringValue(int cpx) {
if (cpx==0) return "#0";
int tag;
Object x;
String suffix="";
try {
tag=tags[cpx];
x=cpool[cpx];
} catch (IndexOutOfBoundsException e) {
return "<Incorrect CP index:"+cpx+">";
}
if (x==null) return "<NULL>";
switch (tag) {
case CONSTANT_UTF8: {
StringBuffer sb=new StringBuffer();
String s=(String)x;
for (int k=0; k<s.length(); k++) {
char c=s.charAt(k);
switch (c) {
case '\t': sb.append('\\').append('t'); break;
case '\n': sb.append('\\').append('n'); break;
case '\r': sb.append('\\').append('r'); break;
case '\"': sb.append('\\').append('\"'); break;
default: sb.append(c);
}
}
return sb.toString();
}
case CONSTANT_DOUBLE: {
Double d=(Double)x;
String sd=d.toString();
return sd+"d";
}
case CONSTANT_FLOAT: {
Float f=(Float)x;
String sf=(f).toString();
return sf+"f";
}
case CONSTANT_LONG: {
Long ln = (Long)x;
return ln.toString()+'l';
}
case CONSTANT_INTEGER: {
Integer in = (Integer)x;
return in.toString();
}
case CONSTANT_CLASS:
return javaName(getClassName(cpx));
case CONSTANT_STRING:
return StringValue(((CPX)x).cpx);
case CONSTANT_FIELD:
case CONSTANT_METHOD:
case CONSTANT_INTERFACEMETHOD:
//return getShortClassName(((CPX2)x).cpx1)+"."+StringValue(((CPX2)x).cpx2);
return javaName(getClassName(((CPX2)x).cpx1))+"."+StringValue(((CPX2)x).cpx2);
case CONSTANT_NAMEANDTYPE:
return getName(((CPX2)x).cpx1)+":"+StringValue(((CPX2)x).cpx2);
default:
return "UnknownTag"; //TBD
}
}
/**
* Returns resolved java type name.
*/
public String javaName(String name) {
if( name==null) return "null";
int len=name.length();
if (len==0) return "\"\"";
int cc='/';
fullname: { // xxx/yyy/zzz
int cp;
for (int k=0; k<len; k += Character.charCount(cp)) {
cp=name.codePointAt(k);
if (cc=='/') {
if (!Character.isJavaIdentifierStart(cp)) break fullname;
} else if (cp!='/') {
if (!Character.isJavaIdentifierPart(cp)) break fullname;
}
cc=cp;
}
return name;
}
return "\""+name+"\"";
}
public String getName(int cpx) {
String res;
try {
return javaName((String)cpool[cpx]); //.replace('/','.');
} catch (ArrayIndexOutOfBoundsException e) {
return "<invalid constant pool index:"+cpx+">";
} catch (ClassCastException e) {
return "<invalid constant pool ref:"+cpx+">";
}
}
/**
* Returns unqualified class name.
*/
public String getShortClassName(int cpx) {
String classname=javaName(getClassName(cpx));
pkgPrefixLen=classname.lastIndexOf("/")+1;
if (pkgPrefixLen!=0) {
pkgPrefix=classname.substring(0,pkgPrefixLen);
if (classname.startsWith(pkgPrefix)) {
return classname.substring(pkgPrefixLen);
}
}
return classname;
}
/**
* Returns source file name.
*/
public String getSourceName(){
return getName(source_cpx);
}
/**
* Returns package name.
*/
public String getPkgName(){
String classname=getClassName(this_class);
pkgPrefixLen=classname.lastIndexOf("/")+1;
if (pkgPrefixLen!=0) {
pkgPrefix=classname.substring(0,pkgPrefixLen);
return("package "+pkgPrefix.substring(0,pkgPrefixLen-1)+";\n");
}else return null;
}
/**
* Returns total constant pool entry count.
*/
public int getCpoolCount(){
return cpool_count;
}
public String StringTag(int cpx) {
byte tag=0;
String str=null;
try {
if (cpx==0) throw new IndexOutOfBoundsException();
tag=tags[cpx];
return TagString(tag);
} catch (IndexOutOfBoundsException e) {
str="Incorrect CP index:"+cpx;
}
return str;
}
/**
* Returns minor version of class file.
*/
public int getMinor_version(){
return minor_version;
}
/**
* Returns major version of class file.
*/
public int getMajor_version(){
return major_version;
}
public static void main(String[] args) throws FileNotFoundException{
System.out.println(new ClassData(new FileInputStream(new File("E:\\logs\\Example.class"))));
}
}
读取类的field信息的类:
package sun.tools.javap;
import java.util.*;
import java.io.*;
/**
* Strores field data informastion.
*
* @author Sucheta Dambalkar (Adopted code from jdis)
*/
public class FieldData implements RuntimeConstants {
ClassData cls;
int access;
int name_index;
int descriptor_index;
int attributes_count;
int value_cpx=0;
boolean isSynthetic=false;
boolean isDeprecated=false;
Vector attrs;
public FieldData(ClassData cls){
this.cls=cls;
}
/**
* Read and store field info.
*/
public void read(DataInputStream in) throws IOException {
access = in.readUnsignedShort();
name_index = in.readUnsignedShort();
descriptor_index = in.readUnsignedShort();
// Read the attributes
int attributes_count = in.readUnsignedShort();
attrs=new Vector(attributes_count);
for (int i = 0; i < attributes_count; i++) {
int attr_name_index=in.readUnsignedShort();
if (cls.getTag(attr_name_index)!=CONSTANT_UTF8) continue;
String attr_name=cls.getString(attr_name_index);
if (attr_name.equals("ConstantValue")){
if (in.readInt()!=2)
throw new ClassFormatError("invalid ConstantValue attr length");
value_cpx=in.readUnsignedShort();
AttrData attr=new AttrData(cls);
attr.read(attr_name_index);
attrs.addElement(attr);
} else if (attr_name.equals("Synthetic")){
if (in.readInt()!=0)
throw new ClassFormatError("invalid Synthetic attr length");
isSynthetic=true;
AttrData attr=new AttrData(cls);
attr.read(attr_name_index);
attrs.addElement(attr);
} else if (attr_name.equals("Deprecated")){
if (in.readInt()!=0)
throw new ClassFormatError("invalid Synthetic attr length");
isDeprecated = true;
AttrData attr=new AttrData(cls);
attr.read(attr_name_index);
attrs.addElement(attr);
} else {
AttrData attr=new AttrData(cls);
attr.read(attr_name_index, in);
attrs.addElement(attr);
}
}
} // end read
/**
* Returns access of a field.
*/
public String[] getAccess(){
Vector v = new Vector();
if ((access & ACC_PUBLIC) !=0) v.addElement("public");
if ((access & ACC_PRIVATE) !=0) v.addElement("private");
if ((access & ACC_PROTECTED) !=0) v.addElement("protected");
if ((access & ACC_STATIC) !=0) v.addElement("static");
if ((access & ACC_FINAL) !=0) v.addElement("final");
if ((access & ACC_VOLATILE) !=0) v.addElement("volatile");
if ((access & ACC_TRANSIENT) !=0) v.addElement("transient");
String[] accflags = new String[v.size()];
v.copyInto(accflags);
return accflags;
}
/**
* Returns name of a field.
*/
public String getName(){
return cls.getStringValue(name_index);
}
/**
* Returns internal signature of a field
*/
public String getInternalSig(){
return cls.getStringValue(descriptor_index);
}
/**
* Returns java type signature of a field.
*/
public String getType(){
return new TypeSignature(getInternalSig()).getFieldType();
}
/**
* Returns true if field is synthetic.
*/
public boolean isSynthetic(){
return isSynthetic;
}
/**
* Returns true if field is deprecated.
*/
public boolean isDeprecated(){
return isDeprecated;
}
/**
* Returns index of constant value in cpool.
*/
public int getConstantValueIndex(){
return (value_cpx);
}
/**
* Returns list of attributes of field.
*/
public Vector getAttributes(){
return attrs;
}
}
读取类的方法
import java.util.*;
import java.io.*;
import static sun.tools.javap.RuntimeConstants.*;
/**
* Strores method data informastion.
*
* @author Sucheta Dambalkar (Adopted code from jdis)
*/
public class MethodData {
ClassData cls;
int access;
int name_index;
int descriptor_index;
int attributes_count;
byte[] code;
Vector exception_table = new Vector(0);
Vector lin_num_tb = new Vector(0);
Vector loc_var_tb = new Vector(0);
StackMapTableData[] stackMapTable;
StackMapData[] stackMap;
int[] exc_index_table=null;
Vector attrs=new Vector(0);
Vector code_attrs=new Vector(0);
int max_stack, max_locals;
boolean isSynthetic=false;
boolean isDeprecated=false;
public MethodData(ClassData cls){
this.cls=cls;
}
/**
* Read method info.
*/
public void read(DataInputStream in) throws IOException {
access = in.readUnsignedShort();
name_index=in.readUnsignedShort();
descriptor_index =in.readUnsignedShort();
int attributes_count = in.readUnsignedShort();
for (int i = 0; i < attributes_count; i++) {
int attr_name_index=in.readUnsignedShort();
readAttr: {
if (cls.getTag(attr_name_index)==CONSTANT_UTF8) {
String attr_name=cls.getString(attr_name_index);
if ( attr_name.equals("Code")){
readCode (in);
AttrData attr=new AttrData(cls);
attr.read(attr_name_index);
attrs.addElement(attr);
break readAttr;
} else if ( attr_name.equals("Exceptions")){
readExceptions(in);
AttrData attr=new AttrData(cls);
attr.read(attr_name_index);
attrs.addElement(attr);
break readAttr;
} else if (attr_name.equals("Synthetic")){
if (in.readInt()!=0)
throw new ClassFormatError("invalid Synthetic attr length");
isSynthetic=true;
AttrData attr=new AttrData(cls);
attr.read(attr_name_index);
attrs.addElement(attr);
break readAttr;
} else if (attr_name.equals("Deprecated")){
if (in.readInt()!=0)
throw new ClassFormatError("invalid Synthetic attr length");
isDeprecated = true;
AttrData attr=new AttrData(cls);
attr.read(attr_name_index);
attrs.addElement(attr);
break readAttr;
}
}
AttrData attr=new AttrData(cls);
attr.read(attr_name_index, in);
attrs.addElement(attr);
}
}
}
/**
* Read code attribute info.
*/
public void readCode(DataInputStream in) throws IOException {
int attr_length = in.readInt();
max_stack=in.readUnsignedShort();
max_locals=in.readUnsignedShort();
int codelen=in.readInt();
code=new byte[codelen];
int totalread = 0;
while(totalread < codelen){
totalread += in.read(code, totalread, codelen-totalread);
}
// in.read(code, 0, codelen);
int clen = 0;
readExceptionTable(in);
int code_attributes_count = in.readUnsignedShort();
for (int k = 0 ; k < code_attributes_count ; k++) {
int table_name_index=in.readUnsignedShort();
int table_name_tag=cls.getTag(table_name_index);
AttrData attr=new AttrData(cls);
if (table_name_tag==CONSTANT_UTF8) {
String table_name_tstr=cls.getString(table_name_index);
if (table_name_tstr.equals("LineNumberTable")) {
readLineNumTable(in);
attr.read(table_name_index);
} else if (table_name_tstr.equals("LocalVariableTable")) {
readLocVarTable(in);
attr.read(table_name_index);
} else if (table_name_tstr.equals("StackMapTable")) {
readStackMapTable(in);
attr.read(table_name_index);
} else if (table_name_tstr.equals("StackMap")) {
readStackMap(in);
attr.read(table_name_index);
} else {
attr.read(table_name_index, in);
}
code_attrs.addElement(attr);
continue;
}
attr.read(table_name_index, in);
code_attrs.addElement(attr);
}
}
/**
* Read exception table info.
*/
void readExceptionTable (DataInputStream in) throws IOException {
int exception_table_len=in.readUnsignedShort();
exception_table=new Vector(exception_table_len);
for (int l = 0; l < exception_table_len; l++) {
exception_table.addElement(new TrapData(in, l));
}
}
/**
* Read LineNumberTable attribute info.
*/
void readLineNumTable (DataInputStream in) throws IOException {
int attr_len = in.readInt(); // attr_length
int lin_num_tb_len = in.readUnsignedShort();
lin_num_tb=new Vector(lin_num_tb_len);
for (int l = 0; l < lin_num_tb_len; l++) {
lin_num_tb.addElement(new LineNumData(in));
}
}
/**
* Read LocalVariableTable attribute info.
*/
void readLocVarTable (DataInputStream in) throws IOException {
int attr_len=in.readInt(); // attr_length
int loc_var_tb_len = in.readUnsignedShort();
loc_var_tb = new Vector(loc_var_tb_len);
for (int l = 0; l < loc_var_tb_len; l++) {
loc_var_tb.addElement(new LocVarData(in));
}
}
/**
* Read Exception attribute info.
*/
public void readExceptions(DataInputStream in) throws IOException {
int attr_len=in.readInt(); // attr_length in prog
int num_exceptions = in.readUnsignedShort();
exc_index_table=new int[num_exceptions];
for (int l = 0; l < num_exceptions; l++) {
int exc=in.readShort();
exc_index_table[l]=exc;
}
}
/**
* Read StackMapTable attribute info.
*/
void readStackMapTable(DataInputStream in) throws IOException {
int attr_len = in.readInt(); //attr_length
int stack_map_tb_len = in.readUnsignedShort();
stackMapTable = new StackMapTableData[stack_map_tb_len];
for (int i=0; i<stack_map_tb_len; i++) {
stackMapTable[i] = StackMapTableData.getInstance(in, this);
}
}
/**
* Read StackMap attribute info.
*/
void readStackMap(DataInputStream in) throws IOException {
int attr_len = in.readInt(); //attr_length
int stack_map_len = in.readUnsignedShort();
stackMap = new StackMapData[stack_map_len];
for (int i = 0; i<stack_map_len; i++) {
stackMap[i] = new StackMapData(in, this);
}
}
/**
* Return access of the method.
*/
public String[] getAccess(){
Vector v = new Vector();
if ((access & ACC_PUBLIC) !=0) v.addElement("public");
if ((access & ACC_PRIVATE) !=0) v.addElement("private");
if ((access & ACC_PROTECTED) !=0) v.addElement("protected");
if ((access & ACC_STATIC) !=0) v.addElement("static");
if ((access & ACC_FINAL) !=0) v.addElement("final");
if ((access & ACC_SYNCHRONIZED) !=0) v.addElement("synchronized");
if ((access & ACC_NATIVE) !=0) v.addElement("native");
if ((access & ACC_ABSTRACT) !=0) v.addElement("abstract");
if ((access & ACC_STRICT) !=0) v.addElement("strictfp");
String[] accflags = new String[v.size()];
v.copyInto(accflags);
return accflags;
}
/**
* Return name of the method.
*/
public String getName(){
return cls.getStringValue(name_index);
}
/**
* Return internal siganature of the method.
*/
public String getInternalSig(){
return cls.getStringValue(descriptor_index);
}
/**
* Return java return type signature of method.
*/
public String getReturnType(){
String rttype = (new TypeSignature(getInternalSig())).getReturnType();
return rttype;
}
/**
* Return java type parameter signature.
*/
public String getParameters(){
String ptype = (new TypeSignature(getInternalSig())).getParameters();
return ptype;
}
/**
* Return code attribute data of a method.
*/
public byte[] getCode(){
return code;
}
/**
* Return LineNumberTable size.
*/
public int getnumlines(){
return lin_num_tb.size();
}
/**
* Return LineNumberTable
*/
public Vector getlin_num_tb(){
return lin_num_tb;
}
/**
* Return LocalVariableTable size.
*/
public int getloc_var_tbsize(){
return loc_var_tb.size();
}
/**
* Return LocalVariableTable.
*/
public Vector getloc_var_tb(){
return loc_var_tb;
}
/**
* Return StackMap.
*/
public StackMapData[] getStackMap() {
return stackMap;
}
/**
* Return StackMapTable.
*/
public StackMapTableData[] getStackMapTable() {
return stackMapTable;
}
/**
* Return number of arguments of that method.
*/
public int getArgumentlength(){
return new TypeSignature(getInternalSig()).getArgumentlength();
}
/**
* Return true if method is static
*/
public boolean isStatic(){
if ((access & ACC_STATIC) !=0) return true;
return false;
}
/**
* Return max depth of operand stack.
*/
public int getMaxStack(){
return max_stack;
}
/**
* Return number of local variables.
*/
public int getMaxLocals(){
return max_locals;
}
/**
* Return exception index table in Exception attribute.
*/
public int []get_exc_index_table(){
return exc_index_table;
}
/**
* Return exception table in code attributre.
*/
public Vector getexception_table(){
return exception_table;
}
/**
* Return method attributes.
*/
public Vector getAttributes(){
return attrs;
}
/**
* Return code attributes.
*/
public Vector getCodeAttributes(){
return code_attrs;
}
/**
* Return true if method id synthetic.
*/
public boolean isSynthetic(){
return isSynthetic;
}
/**
* Return true if method is deprecated.
*/
public boolean isDeprecated(){
return isDeprecated;
}
}
我们将下面这个class文件解析之后的数据如下:过程很简单,有兴趣的大家调试一遍就知道了。
import java.io.PrintStream;
public class AsmAopExample$Foo
{
public static void execute()
{
AsmAopExample.Monitor.start(); System.out.println("test changed method name");
try {
Thread.sleep(10L);
}
catch (InterruptedException e) {
e.printStackTrace();
}
AsmAopExample.Monitor.end();
}
}