package test.java.classfile;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Arrays;
public class BlockStruct {
public static void main(String[] args) {
new BlockStruct().load("HelloWorld.class");
}
public void load(String filename) {
try {
FileInputStream in = new FileInputStream(filename);
magic = readU4(in);
minor_version = readU2(in);
major_version = readU2(in);
CONSTANT_pool_count = readU2(in);
constant_pool = new cp_info[CONSTANT_pool_count];
for (int i = 0; i < CONSTANT_pool_count - 1; i++)
constant_pool[i + 1] = readInfo(in);
// Class Info
access_flags = readU2(in);
this_class = readU2(in);
// Extends
super_class = readU2(in);
// Implements
interfaces_count = readU2(in);
int[] interfaces = new int[interfaces_count];
for (int i = 0; i < interfaces_count; i++)
interfaces[i] = readU2(in);
// Fields
fields_count = readU2(in);
field_info fields[] = new field_info[fields_count];
for (int i = 0; i < fields_count; i++)
fields[i] = new field_info().load(in, constant_pool);
// Method
methods_count = readU2(in);
MethodInfo methods[] = new MethodInfo[methods_count];
for (int i = 0; i < methods_count; i++)
methods[i] = new MethodInfo().load(in, constant_pool);
// Attribute
int attributes_count = readU2(in);
attribute_info attributes[] = new attribute_info[attributes_count];
for (int i = 0; i < attributes_count; i++)
attributes[i] = readAttr(in, constant_pool);
System.out.println("End");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public final static long readU4(InputStream in) {
try {
long a = in.read() << 0X18;
a += in.read() << 0X10;
a += in.read() << 0X08;
a += in.read();
return a;
// return (long) in.read() << 0X18 + (long) in.read() << 0X10 +
// in.read() << 0X08 + in.read();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public final static int readU2(InputStream in) {
try {
int a = in.read() << 0X08;
a += in.read();
return a;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public final static byte readU1(InputStream in) {
try {
return (byte) in.read();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public final static byte[] readBytes(InputStream in, int length) {
try {
byte[] bytes = new byte[length];
in.read(bytes, 0, length);
return bytes;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public final static String readChars(InputStream in, int length) {
try {
char[] cs = new char[length];
int cntChar = 0;
int b0 = 0;
int b1 = 0;
int b2 = 0;
for (int i = 0; i < length; i++) {
b0 = in.read();
if (b0 < 0x80) {
cs[cntChar++] = (char) b0;
} else if ((b0 & 0xE0) == 0xC0 && (b0 & 0x1E) != 0) {
i++;
b1 = in.read();
cs[cntChar++] = (char) (((b0 & 0x1f) << 6) | (b1 & 0x3f));
} else if ((b0 & 0xF0) == 0xE0) {
i++;
b1 = in.read();
i++;
b2 = in.read();
cs[cntChar++] = (char) (((b0 & 0xf) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f));
} else if ((b0 & 0xF8) == 0xF0) {
throw new RuntimeException();
}
// c = ((x & 0x1f) << 6) + (y & 0x3f);
}
return new String(cs, 0, cntChar);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
long magic;
int minor_version;
int major_version;
int CONSTANT_pool_count;
cp_info[] constant_pool;
int access_flags;
int this_class;
int super_class;
int interfaces_count;
int[] interfaces;
int fields_count;
field_info[] fields;
int methods_count;
MethodInfo[] methods;
int attributes_count;
attribute_info[] attributes;
public static final byte CONSTANT_Class = 7;
public static final byte CONSTANT_Fieldref = 9;
public static final byte CONSTANT_Methodref = 10;
public static final byte CONSTANT_InterfaceMethodref = 11;
public static final byte CONSTANT_String = 8;
public static final byte CONSTANT_Integer = 3;
public static final byte CONSTANT_Float = 4;
public static final byte CONSTANT_Long = 5;
public static final byte CONSTANT_Double = 6;
public static final byte CONSTANT_NameAndType = 12;
public static final byte CONSTANT_Utf8 = 1;
public static final int ACC_PUBLIC = 0x0001;
public static final int ACC_PRIVATE = 0x0002;
public static final int ACC_PROTECTED = 0x0004;
public static final int ACC_STATIC = 0x0008;
public static final int ACC_FINAL = 0x0010;
public static final int ACC_SYNCHRONIZED = 0x0020;
public static final int ACC_NATIVE = 0x0100;
public static final int ACC_ABSTRACT = 0x0400;
public static final int ACC_STRICT = 0x0800;
cp_info readInfo(InputStream in) {
byte tag;
cp_info info = null;
tag = readU1(in);
switch (tag) {
case CONSTANT_Class: // 7;
info = new CONSTANT_Class_info();
break;
case CONSTANT_Fieldref: // 9;
info = new CONSTANT_Fieldref_info();
break;
case CONSTANT_Methodref: // 10;
info = new CONSTANT_Methodref_info();
break;
case CONSTANT_InterfaceMethodref: // 11;
info = new CONSTANT_Integer_info();
break;
case CONSTANT_String: // 8;
info = new CONSTANT_String_info();
break;
case CONSTANT_Integer: // 3;
info = new CONSTANT_Integer_info();
break;
case CONSTANT_Float: // 4;
info = new CONSTANT_Float_info();
break;
case CONSTANT_Long: // 5;
info = new CONSTANT_Long_info();
break;
case CONSTANT_Double: // 6;
info = new CONSTANT_Double_info();
break;
case CONSTANT_NameAndType: // 12;
info = new CONSTANT_NameAndType_info();
break;
case CONSTANT_Utf8: // 1;
info = new CONSTANT_Utf8_info();
break;
default:
throw new RuntimeException("Unknown tag");
}
info.load(in);
return info;
}
attribute_info readAttr(InputStream in, cp_info[] CONSTANT_pool) {
String tag;
attribute_info info = null;
int attribute_name_index = readU2(in);
long attribute_length = readU4(in);
tag = ((CONSTANT_Utf8_info) CONSTANT_pool[attribute_name_index]).text;
switch (tag) {
case "LocalVariableTable": // 7;
info = new LocalVariableTable_attribute();
break;
case "LineNumberTable": // 9;
info = new LineNumberTable_attribute();
break;
case "Code": // 10;
info = new Code_attribute();
break;
case "SourceFile": // 11;
info = new SourceFile_attribute();
break;
default:
info = new attribute_info_unknown();
}
info.attribute_name_index = attribute_name_index;
info.attribute_length = attribute_length;
info.load(in);
return info;
}
public static abstract class cp_info {
byte tag;
public abstract cp_info load(InputStream in);
}
public class CONSTANT_Class_info extends cp_info {
int name_index;
@Override
public CONSTANT_Class_info load(InputStream in) {
name_index = readU2(in);
System.out.println(name_index);
return this;
}
}
public class CONSTANT_Fieldref_info extends cp_info {
int class_index;
int name_and_type_index;
@Override
public CONSTANT_Fieldref_info load(InputStream in) {
class_index = readU2(in);
name_and_type_index = readU2(in);
return this;
}
}
public class CONSTANT_Methodref_info extends cp_info {
int class_index;
int name_and_type_index;
@Override
public CONSTANT_Methodref_info load(InputStream in) {
class_index = readU2(in);
name_and_type_index = readU2(in);
return this;
}
}
public class CONSTANT_InterfaceMethodref_info extends cp_info {
int class_index;
int name_and_type_index;
@Override
public CONSTANT_InterfaceMethodref_info load(InputStream in) {
class_index = readU2(in);
name_and_type_index = readU2(in);
return this;
}
}
public class CONSTANT_String_info extends cp_info {
int string_index;
// String string;
@Override
public CONSTANT_String_info load(InputStream in) {
string_index = readU2(in);
return this;
}
public String getString() {
return ((CONSTANT_Utf8_info) constant_pool[string_index]).text;
}
}
public class CONSTANT_Integer_info extends cp_info {
long bytes;
@Override
public CONSTANT_Integer_info load(InputStream in) {
bytes = readU4(in);
return this;
}
}
public class CONSTANT_Float_info extends cp_info {
long bytes;
@Override
public CONSTANT_Float_info load(InputStream in) {
bytes = readU4(in);
return this;
}
}
public class CONSTANT_Long_info extends cp_info {
long high_bytes;
long low_bytes;
@Override
public CONSTANT_Long_info load(InputStream in) {
high_bytes = readU4(in);
low_bytes = readU4(in);
return this;
}
}
public class CONSTANT_Double_info extends cp_info {
long high_bytes;
long low_bytes;
@Override
public CONSTANT_Double_info load(InputStream in) {
high_bytes = readU4(in);
low_bytes = readU4(in);
return this;
}
}
public class CONSTANT_NameAndType_info extends cp_info {
int name_index;
int descriptor_index;
@Override
public CONSTANT_NameAndType_info load(InputStream in) {
name_index = readU2(in);
descriptor_index = readU2(in);
return this;
}
}
public class CONSTANT_Utf8_info extends cp_info {
int length;
String text;
@Override
public CONSTANT_Utf8_info load(InputStream in) {
length = readU2(in);
text = readChars(in, length);
return this;
}
}
public class field_info {
int access_flags;
int name_index;
// String name;
int descriptor_index;
String descriptor;
int attributes_count;
attribute_info attributes[];
public field_info load(InputStream in, cp_info[] constant_pool) {
access_flags = readU2(in);
name_index = readU2(in);
descriptor_index = readU2(in);
attributes_count = readU2(in);
attributes = new attribute_info[attributes_count];
for (int i = 0; i < attributes_count; i++)
attributes[i] = readAttr(in, constant_pool);
return this;
}
public String getName() {
return ((CONSTANT_Utf8_info) constant_pool[name_index]).text;
}
public String getDescriptor() {
return ((CONSTANT_Utf8_info) constant_pool[descriptor_index]).text;
}
@Override
public String toString() {
return "field_info [access_flags=" + access_flags + ", name=" + this.getName() + ", descriptor="
+ this.getDescriptor() + ", attributes=" + Arrays.toString(attributes) + "]";
}
}
public class ConstantValue_attribute extends attribute_info {
int constantvalue_index;
public ConstantValue_attribute load(InputStream in) {
constantvalue_index = readU2(in);
return this;
}
}
// method_info {
// u2 access_flags;
// u2 name_index;
// u2 descriptor_index;
// u2 attributes_count;
// attribute_info attributes[attributes_count];
// }
public class MethodInfo {
int access_flags;
int name_index;
int descriptor_index;
int attributes_count;
attribute_info attributes[];
public MethodInfo load(InputStream in, cp_info[] constant_pool) {
access_flags = readU2(in);
name_index = readU2(in);
descriptor_index = readU2(in);
attributes_count = readU2(in);
attributes = new attribute_info[attributes_count];
for (int i = 0; i < attributes_count; i++)
attributes[i] = readAttr(in, constant_pool);
return this;
}
}
//
// Code_attribute {
// u2 attribute_name_index;
// u4 attribute_length;
// u2 max_stack;
// u2 max_locals;
// u4 code_length;
// u1 code[code_length];
// u2 exception_table_length;
// { u2 start_pc;
// u2 end_pc;
// u2 handler_pc;
// u2 catch_type;
// } exception_table[exception_table_length];
// u2 attributes_count;
// attribute_info attributes[attributes_count];
// }
public class Code_attribute extends attribute_info {
int max_stack;
int max_locals;
long code_length;
byte code[];
int exception_table_length;
exception_table_class exception_table[];
int attributes_count;
attribute_info attributes[];
public Code_attribute load(InputStream in) {
max_stack = readU2(in);
max_locals = readU2(in);
code_length = readU4(in);
code = readBytes(in, (int) code_length);
exception_table_length = readU2(in);
exception_table = new exception_table_class[attributes_count];
for (int i = 0; i < exception_table_length; i++)
exception_table[i] = new exception_table_class().load(in);
attributes_count = readU2(in);
attributes = new attribute_info[attributes_count];
for (int i = 0; i < attributes_count; i++)
attributes[i] = readAttr(in, constant_pool);
return this;
}
class exception_table_class {
int start_pc;
int end_pc;
int handler_pc;
int catch_type;
public exception_table_class load(InputStream in) {
start_pc = readU2(in);
end_pc = readU2(in);
handler_pc = readU2(in);
catch_type = readU2(in);
return this;
}
}
}
public abstract class attribute_info {
int attribute_name_index;
long attribute_length;
public abstract attribute_info load(InputStream in);
@Override
public String toString() {
return this.getClass().getName() + " [attribute_name" + constant_pool[attribute_name_index]
+ ", attribute_length=" + attribute_length + "]";
}
}
public class attribute_info_unknown extends attribute_info {
byte info[];
public attribute_info load(InputStream in) {
info = readBytes(in, (int) super.attribute_length);
return this;
}
}
public class Exceptions_attribute extends attribute_info {
int number_of_exceptions;
int exception_index_table[];
public Exceptions_attribute load(InputStream in) {
number_of_exceptions = readU2(in);
exception_index_table = new int[number_of_exceptions];
for (int i = 0; i < number_of_exceptions; i++)
exception_index_table[i] = readU2(in);
return this;
}
}
public class InnerClasses_attribute extends attribute_info {
int number_of_classes;
classes_class classes[];
public InnerClasses_attribute load(InputStream in) {
number_of_classes = readU2(in);
classes = new classes_class[number_of_classes];
for (int i = 0; i < number_of_classes; i++)
classes[i] = new classes_class().load(in);
return this;
}
}
public class classes_class extends attribute_info {
int inner_class_info_index;
int outer_class_info_index;
int inner_name_index;
int inner_class_access_flags;
public classes_class load(InputStream in) {
inner_class_info_index = readU2(in);
outer_class_info_index = readU2(in);
inner_name_index = readU2(in);
inner_class_access_flags = readU2(in);
return this;
}
}
public class Synthetic_attribute extends attribute_info {
public Synthetic_attribute load(InputStream in) {
return this;
}
}
public class SourceFile_attribute extends attribute_info {
int sourcefile_index;
public SourceFile_attribute load(InputStream in) {
sourcefile_index = readU2(in);
return this;
}
}
public class LineNumberTable_attribute extends attribute_info {
int line_number_table_length;
line_number_table_class line_number_table[];
public LineNumberTable_attribute load(InputStream in) {
line_number_table_length = readU2(in);
line_number_table = new line_number_table_class[line_number_table_length];
for (int i = 0; i < line_number_table_length; i++)
line_number_table[i] = new line_number_table_class().load(in);
return this;
}
}
public class line_number_table_class {
int start_pc;
int line_number;
public line_number_table_class load(InputStream in) {
start_pc = readU2(in);
line_number = readU2(in);
return this;
}
}
public class LocalVariableTable_attribute extends attribute_info {
int local_variable_table_length;
local_variable_table_class local_variable_table[];
public LocalVariableTable_attribute load(InputStream in) {
local_variable_table_length = readU2(in);
local_variable_table = new local_variable_table_class[local_variable_table_length];
for (int i = 0; i < local_variable_table_length; i++)
local_variable_table[i] = new local_variable_table_class().load(in);
return this;
}
}
public class local_variable_table_class {
int start_pc;
int length;
int name_index;
int descriptor_index;
int index;
public local_variable_table_class load(InputStream in) {
start_pc = readU2(in);
length = readU2(in);
name_index = readU2(in);
descriptor_index = readU2(in);
index = readU2(in);
return this;
}
}
public class Deprecated_attribute extends attribute_info {
public Deprecated_attribute load(InputStream in) {
return this;
}
}
}