jbytecode is a Java bytecode disassembler/assembler written in Python.
Because dissasembly code is aligned with Java bytecodes in the class file so modification and re-assembly is always possible, even when class is obfuscated!!!
package helloworld; public class Main { public static void main(String[] args) { System.out.println("Hello world!"); } }
Dump of Main.class file:
This is the hex dump of the Main.class file. All the byte code is there and jbytecode will help you to understand it.
00000000h: CA FE BA BE 00 00 00 2E 00 22 0A 00 06 00 14 09 ; -¦¦+....."...... 00000010h: 00 15 00 16 08 00 17 0A 00 18 00 19 07 00 1A 07 ; ................ 00000020h: 00 1B 01 00 06 3C 69 6E 69 74 3E 01 00 03 28 29 ; ........() 00000030h: 56 01 00 04 43 6F 64 65 01 00 0F 4C 69 6E 65 4E ; V...Code...LineN 00000040h: 75 6D 62 65 72 54 61 62 6C 65 01 00 12 4C 6F 63 ; umberTable...Loc 00000050h: 61 6C 56 61 72 69 61 62 6C 65 54 61 62 6C 65 01 ; alVariableTable. 00000060h: 00 04 74 68 69 73 01 00 11 4C 68 65 6C 6C 6F 77 ; ..this...Lhellow 00000070h: 6F 72 6C 64 2F 4D 61 69 6E 3B 01 00 04 6D 61 69 ; orld/Main;...mai 00000080h: 6E 01 00 16 28 5B 4C 6A 61 76 61 2F 6C 61 6E 67 ; n...([Ljava/lang 00000090h: 2F 53 74 72 69 6E 67 3B 29 56 01 00 04 61 72 67 ; /String;)V...arg 000000A0h: 73 01 00 13 5B 4C 6A 61 76 61 2F 6C 61 6E 67 2F ; s...[Ljava/lang/ 000000B0h: 53 74 72 69 6E 67 3B 01 00 0A 53 6F 75 72 63 65 ; String;...Source 000000C0h: 46 69 6C 65 01 00 09 4D 61 69 6E 2E 6A 61 76 61 ; File...Main.java 000000D0h: 0C 00 07 00 08 07 00 1C 0C 00 1D 00 1E 01 00 0C ; ................ 000000E0h: 48 65 6C 6C 6F 20 77 6F 72 6C 64 21 07 00 1F 0C ; Hello world!.... 000000F0h: 00 20 00 21 01 00 0F 68 65 6C 6C 6F 77 6F 72 6C ; . .!...helloworl 00000100h: 64 2F 4D 61 69 6E 01 00 10 6A 61 76 61 2F 6C 61 ; d/Main...java/la 00000110h: 6E 67 2F 4F 62 6A 65 63 74 01 00 10 6A 61 76 61 ; ng/Object...java 00000120h: 2F 6C 61 6E 67 2F 53 79 73 74 65 6D 01 00 03 6F ; /lang/System...o 00000130h: 75 74 01 00 15 4C 6A 61 76 61 2F 69 6F 2F 50 72 ; ut...Ljava/io/Pr 00000140h: 69 6E 74 53 74 72 65 61 6D 3B 01 00 13 6A 61 76 ; intStream;...jav 00000150h: 61 2F 69 6F 2F 50 72 69 6E 74 53 74 72 65 61 6D ; a/io/PrintStream 00000160h: 01 00 07 70 72 69 6E 74 6C 6E 01 00 15 28 4C 6A ; ...println...(Lj 00000170h: 61 76 61 2F 6C 61 6E 67 2F 53 74 72 69 6E 67 3B ; ava/lang/String; 00000180h: 29 56 00 21 00 05 00 06 00 00 00 00 00 02 00 01 ; )V.!............ 00000190h: 00 07 00 08 00 01 00 09 00 00 00 33 00 01 00 01 ; ...........3.... 000001A0h: 00 00 00 05 2A B7 00 01 B1 00 00 00 02 00 0A 00 ; ....*+..¦....... 000001B0h: 00 00 0A 00 02 00 00 00 03 00 04 00 08 00 0B 00 ; ................ 000001C0h: 00 00 0C 00 01 00 00 00 05 00 0C 00 0D 00 00 00 ; ................ 000001D0h: 09 00 0E 00 0F 00 01 00 09 00 00 00 37 00 02 00 ; ............7... 000001E0h: 01 00 00 00 09 B2 00 02 12 03 B6 00 04 B1 00 00 ; .....¦....¦..¦.. 000001F0h: 00 02 00 0A 00 00 00 0A 00 02 00 00 00 05 00 08 ; ................ 00000200h: 00 06 00 0B 00 00 00 0C 00 01 00 00 00 09 00 10 ; ................ 00000210h: 00 11 00 00 00 01 00 12 00 00 00 02 00 13 00 00 ; ................
Disassembled bytecodes:
This is the disassembly output of jbytecode:
00000000 CAFEBABE ; magic 00000004 0000 ; minor_version 00000006 002E ; major_version 00000008 0022 ; constant_pool_count ; constant_pool_start ; constant_pool_index = 0x1 0000000A 0A ; tag = Methodref 0000000B 0006 ; class_index -> "java/lang/Object" 0000000D 0014 ; name_and_type_index -> "()V" ; constant_pool_index = 0x2 0000000F 09 ; tag = Fieldref 00000010 0015 ; class_index -> "java/lang/System" 00000012 0016 ; name_and_type_index -> "outLjava/io/PrintStream;" ; constant_pool_index = 0x3 00000014 08 ; tag = String 00000015 0017 ; string_index -> "Hello world!" ; constant_pool_index = 0x4 00000017 0A ; tag = Methodref 00000018 0018 ; class_index -> "java/io/PrintStream" 0000001A 0019 ; name_and_type_index -> "println(Ljava/lang/String;)V" ; constant_pool_index = 0x5 0000001C 07 ; tag = Class 0000001D 001A ; name_index -> "helloworld/Main" ; constant_pool_index = 0x6 0000001F 07 ; tag = Class 00000020 001B ; name_index -> "java/lang/Object" ; constant_pool_index = 0x7 00000022 01 ; tag = Utf8 00000023 0006 ; length 00000025 3C696E69743E ; bytes = " " ; constant_pool_index = 0x8 0000002B 01 ; tag = Utf8 0000002C 0003 ; length 0000002E 282956 ; bytes = "()V" ; constant_pool_index = 0x9 00000031 01 ; tag = Utf8 00000032 0004 ; length 00000034 436F6465 ; bytes = "Code" ; constant_pool_index = 0xa 00000038 01 ; tag = Utf8 00000039 000F ; length 0000003B 4C696E654E756D6265725461626C65 ; bytes = "LineNumberTable" ; constant_pool_index = 0xb 0000004A 01 ; tag = Utf8 0000004B 0012 ; length 0000004D 4C6F63616C5661726961626C655461626C65 ; bytes = "LocalVariableTable" ; constant_pool_index = 0xc 0000005F 01 ; tag = Utf8 00000060 0004 ; length 00000062 74686973 ; bytes = "this" ; constant_pool_index = 0xd 00000066 01 ; tag = Utf8 00000067 0011 ; length 00000069 4C68656C6C6F776F726C642F4D61696E3B ; bytes = "Lhelloworld/Main;" ; constant_pool_index = 0xe 0000007A 01 ; tag = Utf8 0000007B 0004 ; length 0000007D 6D61696E ; bytes = "main" ; constant_pool_index = 0xf 00000081 01 ; tag = Utf8 00000082 0016 ; length 00000084 285B4C6A6176612F6C616E672F537472696E673B2956 ; bytes = "([Ljava/lang/String;)V" ; constant_pool_index = 0x10 0000009A 01 ; tag = Utf8 0000009B 0004 ; length 0000009D 61726773 ; bytes = "args" ; constant_pool_index = 0x11 000000A1 01 ; tag = Utf8 000000A2 0013 ; length 000000A4 5B4C6A6176612F6C616E672F537472696E673B ; bytes = "[Ljava/lang/String;" ; constant_pool_index = 0x12 000000B7 01 ; tag = Utf8 000000B8 000A ; length 000000BA 536F7572636546696C65 ; bytes = "SourceFile" ; constant_pool_index = 0x13 000000C4 01 ; tag = Utf8 000000C5 0009 ; length 000000C7 4D61696E2E6A617661 ; bytes = "Main.java" ; constant_pool_index = 0x14 000000D0 0C ; tag = NameAndType 000000D1 0007 ; name_index -> " " 000000D3 0008 ; descriptor_index -> "()V" ; constant_pool_index = 0x15 000000D5 07 ; tag = Class 000000D6 001C ; name_index -> "java/lang/System" ; constant_pool_index = 0x16 000000D8 0C ; tag = NameAndType 000000D9 001D ; name_index -> "out" 000000DB 001E ; descriptor_index -> "Ljava/io/PrintStream;" ; constant_pool_index = 0x17 000000DD 01 ; tag = Utf8 000000DE 000C ; length 000000E0 48656C6C6F20776F726C6421 ; bytes = "Hello world!" ; constant_pool_index = 0x18 000000EC 07 ; tag = Class 000000ED 001F ; name_index -> "java/io/PrintStream" ; constant_pool_index = 0x19 000000EF 0C ; tag = NameAndType 000000F0 0020 ; name_index -> "println" 000000F2 0021 ; descriptor_index -> "(Ljava/lang/String;)V" ; constant_pool_index = 0x1a 000000F4 01 ; tag = Utf8 000000F5 000F ; length 000000F7 68656C6C6F776F726C642F4D61696E ; bytes = "helloworld/Main" ; constant_pool_index = 0x1b 00000106 01 ; tag = Utf8 00000107 0010 ; length 00000109 6A6176612F6C616E672F4F626A656374 ; bytes = "java/lang/Object" ; constant_pool_index = 0x1c 00000119 01 ; tag = Utf8 0000011A 0010 ; length 0000011C 6A6176612F6C616E672F53797374656D ; bytes = "java/lang/System" ; constant_pool_index = 0x1d 0000012C 01 ; tag = Utf8 0000012D 0003 ; length 0000012F 6F7574 ; bytes = "out" ; constant_pool_index = 0x1e 00000132 01 ; tag = Utf8 00000133 0015 ; length 00000135 4C6A6176612F696F2F5072696E7453747265616D3B ; bytes = "Ljava/io/PrintStream;" ; constant_pool_index = 0x1f 0000014A 01 ; tag = Utf8 0000014B 0013 ; length 0000014D 6A6176612F696F2F5072696E7453747265616D ; bytes = "java/io/PrintStream" ; constant_pool_index = 0x20 00000160 01 ; tag = Utf8 00000161 0007 ; length 00000163 7072696E746C6E ; bytes = "println" ; constant_pool_index = 0x21 0000016A 01 ; tag = Utf8 0000016B 0015 ; length 0000016D 284C6A6176612F6C616E672F537472696E673B2956 ; bytes = "(Ljava/lang/String;)V" ; constant_pool_end 00000182 0021 ; access_flags 00000184 0005 ; this_class -> "helloworld/Main" 00000186 0006 ; super_class -> "java/lang/Object" 00000188 0000 ; interfaces_count ; interfaces_start ; interfaces_end 0000018A 0000 ; fields_count ; fields_start ; fields_end 0000018C 0002 ; methods_count ; methods_start ; method_index = 0x0 0000018E 0001 ; access_flags 00000190 0007 ; name_index = " " 00000192 0008 ; descriptor_index = "()V" 00000194 0001 ; attributes_count ; attribute_index = 0x0 00000196 0009 ; attribute_name_index = "Code" 00000198 00000033 ; attribute_length ; code_start ************************************************* 0000019C 0001 ; start_pc 0000019E 0001 ; max_locals 000001A0 00000005 ; code_length 000001A4 2A ; ALOAD_0 000001A5 B70001 ; INVOKESPECIAL java/lang/Object. 000001A8 B1 ; RETURN 000001A9 0000 ; exception_table_length 000001AB 0002 ; attributes_count ; attribute_index = 0x0 000001AD 000A ; attribute_name_index = "LineNumberTable" 000001AF 0000000A ; attribute_length 000001B3 00020000000300040008 ; info ; attribute_index = 0x1 000001BD 000B ; attribute_name_index = "LocalVariableTable" 000001BF 0000000C ; attribute_length 000001C3 000100000005000C000D0000 ; info ; code_end *************************************************** ; method_index = 0x1 000001CF 0009 ; access_flags 000001D1 000E ; name_index = "main" 000001D3 000F ; descriptor_index = "([Ljava/lang/String;)V" 000001D5 0001 ; attributes_count ; attribute_index = 0x0 000001D7 0009 ; attribute_name_index = "Code" 000001D9 00000037 ; attribute_length ; code_start ************************************************* 000001DD 0002 ; start_pc 000001DF 0001 ; max_locals 000001E1 00000009 ; code_length 000001E5 B20002 ; GETSTATIC java/lang/System.out 000001E8 1203 ; LDC "Hello world!" 000001EA B60004 ; INVOKEVIRTUAL java/io/PrintStream.println 000001ED B1 ; RETURN 000001EE 0000 ; exception_table_length 000001F0 0002 ; attributes_count ; attribute_index = 0x0 000001F2 000A ; attribute_name_index = "LineNumberTable" 000001F4 0000000A ; attribute_length 000001F8 00020000000500080006 ; info ; attribute_index = 0x1 00000202 000B ; attribute_name_index = "LocalVariableTable" 00000204 0000000C ; attribute_length 00000208 000100000009001000110000 ; info ; code_end *************************************************** ; methods_end 00000214 0001 ; attributes_count ; attributes_start ; attribute_index = 0x0 00000216 0012 ; attribute_name_index = "SourceFile" 00000218 00000002 ; attribute_length 0000021C 0013 ; info ; attributes_end
You can generate "Main.class" from the disassembly code and it will be identical to the original "Main.class" file!!!
The assembly process just takes all the values in the bytecodes column and generates a file with them.
Modifications to those bytecodes will result in modifications to the class.
If you fix or add improvements to jbytecode please send them to me so I can include them in the next release.
Use the tracker to ask for support, suggest new features, etc... or interact in the forum.