⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 manual.txt

📁 一个用于对.class文件进行插桩的开源工具
💻 TXT
📖 第 1 页 / 共 4 页
字号:
2.3    Method codeNon-abstract methods contain an attribute (Code) that holds the following data:  Themaximum size of the method's stack frame, the number of local variables and an arrayof byte code instructions. Optionally, it may also contain information about the namesof local variables and source file line numbers that can be used by a debugger.    Whenever an exception is thrown, the JVM performs exception handling by lookinginto a table of exception handlers. The table marks handlers, i.e. pieces of code, to beresponsible for exceptions of certain types that are raised within a given area of the bytecode.  When there is no appropriate handler the exception is propagated back to thecaller of the method. The handler information is itself stored in an attribute containedwithin the Code attribute.2.4    Byte code offsetsTargets of branch instructions like goto are encoded as relative offsets in the array ofbyte codes.  Exception handlers and local variables refer to absolute addresses withinthe byte code. The former contains references to the start and the end of the try block,and to the instruction handler code. The latter marks the range in which a local variableis valid, i.e. its scope. This makes it difficult to insert or delete code areas on this level ofabstraction, since one has to recompute the offsets every time and update the referringobjects. We will see in section 3.3 how BCEL remedies this restriction.2.5    Type informationJava is a type-safe language and the information about the types of fields, local vari-ables, and methods is stored in signatures. These are strings stored in the constant pooland encoded in a special format.  For example the argument and return types of themain method   public  static  void  main(String[]  argv)    are represented by the signature   ([java/lang/String;)V    Classes and arrays are internally represented by strings like "java/lang/String",basic types like float by an integer number. Within signatures they are represented bysingle characters, e.g., "I", for integer.                                                  72.6    Code exampleThe following example program prompts for a number and prints the faculty of it. ThereadLine() method reading from the standard input may raise an IOException andif a misspelled number is passed to parseInt() it throws a NumberFormatExcep-tion. Thus, the critical area of code must be encapsulated in a try-catch block.import  java.io.*;public  class  Faculty  -   private  static  BufferedReader  in  =  new  BufferedReader(new                                              InputStreamReader(System.in));   public  static  final  int  fac(int  n)  -      return  (n  ==  0)?  1  :  n  *  fac(n  -  1);   "   public  static  final  int  readInt()  -      int  n  =  4711;      try  -         System.out.print("Please  enter  a  number>  ");         n  =  Integer.parseInt(in.readLine());      "  catch(IOException  e1)  -  System.err.println(e1);  "         catch(NumberFormatException  e2)  -  System.err.println(e2);  "      return  n;   "   public  static  void  main(String[]  argv)  -      int  n  =  readInt();      System.out.println("Faculty  of  "  +  n  +  "  is  "  +  fac(n));   ""    This code example typically compiles to the following chunks of byte code:2.6.1   Method fac0:   iload`01:   ifne                 #84:   iconst`15:   goto                 #168:   iload`09:   iload`010:  iconst`111:  isub12:  invokestatic      Faculty.fac  (I)I  (12)15:  imul16:  ireturnLocalVariable(start`pc  =  0,  length  =  16,  index  =  0:int  n)                                                  8    The method fac has only one local variable, the argument n, stored in slot 0. This variable'sscope ranges from the start of the byte code sequence to the very end. If the value of n (storedin local variable 0, i.e. the value fetched with iload_0) is not equal to 0, the ifne instructionbranches to the byte code at offset 8, otherwise a 1 is pushed onto the operand stack and the con-trol flow branches to the final return. For ease of reading, the offsets of the branch instructions,which are actually relative, are displayed as absolute addresses in these examples.    If recursion has to continue, the arguments for the multiplication (n and fac(n  -  1)) areevaluated and the results pushed onto the operand stack. After the multiplication operation hasbeen performed the function returns the computed value from the top of the stack.2.6.2   Method readInt0:   sipush            47113:   istore`04:   getstatic       java.lang.System.out  Ljava/io/PrintStream;7:   ldc                "Please  enter  a  number>  "9:   invokevirtual  java.io.PrintStream.print  (Ljava/lang/String;)V12:  getstatic       Faculty.in  Ljava/io/BufferedReader;15:  invokevirtual  java.io.BufferedReader.readLine  ()Ljava/lang/String;18:  invokestatic   java.lang.Integer.parseInt  (Ljava/lang/String;)I21:  istore`022:  goto               #4425:  astore`126:  getstatic       java.lang.System.err  Ljava/io/PrintStream;29:  aload`130:  invokevirtual  java.io.PrintStream.println  (Ljava/lang/Object;)V33:  goto               #4436:  astore`137:  getstatic       java.lang.System.err  Ljava/io/PrintStream;40:  aload`141:  invokevirtual  java.io.PrintStream.println  (Ljava/lang/Object;)V44:  iload`045:  ireturnException  handler(s)  =From      To         Handler  Type4          22         25         java.io.IOException(6)4          22         36         NumberFormatException(10)    First the local variable n (in slot 0) is initialized to the value 4711.  The next instruction,getstatic, loads the static System.out field onto the stack.  Then a string is loaded andprinted, a number read from the standard input and assigned to n.    If one of the called methods (readLine() and parseInt()) throws an exception, the JavaVirtual Machine calls one of the declared exception handlers, depending on the type of the ex-ception. The try-clause itself does not produce any code, it merely defines the range in whichthe following handlers are active. In the example the specified source code area maps to a byte                                                  9code area ranging from offset 4 (inclusive) to 22 (exclusive). If no exception has occurred ("nor-mal" execution flow) the goto instructions branch behind the handler code. There the value ofn is loaded and returned.    For example the handler for java.io.IOException starts at offset 25. It simply prints theerror and branches back to the normal execution flow, i.e. as if no exception had occurred.3     The BCEL APIThe BCEL API abstracts from the concrete circumstances of the Java Virtual Machine and howto read and write binary Java class files. The API mainly consists of three parts:    1. A package that contains classes that describe "static" constraints of class files, i.e., ref* *lect       the class file format and is not intended for byte code modifications. The classes may be       used to read and write class files from or to a file. This is useful especially for analyzing       Java classes without having the source files at hand.  The main data structure is called       JavaClass which contains methods, fields, etc..    2. A package to dynamically generate or modify JavaClass objects. It may be used e.g. to       insert analysis code, to strip unnecessary information from class files, or to implement the       code generator back-end of a Java compiler.    3. Various code examples and utilities like a class file viewer, a tool to convert class files * *into       HTML, and a converter from class files to the Jasmin assembly language [MD97   ].3.1    JavaClassThe "static" component of the BCEL API resides in the package de.fub.bytecode.classfileand represents class files. All of the binary components and data structures declared in the JVMspecification [LY97 ] and described in section 2 are mapped to classes. Figure 3 shows an UMLdiagram of the hierarchy of classes of the BCEL API. Figure 8 in the appendix also shows adetailed diagram of the ConstantPool components.    The top-level data structure is JavaClass, which in most cases is created by a ClassPar-ser object that is capable of parsing binary class files. A JavaClass object basically consists offields, methods, symbolic references to the super class and to the implemented interfaces.    The constant pool serves as some kind of central repository and is thus of outstanding impor-tance for all components. ConstantPool objects contain an array of fixed size of Constantentries, which may be retrieved via the getConstant() method taking an integer index asargument.  Indexes to the constant pool may be contained in instructions as well as in othercomponents of a class file and in constant pool entries themselves.    Methods and fields contain a signature, symbolically defining their types. Access flags likepublic  static  final occur in several places and are encoded by an integer bit mask, e.g.public  static  final matches to the Java expression   int  access`flags  =  ACC`PUBLIC  --  ACC`STATIC  --  ACC`FINAL;                                                 10Figure 3: UML diagram for the BCEL API                       11    As mentioned in section 2.1 already, several components may contain attribute objects: classes,fields, methods, and Code objects (introduced in section 2.3). The latter is an attribute itself th* *atcontains the actual byte code array, the maximum stack size, the number of local variables, atable of handled exceptions, and some optional debugging information coded as LineNum-berTable and LocalVariableTable attributes.  Attributes are in general specific to somedata structure, i.e. no two components share the same kind of attribute, though this is not ex-plicitly forbidden.  In the figure the Attribute classes are marked with the component theybelong to.3.2    Class repositoryUsing the provided Repository class, reading class files into a JavaClass object is quitesimple:   JavaClass  clazz  =  Repository.lookupClass("java.lang.String");    The repository also contains methods providing the dynamic equivalent of the instanceofoperator, and other useful routines:   if(Repository.instanceOf(clazz,  super`class)  -      ...   "3.2.1   Accessing class file dataInformation within the class file components may be accessed like Java Beans via intuitiveset/get methods. All of them also define a toString() method so that implementing a simpleclass viewer is very easy. In fact all of the examples used here have been produced this way:   System.out.println(clazz);   printCode(clazz.getMethods());   ...   public  static  void  printCode(Method[]  methods)  -      for(int  i=0;  i  <  methods.length;  i++)  -         System.out.println(methods[i]);         Code  code  =  methods[i].getCode();         if(code  !=  null)  //  Non-abstract  method            System.out.println(code);      "   "3.2.2   Analyzing class dataLast but not least, BCEL supports the Visitor design pattern [GHJV95   ], so one can write visitorobjects to traverse and analyze the contents of a class file. Included in the distribution is a cla* *ssJasminVisitor that converts class files into the Jasmin assembler language [MD97   ].                                                 123.3    ClassGenThis part of the API (package ork.apache.bcel.generic) supplies an abstraction level forcreating or transforming class files dynamically. It makes the static constraints of Java class fil* *eslike the hard-coded byte code addresses generic.  The generic constant pool, for example, isimplemented by the class ConstantPoolGen which offers methods for adding different typesof constants. Accordingly, ClassGen offers an interface to add methods, fields, and attributes.Figure 4 gives an overview of this part of the API.3.3.1   TypesWe abstract from the concrete details of the type signature syntax (see 2.5) by introducing theType class, which is used, for example, by methods to define their return and argument types.Concrete sub-classes are BasicType, ObjectType, and ArrayType which consists of the el-ement type and the number of dimensions.  For commonly used types the class offers somepredefined constants. For example the method signature of the main method as shown in sec-tion 2.5 is represented by:   Type     return`type  =  Type.VOID;   Type[]  arg`types     =  new  Type[]  -  new  ArrayType(Type.STRING,  1)  ";    Type also contains methods to convert types into textual signatures and vice versa. The sub-classes contain implementations of the routines and constraints specified by the Java LanguageSpecification [GJS96 ].3.3.2   Generic fields and methodsFields are represented by FieldGen objects, which may be freely modified by the user. If theyhave the access rights static  final, i.e. are constants and of basic type, they may optionallyhave an initializing value.    Generic methods contain methods to add exceptions the method may throw, local variables,and exception handlers. The latter two are represented by user-configurable objects as well. Be-cause exception handlers and local variables contain references to byte code addresses, they alsotake the role of an instruction targeter in our terminology. Instruction targeters contain a methodupdateTarget() to redirect a reference.  Generic (non-abstract) methods refer to instructionlists that consist of instruction objects.  References to byte code addresses are implemented byhandles to instruction objects. This is explained in more detail in the following sections.    The maximum stack size needed by the method and the maximum number of local vari-ables used may be set manually or computed via the setMaxStack() and setMaxLocals()methods automatically.3.3.3   InstructionsModeling instructions as objects may look somewhat odd at first sight, but in fact enables pro-grammers to obtain a high-level view upon control flow without handling details like concretebyte code offsets. Instructions consist of a tag, i.e. an opcode, their length in bytes and an offs* *et                                                 13Figure 4: UML diagram of the ClassGen API                        14(or index) within the byte code.  Since many instructions are immutable, the Instruction-Constants interface offers shareable predefined "fly-weight" constants to use.    Instructions are grouped via sub-classing, the type hierarchy of instruction classes is illus-

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -