/** * Get constant from constant pool. * * @param index Index in constant pool * @return Constant value * @see Constant */ public Constant getConstant(int index) { if (index >= constant_pool.length || index < 0) throw new ClassFormatException("Invalid constant pool reference: " + index + ". Constant pool size is: " + constant_pool.length); return constant_pool[index]; }
/** * Get constant from constant pool. * * @param index Index in constant pool * @return Constant value * @see Constant */ public Constant getConstant(int index) { if (index >= constant_pool.length || index < 0) throw new ClassFormatException("Invalid constant pool reference: " + index + ". Constant pool size is: " + constant_pool.length); return constant_pool[index]; }
/** * Check whether the header of the file is ok. * Of course, this has to be the first action on successive file reads. * @throws IOException * @throws ClassFormatException */ private final void readID() throws IOException, ClassFormatException { int magic = 0xCAFEBABE; if(file.readInt() != magic) throw new ClassFormatException(file_name + " is not a Java .class file"); } /**
/** * Check whether the header of the file is ok. * Of course, this has to be the first action on successive file reads. * @throws IOException * @throws ClassFormatException */ private final void readID() throws IOException, ClassFormatException { int magic = 0xCAFEBABE; if(file.readInt() != magic) throw new ClassFormatException(file_name + " is not a Java .class file"); } /**
/** * Return type of signature as a byte value as defined in <em>Constants</em> * * @param signature in format described above * @return type of signature * @see Constants */ public static final byte typeOfSignature(String signature) throws ClassFormatException { try { switch(signature.charAt(0)) { case 'B' : return Constants.T_BYTE; case 'C' : return Constants.T_CHAR; case 'D' : return Constants.T_DOUBLE; case 'F' : return Constants.T_FLOAT; case 'I' : return Constants.T_INT; case 'J' : return Constants.T_LONG; case 'L' : return Constants.T_REFERENCE; case '[' : return Constants.T_ARRAY; case 'V' : return Constants.T_VOID; case 'Z' : return Constants.T_BOOLEAN; case 'S' : return Constants.T_SHORT; default: throw new ClassFormatException("Invalid method signature: " + signature); } } catch(StringIndexOutOfBoundsException e) { throw new ClassFormatException("Invalid method signature: " + signature); } }
/** * Read information about the class and its super class. * @throws IOException * @throws ClassFormatException */ private final void readClassInfo() throws IOException, ClassFormatException { access_flags = file.readUnsignedShort(); /* Interfaces are implicitely abstract, the flag should be set * according to the JVM specification. */ if((access_flags & Constants.ACC_INTERFACE) != 0) access_flags |= Constants.ACC_ABSTRACT; if(((access_flags & Constants.ACC_ABSTRACT) != 0) && ((access_flags & Constants.ACC_FINAL) != 0 )) throw new ClassFormatException("Class can't be both final and abstract"); class_name_index = file.readUnsignedShort(); superclass_name_index = file.readUnsignedShort(); } /**
/** * Read information about the class and its super class. * @throws IOException * @throws ClassFormatException */ private final void readClassInfo() throws IOException, ClassFormatException { access_flags = file.readUnsignedShort(); /* Interfaces are implicitely abstract, the flag should be set * according to the JVM specification. */ if((access_flags & Constants.ACC_INTERFACE) != 0) access_flags |= Constants.ACC_ABSTRACT; if(((access_flags & Constants.ACC_ABSTRACT) != 0) && ((access_flags & Constants.ACC_FINAL) != 0 )) throw new ClassFormatException("Class can't be both final and abstract"); class_name_index = file.readUnsignedShort(); superclass_name_index = file.readUnsignedShort(); } /**
/** * Return type of method signature as a byte value as defined in <em>Constants</em> * * @param signature in format described above * @return type of method signature * @see Constants */ public static final byte typeOfMethodSignature(String signature) throws ClassFormatException { int index; try { if(signature.charAt(0) != '(') throw new ClassFormatException("Invalid method signature: " + signature); index = signature.lastIndexOf(')') + 1; return typeOfSignature(signature.substring(index)); } catch(StringIndexOutOfBoundsException e) { throw new ClassFormatException("Invalid method signature: " + signature); } }
/** * Convert return value of a method (signature) to a Type object. * * @param signature signature string such as (Ljava/lang/String;)V * @return return type */ public static Type getReturnType(String signature) { try { // Read return type after `)' int index = signature.lastIndexOf(')') + 1; return getType(signature.substring(index)); } catch(StringIndexOutOfBoundsException e) { // Should never occur throw new ClassFormatException("Invalid method signature: " + signature); } }
/** * Return type of method signature as a byte value as defined in <em>Constants</em> * * @param signature in format described above * @return type of method signature * @see Constants */ public static final byte typeOfMethodSignature(String signature) throws ClassFormatException { int index; try { if(signature.charAt(0) != '(') throw new ClassFormatException("Invalid method signature: " + signature); index = signature.lastIndexOf(')') + 1; return typeOfSignature(signature.substring(index)); } catch(StringIndexOutOfBoundsException e) { throw new ClassFormatException("Invalid method signature: " + signature); } }
/** * Convert return value of a method (signature) to a Type object. * * @param signature signature string such as (Ljava/lang/String;)V * @return return type */ public static Type getReturnType(String signature) { try { // Read return type after `)' int index = signature.lastIndexOf(')') + 1; return getType(signature.substring(index)); } catch(StringIndexOutOfBoundsException e) { // Should never occur throw new ClassFormatException("Invalid method signature: " + signature); } }
/** * Convert arguments of a method (signature) to an array of Type objects. * @param signature signature string such as (Ljava/lang/String;)V * @return array of argument types */ public static Type[] getArgumentTypes(String signature) { ArrayList vec = new ArrayList(); int index; Type[] types; try { // Read all declarations between for `(' and `)' if(signature.charAt(0) != '(') throw new ClassFormatException("Invalid method signature: " + signature); index = 1; // current string position while(signature.charAt(index) != ')') { vec.add(getType(signature.substring(index))); index += consumed_chars; // update position } } catch(StringIndexOutOfBoundsException e) { // Should never occur throw new ClassFormatException("Invalid method signature: " + signature); } types = new Type[vec.size()]; vec.toArray(types); return types; }
/** * Convert arguments of a method (signature) to an array of Type objects. * @param signature signature string such as (Ljava/lang/String;)V * @return array of argument types */ public static Type[] getArgumentTypes(String signature) { ArrayList vec = new ArrayList(); int index; Type[] types; try { // Read all declarations between for `(' and `)' if(signature.charAt(0) != '(') throw new ClassFormatException("Invalid method signature: " + signature); index = 1; // current string position while(signature.charAt(index) != ')') { vec.add(getType(signature.substring(index))); index += consumed_chars; // update position } } catch(StringIndexOutOfBoundsException e) { // Should never occur throw new ClassFormatException("Invalid method signature: " + signature); } types = new Type[vec.size()]; vec.toArray(types); return types; }
/** * Get constant from constant pool and check whether it has the * expected type. * * @param index Index in constant pool * @param tag Tag of expected constant, i.e., its type * @return Constant value * @see Constant * @throws ClassFormatException */ public Constant getConstant(int index, byte tag) throws ClassFormatException { Constant c; c = getConstant(index); if(c == null) throw new ClassFormatException("Constant pool at index " + index + " is null."); if(c.getTag() == tag) return c; else throw new ClassFormatException("Expected class `" + Constants.CONSTANT_NAMES[tag] + "' at index " + index + " and got " + c); }
/** * Get constant from constant pool and check whether it has the * expected type. * * @param index Index in constant pool * @param tag Tag of expected constant, i.e., its type * @return Constant value * @see Constant * @throws ClassFormatException */ public Constant getConstant(int index, byte tag) throws ClassFormatException { Constant c; c = getConstant(index); if(c == null) throw new ClassFormatException("Constant pool at index " + index + " is null."); if(c.getTag() == tag) return c; else throw new ClassFormatException("Expected class `" + Constants.CONSTANT_NAMES[tag] + "' at index " + index + " and got " + c); }
/** * Converts string containing the method return and argument types * to a byte code method signature. * * @param ret Return type of method * @param argv Types of method arguments * @return Byte code representation of method signature */ public final static String methodTypeToSignature(String ret, String[] argv) throws ClassFormatException { StringBuffer buf = new StringBuffer("("); String str; if(argv != null) for(int i=0; i < argv.length; i++) { str = getSignature(argv[i]); if(str.endsWith("V")) // void can't be a method argument throw new ClassFormatException("Invalid type: " + argv[i]); buf.append(str); } str = getSignature(ret); buf.append(")" + str); return buf.toString(); }
/** * Converts string containing the method return and argument types * to a byte code method signature. * * @param ret Return type of method * @param argv Types of method arguments * @return Byte code representation of method signature */ public final static String methodTypeToSignature(String ret, String[] argv) throws ClassFormatException { StringBuffer buf = new StringBuffer("("); String str; if(argv != null) for(int i=0; i < argv.length; i++) { str = getSignature(argv[i]); if(str.endsWith("V")) // void can't be a method argument throw new ClassFormatException("Invalid type: " + argv[i]); buf.append(str); } str = getSignature(ret); buf.append(")" + str); return buf.toString(); }
/** * @param signature Method signature * @param chopit Shorten class names ? * @return return type of method * @throws ClassFormatException */ public static final String methodSignatureReturnType(String signature, boolean chopit) throws ClassFormatException { int index; String type; try { // Read return type after `)' index = signature.lastIndexOf(')') + 1; type = signatureToString(signature.substring(index), chopit); } catch(StringIndexOutOfBoundsException e) { // Should never occur throw new ClassFormatException("Invalid method signature: " + signature); } return type; }
/** * @param signature Method signature * @param chopit Shorten class names ? * @return return type of method * @throws ClassFormatException */ public static final String methodSignatureReturnType(String signature, boolean chopit) throws ClassFormatException { int index; String type; try { // Read return type after `)' index = signature.lastIndexOf(')') + 1; type = signatureToString(signature.substring(index), chopit); } catch(StringIndexOutOfBoundsException e) { // Should never occur throw new ClassFormatException("Invalid method signature: " + signature); } return type; }
/** * Read one constant from the given file, the type depends on a tag byte. * * @param file Input stream * @return Constant object */ static final Constant readConstant(DataInputStream file) throws IOException, ClassFormatException { byte b = file.readByte(); // Read tag byte switch(b) { case Constants.CONSTANT_Class: return new ConstantClass(file); case Constants.CONSTANT_Fieldref: return new ConstantFieldref(file); case Constants.CONSTANT_Methodref: return new ConstantMethodref(file); case Constants.CONSTANT_InterfaceMethodref: return new ConstantInterfaceMethodref(file); case Constants.CONSTANT_String: return new ConstantString(file); case Constants.CONSTANT_Integer: return new ConstantInteger(file); case Constants.CONSTANT_Float: return new ConstantFloat(file); case Constants.CONSTANT_Long: return new ConstantLong(file); case Constants.CONSTANT_Double: return new ConstantDouble(file); case Constants.CONSTANT_NameAndType: return new ConstantNameAndType(file); case Constants.CONSTANT_Utf8: return new ConstantUtf8(file); default: throw new ClassFormatException("Invalid byte tag in constant pool: " + b); } } }