jbytecode

Project home page

jbytecode is a Java bytecode disassembler/assembler written in Python.

Why is jbytecode unique?

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!!!

Example

This is the Java code for the "Hello World" example ("helloworld.Main" Java class, "Main.class" file).

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:

  • First column is the offset in the input file
  • Second column is the bytecodes
  • Comment on the left is the interpretation of those bytecodes

    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!!!

    Things to know

    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.

    Support

    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.

    Download jbytecode 0.4 (2006-07-16)

    Support This Project

    SourceForge.net Logo