javaclass

bytecode.py

5:d18e689a422d
2004-10-29 Paul Boddie Added a class for the reading and conversion of Java bytecodes, moved the bytecode table into this class, added some initial conversion methods.
     1 #!/usr/bin/env python     2      3 """     4 Java bytecode conversion. Specification found at the following URL:     5 http://java.sun.com/docs/books/vmspec/2nd-edition/html/Instructions2.doc.html     6      7 NOTE: Synchronized constructs are not actually supported.     8 """     9     10 import dis # for access to Python bytecode values    11     12 # Bytecode production classes.    13     14 class BytecodeWriter:    15     def __init__(self):    16         self.loops = []    17         self.jumps = []    18         self.output = []    19         self.position = 0    20     21     # Special methods.    22     23     def end_loop(self):    24         current_loop_start = self.loops.pop()    25         self.jump_absolute(current_loop_start)    26         self.output[current_loop_start + 1] = self.position    27         self.pop_block()    28     29     def jump_to_next(self, status):    30         self.jumps.push(self.position)    31         if status:    32             self.jump_if_true()    33         else:    34             self.jump_if_false()    35     36     def start_next(self):    37         current_jump_start = self.jumps.pop()    38         self.output[current_jump_start + 1] = self.position    39     40     # Normal bytecode generators.    41     42     def for_iter(self):    43         self.loops.push(self.position)    44         self.output.append(opmap["FOR_ITER"])    45         self.output.append(None) # To be filled in later    46         self.position += 2    47     48     def jump_if_false(self, offset=None):    49         self.output.append(opmap["JUMP_IF_FALSE"])    50         self.output.append(offset) # May be filled in later    51         self.position += 2    52     53     def jump_if_true(self, offset=None):    54         self.output.append(opmap["JUMP_IF_TRUE"])    55         self.output.append(offset) # May be filled in later    56         self.position += 2    57     58 # Bytecode conversion.    59     60 class BytecodeReader:    61     def __init__(self, class_file):    62         self.class_file = class_file    63         self.position_mapping = {}    64     65     def process(self, code, program):    66         self.java_position = 0    67         while self.java_position < len(code):    68             self.position_mapping[self.java_position] = program.position    69             bytecode = ord(code[self.java_position])    70             mnemonic, number_of_arguments = self.java_bytecodes[bytecode]    71             self.process_bytecode(mnemonic, number_of_arguments)    72     73     def process_bytecode(self, mnemonic, number_of_arguments):    74         if number_of_arguments is not None:    75             arguments = []    76             for j in range(0, number_of_arguments):    77                 arguments.append(ord(code[self.java_position + 1 + j]))    78     79             # Call the handler.    80             getattr(self, mnemonic)(arguments, program)    81         else:    82             # Call the handler.    83             number_of_arguments = getattr(self, mnemonic)(code[self.java_position+1:], program)    84     85         self.java_position = self.java_position + 1 + number_of_arguments    86     87     def nop(self, arguments, program):    88         pass    89     90     def aaload(self, arguments, program):    91         # NOTE: No type checking performed.    92         program.binary_subscr()    93     94     def aastore(self, arguments, program):    95         # NOTE: No type checking performed.    96         # Stack: arrayref, index, value    97         program.rot_three() # Stack: value, arrayref, index    98         program.store_subscr()    99    100     def aconst_null(self, arguments, program):   101         program.load_global(None)   102    103     def aload(self, arguments, program):   104         program.load_fast(arguments[0])   105    106     def aload_0(self, arguments, program):   107         program.load_fast(0)   108    109     def aload_1(self, arguments, program):   110         program.load_fast(1)   111    112     def aload_2(self, arguments, program):   113         program.load_fast(2)   114    115     def aload_3(self, arguments, program):   116         program.load_fast(3)   117    118     def anewarray(self, arguments, program):   119         # NOTE: Does not raise NegativeArraySizeException.   120         # NOTE: Not using the index to type the list/array.   121         index = arguments[0] << 8 + arguments[1]   122    123         program.build_list()   124         program.setup_loop()   125         program.load_global("range")   126         program.load_const(0)       # Stack: list, count, range, 0   127         program.rot_three()         # Stack: list, 0, count, range   128         program.rot_three()         # Stack: list, range, 0, count   129         program.call_function(2)    # Stack: list, range_list   130         program.get_iter()          # Stack: list, iter   131         program.for_iter()          # Stack: list, iter, value   132         program.pop_top()           # Stack: list, iter   133         program.rot_two()           # Stack: iter, list   134         program.dup_top()           # Stack: iter, list, list   135         program.load_attr("append") # Stack: iter, list, append   136         program.load_global(None)   # Stack: iter, list, append, None   137         program.call_function(1)    # Stack: iter, list, None   138         program.pop_top()           # Stack: iter, list   139         program.rot_two()           # Stack: list, iter   140         program.end_loop()          # Back to for_iter above   141    142     def areturn(self, arguments, program):   143         program.return_value()   144    145     def arraylength(self, arguments, program):   146         program.load_global("len")  # Stack: arrayref, len   147         program.rot_two()           # Stack: len, arrayref   148         program.call_function(1)   149    150     def astore(self, arguments, program):   151         program.store_fast(arguments[0])   152    153     def astore_0(self, arguments, program):   154         program.store_fast(0)   155    156     def astore_1(self, arguments, program):   157         program.store_fast(1)   158    159     def astore_2(self, arguments, program):   160         program.store_fast(2)   161    162     def astore_3(self, arguments, program):   163         program.store_fast(3)   164    165     def athrow(self, arguments, program):   166         # NOTE: NullPointerException not raised where null/None is found on the stack.   167         program.raise_varargs(1)   168    169     baload = aaload   170     bastore = aastore   171    172     def bipush(self, arguments, program):   173         program.load_const(arguments[0])   174    175     caload = aaload   176     castore = aastore   177    178     def checkcast(self, arguments, program):   179         index = arguments[0] << 8 + arguments[1]   180         target_name = self.class_file.constants[index - 1].get_name()   181         target_components = target_name.split("/")   182    183         program.dup_top()                   # Stack: objectref, objectref   184         program.load_global("isinstance")   # Stack: objectref, objectref, isinstance   185         program.rot_two()                   # Stack: objectref, isinstance, objectref   186         program.load_global(target_components[0])   187         for target_component in target_components[1:]:   188             program.load_attr(target_component)   189         program.call_function(2)            # Stack: objectref   190    191     def d2f(self, arguments, program):   192         pass   193    194     def d2i(self, arguments, program):   195         program.load_global("int")  # Stack: value, int   196         program.rot_two()           # Stack: int, value   197         program.call_function(1)    # Stack: result   198    199     d2l = d2i # Preserving Java semantics   200    201     def dadd(self, arguments, program):   202         # NOTE: No type checking performed.   203         program.binary_add()   204    205     daload = aaload   206     dastore = aastore   207    208     def dcmpg(self, arguments, program):   209         # NOTE: No type checking performed.   210         program.compare_op(">")   211    212     def dcmpl(self, arguments, program):   213         # NOTE: No type checking performed.   214         program.compare_op("<")   215    216     def dconst_0(self, arguments, program):   217         program.load_const(0.0)   218    219     def dconst_1(self, arguments, program):   220         program.load_const(1.0)   221    222     def ddiv(self, arguments, program):   223         # NOTE: No type checking performed.   224         program.binary_divide()   225    226     dload = aload   227     dload_0 = aload_0   228     dload_1 = aload_1   229     dload_2 = aload_2   230     dload_3 = aload_3   231    232     def dmul(self, arguments, program):   233         # NOTE: No type checking performed.   234         program.binary_multiply()   235    236     def dneg(self, arguments, program):   237         # NOTE: No type checking performed.   238         program.unary_negative()   239    240     def drem(self, arguments, program):   241         # NOTE: No type checking performed.   242         program.binary_modulo()   243    244     dreturn = areturn   245     dstore = astore   246     dstore_0 = astore_0   247     dstore_1 = astore_1   248     dstore_2 = astore_2   249     dstore_3 = astore_3   250    251     def dsub(self, arguments, program):   252         # NOTE: No type checking performed.   253         program.binary_subtract()   254    255     def dup(self, arguments, program):   256         program.dup_top()   257    258     def dup_x1(self, arguments, program):   259         # Ignoring computational type categories.   260         program.dup_top()   261         program.rot_three()   262    263     def dup_x2(self, arguments, program):   264         # Ignoring computational type categories.   265         program.dup_top()   266         program.rot_four()   267    268     dup2 = dup # Ignoring computational type categories   269     dup2_x1 = dup_x1 # Ignoring computational type categories   270     dup2_x2 = dup_x2 # Ignoring computational type categories   271    272     def f2d(self, arguments, program):   273         pass # Preserving Java semantics   274    275     def f2i(self, arguments, program):   276         program.load_global("int")  # Stack: value, int   277         program.rot_two()           # Stack: int, value   278         program.call_function(1)    # Stack: result   279    280     f2l = f2i # Preserving Java semantics   281     fadd = dadd   282     faload = daload   283     fastore = dastore   284     fcmpg = dcmpg   285     fcmpl = dcmpl   286     fconst_0 = dconst_0   287     fconst_1 = dconst_1   288    289     def fconst_2(self, arguments, program):   290         program.load_const(2.0)   291    292     fdiv = ddiv   293     fload = dload   294     fload_0 = dload_0   295     fload_1 = dload_1   296     fload_2 = dload_2   297     fload_3 = dload_3   298     fmul = dmul   299     fneg = dneg   300     frem = drem   301     freturn = dreturn   302     fstore = dstore   303     fstore_0 = dstore_0   304     fstore_1 = dstore_1   305     fstore_2 = dstore_2   306     fstore_3 = dstore_3   307     fsub = dsub   308    309     def getfield(self, arguments, program):   310         index = arguments[0] << 8 + arguments[1]   311         target_name = self.class_file.constants[index - 1].get_name()   312         # NOTE: Using the string version of the name which may contain incompatible characters.   313         program.load_attr(str(target_name))   314    315     getstatic = getfield # Ignoring Java restrictions   316    317     def goto(self, arguments, program):   318         offset = arguments[0] << 8 + arguments[1]   319         java_absolute = self.java_position + offset   320         program.jump_absolute(self.position_mapping[java_absolute])   321    322     def goto_w(self, arguments, program):   323         offset = arguments[0] << 24 + arguments[1] << 16 + arguments[2] << 8 + arguments[3]   324         java_absolute = self.java_position + offset   325         program.jump_absolute(self.position_mapping[java_absolute])   326    327     def i2b(self, arguments, program):   328         pass   329    330     def i2c(self, arguments, program):   331         program.load_global("chr")  # Stack: value, chr   332         program.rot_two()           # Stack: chr, value   333         program.call_function(1)    # Stack: result   334    335     def i2d(self, arguments, program):   336         program.load_global("float")    # Stack: value, float   337         program.rot_two()               # Stack: float, value   338         program.call_function(1)        # Stack: result   339    340     i2f = i2d # Not distinguishing between float and double   341    342     def i2l(self, arguments, program):   343         pass # Preserving Java semantics   344    345     def i2s(self, arguments, program):   346         pass # Not distinguishing between int and short   347    348     iadd = fadd   349     iaload = faload   350    351     def iand(self, arguments, program):   352         # NOTE: No type checking performed.   353         program.binary_and()   354    355     iastore = fastore   356    357     def iconst_m1(self, arguments, program):   358         program.load_const(-1)   359    360     def iconst_0(self, arguments, program):   361         program.load_const(0)   362    363     def iconst_1(self, arguments, program):   364         program.load_const(1)   365    366     def iconst_2(self, arguments, program):   367         program.load_const(2)   368    369     def iconst_3(self, arguments, program):   370         program.load_const(3)   371    372     def iconst_4(self, arguments, program):   373         program.load_const(4)   374    375     def iconst_5(self, arguments, program):   376         program.load_const(5)   377    378     idiv = fdiv   379    380     def _if_xcmpx(self, arguments, program, op):   381         offset = arguments[0] << 8 + arguments[1]   382         java_absolute = self.java_position + offset   383         program.compare_op(op)   384         program.jump_to_next(0) # skip if false   385         program.goto(offset)   386         program.start_next()   387    388     def if_acmpeq(self, arguments, program):   389         # NOTE: No type checking performed.   390         self._if_xcmpx(arguments, program, "is")   391    392     def if_acmpne(self, arguments, program):   393         # NOTE: No type checking performed.   394         self._if_xcmpx(arguments, program, "is not")   395    396     def if_icmpeq(self, arguments, program):   397         # NOTE: No type checking performed.   398         self._if_xcmpx(arguments, program, "==")   399    400     def if_icmpne(self, arguments, program):   401         # NOTE: No type checking performed.   402         self._if_xcmpx(arguments, program, "!=")   403    404     def if_icmplt(self, arguments, program):   405         # NOTE: No type checking performed.   406         self._if_xcmpx(arguments, program, "<")   407    408     def if_icmpge(self, arguments, program):   409         # NOTE: No type checking performed.   410         self._if_xcmpx(arguments, program, ">=")   411    412     def if_icmpgt(self, arguments, program):   413         # NOTE: No type checking performed.   414         self._if_xcmpx(arguments, program, ">")   415    416     def if_icmple(self, arguments, program):   417         # NOTE: No type checking performed.   418         self._if_xcmpx(arguments, program, "<=")   419    420     def ifeq(self, arguments, program):   421         # NOTE: No type checking performed.   422         program.load_const(0)   423         self._if_xcmpx(arguments, program, "==")   424    425     def ifne(self, arguments, program):   426         # NOTE: No type checking performed.   427         program.load_const(0)   428         self._if_xcmpx(arguments, program, "!=")   429    430     def iflt(self, arguments, program):   431         # NOTE: No type checking performed.   432         program.load_const(0)   433         self._if_xcmpx(arguments, program, "<")   434    435     def ifge(self, arguments, program):   436         # NOTE: No type checking performed.   437         program.load_const(0)   438         self._if_xcmpx(arguments, program, ">=")   439    440     def ifgt(self, arguments, program):   441         # NOTE: No type checking performed.   442         program.load_const(0)   443         self._if_xcmpx(arguments, program, ">")   444    445     def ifle(self, arguments, program):   446         # NOTE: No type checking performed.   447         program.load_const(0)   448         self._if_xcmpx(arguments, program, "<=")   449    450     def ifnonnull(self, arguments, program):   451         # NOTE: No type checking performed.   452         program.load_const(None)   453         self._if_xcmpx(arguments, program, "is not")   454    455     def ifnull(self, arguments, program):   456         # NOTE: No type checking performed.   457         program.load_const(None)   458         self._if_xcmpx(arguments, program, "is")   459    460     def iinc(self, arguments, program):   461         # NOTE: No type checking performed.   462         program.load_fast(arguments[0])   463         program.load_const(arguments[1])   464         program.binary_add()   465    466     iload = fload   467     iload_0 = fload_0   468     iload_1 = fload_1   469     iload_2 = fload_2   470     iload_3 = fload_3   471     imul = fmul   472     ineg = fneg   473    474     def instanceof(self, arguments, program):   475         index = arguments[0] << 8 + arguments[1]   476         target_name = self.class_file.constants[index - 1].get_name()   477         target_components = target_name.split("/")   478    479         program.load_global("isinstance")   # Stack: objectref, isinstance   480         program.rot_two()                   # Stack: isinstance, objectref   481         program.load_global(target_components[0])   482         for target_component in target_components[1:]:   483             program.load_attr(target_component)   484         program.call_function(2)            # Stack: result   485    486     def _invoke(self, target_name, program):   487         program.rot_two()                   # Stack: tuple, objectref   488         # NOTE: Using the string version of the name which may contain incompatible characters.   489         program.load_attr(str(target_name)) # Stack: tuple, method   490         program.rot_two()                   # Stack: method, tuple   491         program.load_global("apply")        # Stack: method, tuple, apply   492         program.rot_three()                 # Stack: apply, method, tuple   493         program.call_function(2)   494    495     def invokeinterface(self, arguments, program):   496         # NOTE: This implementation does not perform the necessary checks for   497         # NOTE: signature-based polymorphism.   498         # NOTE: Java rules not specifically obeyed.   499         index = arguments[0] << 8 + arguments[1]   500         count = arguments[2]   501         target_name = self.class_file.constants[index - 1].get_name()   502         # Stack: objectref, arg1, arg2, ...   503         program.build_tuple(count)          # Stack: objectref, tuple   504         self._invoke(target_name, program)   505    506     def invokespecial(self, arguments, program):   507         # NOTE: This implementation does not perform the necessary checks for   508         # NOTE: signature-based polymorphism.   509         # NOTE: Java rules not specifically obeyed.   510         index = arguments[0] << 8 + arguments[1]   511         target = self.class_file.constants[index - 1]   512         target_name = target.get_name()   513         # Get the number of parameters from the descriptor.   514         count = len(target.get_descriptor()[0])   515         # Stack: objectref, arg1, arg2, ...   516         program.build_tuple(count)          # Stack: objectref, tuple   517         self._invoke(target_name, program)   518    519     def invokestatic(self, arguments, program):   520         # NOTE: This implementation does not perform the necessary checks for   521         # NOTE: signature-based polymorphism.   522         # NOTE: Java rules not specifically obeyed.   523         index = arguments[0] << 8 + arguments[1]   524         target = self.class_file.constants[index - 1]   525         target_name = target.get_name()   526         # Get the number of parameters from the descriptor.   527         count = len(target.get_descriptor()[0])   528         # Stack: arg1, arg2, ...   529         program.build_tuple(count)  # Stack: tuple   530         # NOTE: Should probably use Python static methods.   531         program.load_name("self")   # Stack: tuple, self   532         self._invoke(target_name, program)   533    534     invokevirtual = invokeinterface # Ignoring Java rules   535    536     def ior(self, arguments, program):   537         # NOTE: No type checking performed.   538         program.binary_or()   539    540     irem = frem   541     ireturn = freturn   542    543     def ishl(self, arguments, program):   544         # NOTE: No type checking performed.   545         # NOTE: Not verified.   546         program.binary_lshift()   547    548     def ishr(self, arguments, program):   549         # NOTE: No type checking performed.   550         # NOTE: Not verified.   551         program.binary_rshift()   552    553     istore = fstore   554     istore_0 = fstore_0   555     istore_1 = fstore_1   556     istore_2 = fstore_2   557     istore_3 = fstore_3   558     isub = fsub   559     iushr = ishr # Ignoring distinctions between arithmetic and logical shifts   560    561     def ishr(self, arguments, program):   562         # NOTE: No type checking performed.   563         program.binary_xor()   564    565     def jsr(self, arguments, program):   566         offset = arguments[0] << 8 + arguments[1]   567         java_absolute = self.java_position + offset   568         # NOTE: To be implemented.   569    570     def wide(self, code, program):   571         # NOTE: To be implemented.   572         return number_of_arguments   573    574     java_bytecodes = {   575         # code : (mnemonic, number of following bytes, change in stack)   576         0 : ("nop", 0),   577         1 : ("aconst_null", 0),   578         2 : ("iconst_m1", 0),   579         3 : ("iconst_0", 0),   580         4 : ("iconst_1", 0),   581         5 : ("iconst_2", 0),   582         6 : ("iconst_3", 0),   583         7 : ("iconst_4", 0),   584         8 : ("iconst_5", 0),   585         9 : ("lconst_0", 0),   586         10 : ("lconst_1", 0),   587         11 : ("fconst_0", 0),   588         12 : ("fconst_1", 0),   589         13 : ("fconst_2", 0),   590         14 : ("dconst_0", 0),   591         15 : ("dconst_1", 0),   592         16 : ("bipush", 1),   593         17 : ("sipush", 2),   594         18 : ("ldc", 1),   595         19 : ("ldc_w", 2),   596         20 : ("ldc2_w", 2),   597         21 : ("iload", 1),   598         22 : ("lload", 1),   599         23 : ("fload", 1),   600         24 : ("dload", 1),   601         25 : ("aload", 1),   602         26 : ("iload_0", 0),   603         27 : ("iload_1", 0),   604         28 : ("iload_2", 0),   605         29 : ("iload_3", 0),   606         30 : ("lload_0", 0),   607         31 : ("lload_1", 0),   608         32 : ("lload_2", 0),   609         33 : ("lload_3", 0),   610         34 : ("fload_0", 0),   611         35 : ("fload_1", 0),   612         36 : ("fload_2", 0),   613         37 : ("fload_3", 0),   614         38 : ("dload_0", 0),   615         39 : ("dload_1", 0),   616         40 : ("dload_2", 0),   617         41 : ("dload_3", 0),   618         42 : ("aload_0", 0),   619         43 : ("aload_1", 0),   620         44 : ("aload_2", 0),   621         45 : ("aload_3", 0),   622         46 : ("iaload", 0),   623         47 : ("laload", 0),   624         48 : ("faload", 0),   625         49 : ("daload", 0),   626         50 : ("aaload", 0),   627         51 : ("baload", 0),   628         52 : ("caload", 0),   629         53 : ("saload", 0),   630         54 : ("istore", 1),   631         55 : ("lstore", 1),   632         56 : ("fstore", 1),   633         57 : ("dstore", 1),   634         58 : ("astore", 1),   635         59 : ("istore_0", 0),   636         60 : ("istore_1", 0),   637         61 : ("istore_2", 0),   638         62 : ("istore_3", 0),   639         63 : ("lstore_0", 0),   640         64 : ("lstore_1", 0),   641         65 : ("lstore_2", 0),   642         66 : ("lstore_3", 0),   643         67 : ("fstore_0", 0),   644         68 : ("fstore_1", 0),   645         69 : ("fstore_2", 0),   646         70 : ("fstore_3", 0),   647         71 : ("dstore_0", 0),   648         72 : ("dstore_1", 0),   649         73 : ("dstore_2", 0),   650         74 : ("dstore_3", 0),   651         75 : ("astore_0", 0),   652         76 : ("astore_1", 0),   653         77 : ("astore_2", 0),   654         78 : ("astore_3", 0),   655         79 : ("iastore", 0),   656         80 : ("lastore", 0),   657         81 : ("fastore", 0),   658         82 : ("dastore", 0),   659         83 : ("aastore", 0),   660         84 : ("bastore", 0),   661         85 : ("castore", 0),   662         86 : ("sastore", 0),   663         87 : ("pop", 0),   664         88 : ("pop2", 0),   665         89 : ("dup", 0),   666         90 : ("dup_x1", 0),   667         91 : ("dup_x2", 0),   668         92 : ("dup2", 0),   669         93 : ("dup2_x1", 0),   670         94 : ("dup2_x2", 0),   671         95 : ("swap", 0),   672         96 : ("iadd", 0),   673         97 : ("ladd", 0),   674         98 : ("fadd", 0),   675         99 : ("dadd", 0),   676         100 : ("isub", 0),   677         101 : ("lsub", 0),   678         102 : ("fsub", 0),   679         103 : ("dsub", 0),   680         104 : ("imul", 0),   681         105 : ("lmul", 0),   682         106 : ("fmul", 0),   683         107 : ("dmul", 0),   684         108 : ("idiv", 0),   685         109 : ("ldiv", 0),   686         110 : ("fdiv", 0),   687         111 : ("ddiv", 0),   688         112 : ("irem", 0),   689         113 : ("lrem", 0),   690         114 : ("frem", 0),   691         115 : ("drem", 0),   692         116 : ("ineg", 0),   693         117 : ("lneg", 0),   694         118 : ("fneg", 0),   695         119 : ("dneg", 0),   696         120 : ("ishl", 0),   697         121 : ("lshl", 0),   698         122 : ("ishr", 0),   699         123 : ("lshr", 0),   700         124 : ("iushr", 0),   701         125 : ("lushr", 0),   702         126 : ("iand", 0),   703         127 : ("land", 0),   704         128 : ("ior", 0),   705         129 : ("lor", 0),   706         130 : ("ixor", 0),   707         131 : ("lxor", 0),   708         132 : ("iinc", 2),   709         133 : ("i2l", 0),   710         134 : ("i2f", 0),   711         135 : ("i2d", 0),   712         136 : ("l2i", 0),   713         137 : ("l2f", 0),   714         138 : ("l2d", 0),   715         139 : ("f2i", 0),   716         140 : ("f2l", 0),   717         141 : ("f2d", 0),   718         142 : ("d2i", 0),   719         143 : ("d2l", 0),   720         144 : ("d2f", 0),   721         145 : ("i2b", 0),   722         146 : ("i2c", 0),   723         147 : ("i2s", 0),   724         148 : ("lcmp", 0),   725         149 : ("fcmpl", 0),   726         150 : ("fcmpg", 0),   727         151 : ("dcmpl", 0),   728         152 : ("dcmpg", 0),   729         153 : ("ifeq", 2),   730         154 : ("ifne", 2),   731         155 : ("iflt", 2),   732         156 : ("ifge", 2),   733         157 : ("ifgt", 2),   734         158 : ("ifle", 2),   735         159 : ("if_icmpeq", 2),   736         160 : ("if_icmpne", 2),   737         161 : ("if_icmplt", 2),   738         162 : ("if_icmpge", 2),   739         163 : ("if_icmpgt", 2),   740         164 : ("if_icmple", 2),   741         165 : ("if_acmpeq", 2),   742         166 : ("if_acmpne", 2),   743         167 : ("goto", 2),   744         168 : ("jsr", 2),   745         169 : ("ret", 1),   746         170 : ("tableswitch", None), # variable number of arguments   747         171 : ("lookupswitch", None), # variable number of arguments   748         172 : ("ireturn", 0),   749         173 : ("lreturn", 0),   750         174 : ("freturn", 0),   751         175 : ("dreturn", 0),   752         176 : ("areturn", 0),   753         177 : ("return", 0),   754         178 : ("getstatic", 2),   755         179 : ("putstatic", 2),   756         180 : ("getfield", 2),   757         181 : ("putfield", 2),   758         182 : ("invokevirtual", 2),   759         183 : ("invokespecial", 2),   760         184 : ("invokestatic", 2),   761         185 : ("invokeinterface", 4),   762         187 : ("new", 2),   763         188 : ("newarray", 1),   764         189 : ("anewarray", 2),   765         190 : ("arraylength", 0),   766         191 : ("athrow", 0),   767         192 : ("checkcast", 2),   768         193 : ("instanceof", 2),   769         194 : ("monitorenter", 0),   770         195 : ("monitorexit", 0),   771         196 : ("wide", None), # 3 or 5 arguments, stack changes according to modified element   772         197 : ("multianewarray", 3),   773         198 : ("ifnull", 2),   774         199 : ("ifnonnull", 2),   775         200 : ("goto_w", 4),   776         201 : ("jsr_w", 4),   777         }   778    779 if __name__ == "__main__":   780     import sys   781     from classfile import ClassFile   782     f = open(sys.argv[1])   783     c = ClassFile(f.read())   784    785 # vim: tabstop=4 expandtab shiftwidth=4