Estripando um .class

Resolvi abrir na unha e ler no zóio um .class.
A idéia veio desse tópico aqui: http://www.guj.com.br/posts/list/196646.java

VM Spec The .class File Format

Vou colocar entre code para ficar formatado.
Espero que gostem. :slight_smile:

Nota: Os bytescodes foram “extraidos” via hexdump do linux e acabaram ficando em little-endian.

       0000000 feca beba --> magic number  ( 0xcafebabe )
       0000004 0000 --> minor version
       0000006 3200 --> major version
       0000008 1d00 --> constant pool count 29
                                 //tabela constante pool
                                 //primeiro item
       000000A 0a --> tag tipo CONSTANT_Methodref
       000000B 00 --\__ class_index, index 0006 na tabela constante pool, este index deve apontar para uma estrutura CONSTANT_Class_info
       000000C 06 --/
       000000D 00 --\__ name_and_type_index, index 000f na tabela constante pool, este index deve apontar para uma estrutura CONSTANT_NameAndType_info method descriptor
       000000E 0f --/
                                //segundo item
       000000F 09 --> tag tipo CONSTANT_Fieldref
       0000010 00 --\__ class_index, index 0010 na tabela constante pool, este index deve apontar para uma estrutura do tipo classe ou interface
       0000011 10 --/
       0000012 00 --\__ name_and_type_index, index 0011 na tabela cosntante pool, este index deve apontar para uma estrutura CONSTANT_NameAndType_info field descriptor
       0000013 11 --/
                                //terceiro item
       0000014 08 --> tag tipo CONSTANT_String
       0000015 00 --\__ String_index, index 0012 na tabela constante pool, este index deve apontar para uma estrutura do tipo CONSTANT_utf8_info (os caracteres da String)
       0000016 12 --/
                               //quarto item
       0000017 0a --> tag tipo CONSTANT_Methodref
       0000018 00 --\__ class_index, index 0013 na tabela constante pool, este index deve apontar para uma estrutura CONSTANT_Class_info
       0000019 13 --/
       000001A 00 --\__ name_and_type_index, index 0014 na tabela constante pool, este index deve apontar para uma estrutura CONSTANT_NameAndType_info method descriptor
       000001B 14 --/
                             // quinto item
       000001C 07 --> tag tipo CONSTANT_Class
       000001D 00 --\__ name_index, index 0015 na tabela constante pool, este index deve apontar para uma estrutura do tipo CONSTANT_utf8_info (nome da classe ou interface)
       000001E 15 --/
                             // sexto item
       000001F 07 --> tag tipo CONSTANT_Class
       0000020 00 --\__ name_index, index 0016 na tabela constante pool, este index deve apontar para uma estrutura do tipo CONSTANT_utf8_info (nome da classe ou interface)
       0000021 16 --/
                             //sétimo item
       0000022 01 --> tag tipo CONSTANT_Utf8
       0000023 00 --\__ tamanho em bytes do array, 6 bytes
       0000024 06 --/
       0000025 3c ----> <
       0000026 69 ----> i
       0000027 6e ----> n
       0000028 69 ----> i
       0000029 74 ----> t
       000002A 3e ---> >
                             // oitavo item
       000002B 01 --> tag tipo CONSTANT_Utf8
       000002C 00 --\__ tamanho em bytes do array, 3 bytes
       000002D 03 --/
       000002E 28 ----> (
       000002F 29 ----> )
       0000030 56 ----> V
                             // nono item
       0000031 01 --> tag tipo CONSTANT_Utf8
       0000032 00 --\__ tamanho em bytes do array, 4 bytes
       0000033 04 --/
       0000034 43 ----> C
       0000035 6f ----> o
       0000036 64 ----> d
       0000037 65 ----> e
                           // decimo item
       0000038 01 --> tag tipo CONSTANT_Utf8
       0000039 00 --\__ tamanho em bytes do array, 15 bytes
       000003A 0f --/
       000003B 4c ----> L
       000003C 69 ----> i
       000003D 6e ----> n
       000003E 65 ----> e
       000003F 4e ----> N
       0000040 75 ----> u
       0000041 6d ----> m
       0000042 62 ----> b
       0000043 65 ----> e
       0000044 72 ----> r
       0000045 54 ----> T
       0000046 61 ----> a
       0000047 62 ----> b
       0000048 6c ----> l
       0000049 65 ----> e
                           // decimo primeiro item
       000004A 01 --> tag tipo CONSTANT_Utf8
       000004B 00 --\__ tamanho em bytes do array, 4 bytes
       000004C 04 --/
       000004D 6d ----> m
       000004E 61 ----> a
       000004F 69 ----> i
       0000050 6e ----> n
                           // decimo segundo item
       0000051 01 --> tag tipo CONSTANT_Utf8
       0000052 00 --\__ tamanho em bytes do array, 22 bytes
       0000053 16 --/
       0000054 28 ----> (
       0000055 5b ----> [
       0000056 4c ----> L
       0000057 6a ----> j
       0000058 61 ----> a
       0000059 76 ----> v
       000005A 61 ----> a
       000005B 2f ----> /
       000005C 6c ----> l
       000005D 61 ----> a
       000005E 6e ----> n
       000005F 67 ----> g
       0000060 2f ----> /
       0000061 53 ----> S
       0000062 74 ----> t
       0000063 72 ----> r
       0000064 69 ----> i
       0000065 6e ----> n   
       0000066 67 ----> g
       0000067 3b ----> ;
       0000068 29 ----> )
       0000069 56 ----> V
                          // decimo terceiro item
       000006A 01 --> tag tipo CONSTANT_Utf8
       000006B 00 --\__ tamanho em bytes do array, 10 bytes
       000006C 0a --/
       000006D 53 ----> S
       000006E 6f ----> o
       000006F 75 ----> u
       0000070 72 ----> r
       0000071 63 ----> c
       0000072 65 ----> e
       0000073 46 ----> F
       0000074 69 ----> i
       0000075 6c ----> l
       0000076 65 ----> e
                         // decimo quarto item
       0000077 01 --> tag tipo CONSTANT_Utf8
       0000078 00 --\__ tamanho em bytes do array, 10 bytes
       0000079 0a --/
       000007A 54 ----> T
       000007B 65 ----> e
       000007C 73 ----> s
       000007D 74 ----> t
       000007E 65 ----> e
       000007F 2e ----> .
       0000080 6a ----> j
       0000081 61 ----> a
       0000082 76 ----> v
       0000083 61 ----> a
                         // decimo quinto item
       0000084 0c --> tag tipo CONSTANT_NameAndType 
       0000085 00 --\__ name_index, index 0007 na tabela constante pool, este index deve apontar para uma estrutura do tipo CONSTANT_utf8_info (nome do metodo ou campo)
       0000086 07 --/
       0000087 00 --\__ descriptor_index, index 0008 na tabela constante pool, este index deve apontar para uma estrutura CONSTANT_Utf8_info (method descriptor ou field descriptor)
       0000088 08 --/
                        // decimo sexto item
       0000089 07 --> tag tipo CONSTANT_Class
       000008A 00 --\__ name_index, index 0017 na tabela constante pool, este index deve apontar para uma estrutura do tipo CONSTANT_utf8_info (nome da classe ou interface)
       000008B 17 --/
                        // decimo setimo item
       000008C 0c --> tag tipo CONSTANT_NameAndType 
       000008D 00 --\__ name_index, index 0018 na tabela constante pool, este index deve apontar para uma estrutura do tipo CONSTANT_utf8_info (nome do metodo ou campo)
       000008E 18 --/
       000008F 00 --\__ descriptor_index, index 0019 na tabela constante pool, este index deve apontar para uma estrutura CONSTANT_Utf8_info (method descriptor ou field descriptor)
       0000090 19 --/
                        // decimo oitavo item
       0000091 01 --> tag tipo CONSTANT_Utf8
       0000092 00 --\__ tamanho em bytes do array, 78 bytes
       0000093 4e --/
       0000094 53 ----> S
       0000095 65 ----> e
       0000096 20 ----> <espaco>
       0000097 65 ----> e
       0000098 75 ----> u
       0000099 20 ----> <espaco>
       000009A 70 ----> p
       000009B 75 ----> u
       000009C 64 ----> d
       000009D 65 ----> e
       000009E 73 ----> s
       000009F 73 ----> s
       00000a0 65 ----> e
       00000a1 20 ----> <espaco>
       00000a2 6d ----> m
       00000a3 61 ----> a
       00000a4 74 ----> t
       00000a5 61 ----> a
       00000a6 76 ----> v
       00000a7 61 ----> a
       00000a8 20 ----> <espaco>
       00000a9 6d ----> m
       00000aA 69 ----> i
       00000aB 6c ----> l
       00000aC 2c ----> ,
       00000aD 20 ----> <espaco>
       00000aE 6d ----> m
       00000aF 69 ----> i
       00000b0 6c ----> l
       00000b1 2c ----> ,
       00000b2 20 ----> <espaco>
       00000b3 6d ----> m
       00000b4 69 ----> i
       00000b5 6c ----> l
       00000b6 2e ----> .
       00000b7 20 ----> <espaco>
       00000b8 51 ----> Q
       00000b9 75 ----> u
       00000bA 65 ----> e
       00000bB 20 ----> <espaco>
       00000bC 65 ----> e
       00000bD 75 ----> u
       00000bE 20 ----> <espaco>
       00000bF 73 ----> s
       00000c0 6f ----> o
       00000c1 20 ----> <espaco>
       00000c2 63 ----> c
       00000c3 61 ----> a
       00000c4 62 ----> b
       00000c5 61 ----> a
       00000c6 20 ----> <espaco>
       00000c7 48 ----> H
       00000c8 6f ----> o
       00000c9 6d ----> m
       00000cA 69 ----> i
       00000cB 2e ----> .
       00000cC 20 ----> <espaco>
       00000cD 4d ----> M
       00000cE 61 ----> a
       00000cF 74 ----> t
       00000d0 6f ----> o
       00000d1 20 ----> <espaco>
       00000d2 69 ----> i
       00000d3 6e ----> n
       00000d4 74 ----> t
       00000d5 65 ----> e
       00000d6 20 ----> <espaco>
       00000d7 6f ----> o
       00000d8 20 ----> <espaco>
       00000d9 64 ----> d
       00000dA 65 ----> e
       00000dB 6c ----> l
       00000dC 65 ----> e
       00000dD 67 ----> g
       00000dE 61 ----> a
       00000dF 64 ----> d
       00000e0 6f ----> o
       00000e1 2e ----> .
                   // decimo nono item
       00000e2 07 --> tag tipo CONSTANT_Class
       00000e3 00 --\__ name_index, index 001a na tabela constante pool, este index deve apontar para uma estrutura do tipo CONSTANT_utf8_info (nome da classe ou interface)
       00000e4 1a --/
                    // vigesimo item
       00000e5 0c --> tag tipo CONSTANT_NameAndType
       00000e6 00 --\__ name_index, index 001b na tabela constante pool, este index deve apontar para uma estrutura do tipo CONSTANT_utf8_info (nome do metodo ou campo)
       00000e7 1b --/
       00000e8 00 --\__ descriptor_index, index 001c na tabela constante pool, este index deve apontar para uma estrutura CONSTANT_Utf8_info (method descriptor ou field descriptor)
       00000e9 1c --/
                    // vigesimo primeiro item
       00000eA 01 --> tag tipo CONSTANT_Utf8
       00000eB 00 --\__ tamanho em bytes do array, 5 bytes
       00000eC 05 --/
       00000eD 54 ----> T
       00000eE 65 ----> e
       00000eF 73 ----> s
       00000f0 74 ----> t
       00000f1 65 ----> e
                    // vegesimo segundo item
       00000f2 01 --> tag tipo CONSTANT_Utf8
       00000f3 00 --\__ tamanho em bytes do array, 16 bytes
       00000f4 10 --/
       00000f5 6a ----> j
       00000f6 61 ----> a
       00000f7 76 ----> v
       00000f8 61 ----> a
       00000f9 2f ----> /
       00000fA 6c ----> l
       00000fB 61 ----> a
       00000fC 6e ----> n
       00000fD 67 ----> g
       00000fE 2f ----> /
       00000fF 4f ----> O
       0000100 62 ----> b
       0000101 6a ----> j
       0000102 65 ----> e
       0000103 63 ----> c
       0000104 74 ----> t
                    // vigesimo terceiro item
       0000105 01 --> tag tipo CONSTANT_Utf8
       0000106 00 --\__ tamanho em bytes do array, 16 bytes
       0000107 10 --/
       0000108 6a ----> j
       0000109 61 ----> a
       000010A 76 ----> v
       000010B 61 ----> a
       000010C 2f ----> /
       000010D 6c ----> l
       000010E 61 ----> a
       000010F 6e ----> n
       0000110 67 ----> g
       0000111 2f ----> /
       0000112 53 ----> S
       0000113 79 ----> y
       0000114 73 ----> s
       0000115 74 ----> t
       0000116 65 ----> e
       0000117 6d ----> m
                    // vigesimo quarto item
       0000118 01 --> tag tipo CONSTANT_Utf8
       0000119 00 --\__ tamanho em bytes do array, 3 bytes
       000011A 03 --/ 
       000011B 6f ----> o
       000011C 75 ----> u
       000011D 74 ----> t
                   // vigesimo quinto item
       000011E 01 --> tag tipo CONSTANT_Utf8
       000011F 00 --\__ tamanho em bytes do array, 21 bytes
       0000120 15 --/
       0000121 4c ----> L
       0000122 6a ----> j
       0000123 61 ----> a
       0000124 76 ----> v
       0000125 61 ----> a
       0000126 2f ----> /
       0000127 69 ----> i
       0000128 6f ----> o
       0000129 2f ----> /
       000012A 50 ----> p
       000012B 72 ----> r
       000012C 69 ----> i
       000012D 6e ----> n
       000012E 74 ----> t
       000012F 53 ----> S
       0000130 74 ----> t
       0000131 72 ----> r
       0000132 65 ----> e
       0000133 61 ----> a
       0000134 6d ----> m
       0000135 3b ----> ;
                     // vigesimo sexto item
       0000136 01 --> tag tipo CONSTANT_Utf8
       0000137 00 --\__ tamanho em bytes do array, 19 bytes
       0000138 13 --/
       0000139 6a ----> j
       000013A 61 ----> a
       000013B 76 ----> v
       000013C 61 ----> a
       000013D 2f ----> /
       000013E 69 ----> i
       000013F 6f ----> o
       0000140 2f ----> /
       0000141 50 ----> P
       0000142 72 ----> r
       0000143 69 ----> i
       0000144 6e ----> n
       0000145 74 ----> t
       0000146 53 ----> S
       0000147 74 ----> t
       0000148 72 ----> r
       0000149 65 ----> e
       000014A 61 ----> a
       000014B 6d ----> m
                    // vigesimo setimo item
       000014C 01 --> tag tipo CONSTANT_Utf8
       000014D 00 --\__ tamanho em bytes do array, 7 bytes
       000014E 07 --/
       000014F 70 ----> p
       0000150 72 ----> r
       0000151 69 ----> i
       0000152 6e ----> n
       0000153 74 ----> t
       0000154 6c ----> l
       0000155 6e ----> n
                   // vigesimo oitavo item
       0000156 01 --> tag tipo CONSTANT_Utf8
       0000157 00 --\__ tamanho em bytes do array, 21 bytes
       0000158 15 --/
       0000159 28 ----> (
       000015A 4c ----> L
       000015B 6a ----> j
       000015C 61 ----> a
       000015D 76 ----> v
       000015E 61 ----> a
       000015F 2f ----> /
       0000160 6c ----> l
       0000161 61 ----> a
       0000162 6e ----> n
       0000163 67 ----> g
       0000164 2f ----> /
       0000165 53 ----> S
       0000166 74 ----> t
       0000167 72 ----> r
       0000168 69 ----> i
       0000169 6e ----> n
       000016A 67 ----> g
       000016B 3b ----> ;
       000016C 29 ----> )
       000016D 56 ----> V
       000016E 2100 --> access flag (ACC_PUBLIC e ACC_SUPER)
       0000170 0500 --> this_class, index 0005 na tabela constante pool, este index deve apontar para uma estrutura CONSTANT_Class_info)
       0000172 0600 --> super_class, index 0006 na tabela constante pool, este index deve apontar para uma estrutura CONSTANT_Class_info)
       0000174 0000 --> interfaces_count, numero de super interfaces dessa classe ou interface, 0 superinterfaces.
       0000176 0000 --> fields_count, numero de estruturas field_info na tabela field, 0 estruturas.
       0000178 0200 --> methods_count, numero de estruturas method_info na tabela methods, 2 estruturas.
                   // tabela method
                   // primeiro item
       000017A 0100 --> access_flag (ACC_PUBLIC)
       000017C 0700 --> name_index, index 0007 na tabela constante pool, este index deve apontar para uma estrutura do tipo CONSTANT_utf8_info (<init>)
       000017E 0800 --> descriptor_index, index 0008 na tabela constante pool, este index deve apontar para uma estrutura do tipo CONSTANT_utf8_info (()V)
       0000180 0100 --> attributes_count, numero de atributos adicionais desse campo, 1 atributo adicional.
                         // atributos do primeiro item
       0000182 0900 --> attribute_name_index, index 0009 na tabela constante pool, este index deve apontar para uma estrutura do tipo CONSTANT_utf8_info (Code, sessao de codigo do metodo <init>)
       0000184 0000 1d00 --> attribute_length, tamanho do conteudo deste atributo, 29 bytes, estrutura Code_attibute.
       0000188 0100 --> max_stack, tamanho maximo da profundidade da pilha do metodo, 1 byte.
       000018A 0100 --> max_locals, numero maximo de variaveis locais, 1 variavel.
       000018C 0000 0500 --> code_length, 5 bytes.
       0000190 2a --> bytecode => aload_0
       0000191 b7 --> bytecode => invokespecial
       0000192 00 --> bytecode => index byte1 de invokespecial
       0000193 01 --> bytecode => index byte2 de invokespecial
       0000194 b1 --> bytecode => return
       0000195 0000 --> exception_table_length, numero de entradas na tabela de exception_table, 0 entrada.
       0000197 0100 --> attributes_count, numero de atributos de Code, 1 atributo.
       0000199 0a00 --> attribute_name_index, index 000a na tabela constante pool, este index deve apontar para uma estrutura do tipo CONSTANT_utf8_info (LineNumberTable)
       000019B 0000 0600 --> attribute_length, tamanho do conteudo deste atributo, 6 bytes.
       000019F 0100 --> line_number_table_lenght, quantidade de entradas na tabela line_number_table, 1 entrada.
       00001a1 0000 ----> start_pc, index 0000 no array code.
       00001a3 0100 ----> line_number, numero da linha no codigo fonte ariginal, linha 1.
                   // segundo item
       00001a5 0900 --> access_flags (ACC_STATIC e ACC_PUBLIC)
       00001a7 0b00 --> name_index, index 000b na tabela constante pool, este index deve apontar para uma estrutura do tipo CONSTANT_utf8_info (main, metodo)
       00001a9 0c00 --> descriptor_index, index 000c na tabela constante pool, este index deve apontar para uma estrutura do tipo CONSTANT_utf8_info (([Ljava/lang/String;)V)
       00001aB 0100 --> attributes_count, numero de atributos adicionais desse campo, 1 atributo adicional.
                         // atributos do primeiro item
       00001aD 0900 --> attribute_name_index, index 0009 na tabela constante pool, este index deve apontar para uma estrutura do tipo CONSTANT_utf8_info (Code, sessao de codigo do metodo main)
       00001aF 0000 2500 --> attribute_length, tamanho do conteudo deste atributo, 37 bytes, estrutura Code_attibute.
       00001b3 0200 --> max_stack, tamanho maximo da profundidade da pilha do metodo, 2 bytes.
       00001b5 0100 --> max_locals, numero maximo de variaveis locais, 1 variavel.
       00001b7 0000 0900 --> code_length, 9 bytes.
       00001bB b2 --> bytecode => getstatic
       00001bC 00 --> bytecode => index byte1 de getstatic
       00001bD 02 --> bytecode => index byte2 de getstatic
       00001bE 12 --> bytecode => ldc
       00001bF 03 --> bytecode => index de ldc
       00001c0 b6 --> bytecode => invokvirtual
       00001c1 00 --> bytecode => index byte1 de invokvirtual
       00001c2 04 --> bytecode => index byte2 de invokvirtual
       00001c3 b1 --> bytecode => return
       00001c4 0000 --> exception_table_length, numero de entradas na tabela de exception_table, 0 entrada.
       00001c6 0100 --> attributes_count, numero de atributos de Code, 1 atributo.
       00001c8 0a00 --> attribute_name_index, index 000a na tabela constante pool, este index deve apontar para uma estrutura do tipo CONSTANT_utf8_info (LineNumberTable)
       00001cA 0000 0a00 --> attribute_length, tamanho do conteudo deste atributo, 10 bytes.
       00001cE 0200 --> line_number_table_lenght, quantidade de entradas na tabela line_number_table, 2 entradas.
       00001d0 0000 --> start_pc, index 0000 no array code.
       00001d2 0300 --> line_number, numero da linha no codigo fonte ariginal, linha 3.
       00001d4 0800 --> start_pc, index 0008 no array code.
       00001d6 0400 --> line_number, numero da linha no codigo fonte ariginal, linha 4.
       00001d8 0100 --> attributes_count, numero de atributos na tabela attributes, 1 atributo.
                  // tabela attribute
                     // primeiro item
       00001dA 0d00 --> attribute_name_index, index 000d na tabela constante pool, este index deve apontar para uma estrutura do tipo CONSTANT_utf8_info (SourceFile)
       00001dC 0000 0200 --> attribute_length, o tamanho do atributo SourceFile deve ser 2, correto.
       00001e0 0e00 --> sourcefile_index, index 000e na tabela constante pool, este index deve apontar para uma estrutura do tipo CONSTANT_utf8_info (Teste.java)

legal…
Fez isso só seguindo a Especificação da Virtual Machine no site da Sun?

Muito interessante… sempre quis saber como que são os .class

Você usou um programa em C/C++ ou C# para ler o .class?
É que você pegou os conjuntos de 2 bytes (short) e os apresentou em “host byte order” segundo a arquitetura Intel.
Que eu saiba, no arquivo binário o cabeçalho (por exemplo) aparece como “0xCAFEBABE”, não como FECA BEBA (o que ocorreria se você usasse a leitura de um short via C/C++ ou C#).
Se usasse um programa em Java, e se você usasse DataInputStream (por exemplo), o readShort já deixa os bytes na ordem certa.

[quote]beliangela
Fez isso só seguindo a Especificação da Virtual Machine no site da Sun?
[/quote]
Sim :smiley:

[quote]entaglement
Você usou um programa em C/C++ ou C# para ler o .class?
[/quote]
Pedi para um colega usar o hexdump (feito em C) do linux para gerar um .txt com os byte codes para que pudesse lê-los aqui no windows. No link que eu coloquei no início tem a saída do hexdump.

[quote]É que você pegou os conjuntos de 2 bytes (short) e os apresentou em “host byte order” segundo a arquitetura Intel.
Que eu saiba, no arquivo binário o cabeçalho (por exemplo) aparece como “0xCAFEBABE”, não como FECA BEBA (o que ocorreria se você usasse a leitura de um short via C/C++ ou C#).
[/quote]
Você tem razão, isso foi culpa do hexdump que gerou a saída em little-endian. Vou por uma nota no post. Vlw.

Puxa vida, que paciência…

De qualquer maneira, em vez de usar o hexdump (ou então o “od” para aqueles que têm sistemas Unix bem velhinhos), você mesmo poderia ter escrito um programa Java. Pegue o programa do Thingol que está aqui:

http://www.guj.com.br/posts/list/56444.java

e separe o método “printHex”. Esse método efetua dump de dados binários, tal como o hexdump.

Hoje de noite eu dou uma olhada com detalhes nese código do Thingol.
Pode ser que futuramente eu porte uns utilitário (hexdump, cat, split, strings) do Unix para java, só para ir aprendendo a programar em java, mas vamos ver.

Esse código do Thingol foi escrito para funcionar no JDK 1.4, portanto tem umas maneiras estranhas de converter um número para hexadecimal. Com o Java 5.0 é bem mais fácil: basta usar algo como String.format ("%08X", n) ou coisa parecida.