bytecodeparser.java

来自「RESIN 3.2 最新源码」· Java 代码 · 共 589 行

JAVA
589
字号
/* * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved * * This file is part of Resin(R) Open Source * * Each copy or derived work must preserve the copyright notice and this * notice unmodified. * * Resin Open Source is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Resin Open Source is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty * of NON-INFRINGEMENT.  See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with Resin Open Source; if not, write to the * *   Free Software Foundation, Inc. *   59 Temple Place, Suite 330 *   Boston, MA 02111-1307  USA * * @author Scott Ferguson */package com.caucho.bytecode;import com.caucho.log.Log;import com.caucho.util.CharBuffer;import com.caucho.util.L10N;import java.io.IOException;import java.io.InputStream;import java.util.ArrayList;import java.util.logging.Logger;/** * Interface to the bytecode parser. */public class ByteCodeParser {  private static final Logger log = Log.open(ByteCode.class);  private static final L10N L = new L10N(ByteCode.class);  static final int CP_CLASS = 7;  static final int CP_FIELD_REF = 9;  static final int CP_METHOD_REF = 10;  static final int CP_INTERFACE_METHOD_REF = 11;  static final int CP_STRING = 8;  static final int CP_INTEGER = 3;  static final int CP_FLOAT = 4;  static final int CP_LONG = 5;  static final int CP_DOUBLE = 6;  static final int CP_NAME_AND_TYPE = 12;  static final int CP_UTF8 = 1;  private JavaClassLoader _loader;  private InputStream _is;  private JavaClass _class;  private ConstantPool _cp;  /**   * Sets the JClassLoader   */  public void setClassLoader(JavaClassLoader loader)  {    _loader = loader;  }  /**   * Sets the class.   */  public void setJavaClass(JavaClass javaClass)  {    _class = javaClass;  }    /**   * Parses the .class file.   */  public JavaClass parse(InputStream is)    throws IOException  {    _is = is;    if (_loader == null)      _loader = new JavaClassLoader();        if (_class == null)      _class = new JavaClass(_loader);    _cp = _class.getConstantPool();        parseClass();    return _class;  }  /**   * Returns the constant pool.   */  public ConstantPool getConstantPool()  {    return _cp;  }  /**   * Returns a UTF8 String from the constant pool.   */  public String getUTF8(int index)  {    return getConstantPool().getUtf8AsString(index);  }  /**   * Parses the ClassFile construct   */  private void parseClass()    throws IOException  {    int magic = readInt();    if (magic != JavaClass.MAGIC)      throw error(L.l("bad magic number in class file"));    int minor = readShort();    int major = readShort();    _class.setMajor(major);    _class.setMinor(minor);    parseConstantPool();    int accessFlags = readShort();    _class.setAccessFlags(accessFlags);    int thisClassIndex = readShort();    _class.setThisClass(_cp.getClass(thisClassIndex).getName());        int superClassIndex = readShort();    if (superClassIndex > 0)      _class.setSuperClass(_cp.getClass(superClassIndex).getName());    int interfaceCount = readShort();    for (int i = 0; i < interfaceCount; i++) {      int classIndex = readShort();      _class.addInterface(_cp.getClass(classIndex).getName());    }    int fieldCount = readShort();    for (int i = 0; i < fieldCount; i++) {      parseField();    }    int methodCount = readShort();    for (int i = 0; i < methodCount; i++)      parseMethod();    int attrCount = readShort();    for (int i = 0; i < attrCount; i++) {      Attribute attr = parseAttribute();      _class.addAttribute(attr);    }  }  /**   * Parses the constant pool.   */  public void parseConstantPool()    throws IOException  {    int count = readShort();    for (int i = 1; i < count; i++) {      ConstantPoolEntry entry = parseConstantPoolEntry(i);      _cp.addConstant(entry);            if (entry instanceof DoubleConstant ||	  entry instanceof LongConstant) {	i++;	_cp.addConstant(null);      }    }  }  /**   * Parses a constant pool entry.   */  private ConstantPoolEntry parseConstantPoolEntry(int index)    throws IOException  {    int tag = read();    switch (tag) {    case CP_CLASS:      return parseClassConstant(index);          case CP_FIELD_REF:      return parseFieldRefConstant(index);          case CP_METHOD_REF:      return parseMethodRefConstant(index);          case CP_INTERFACE_METHOD_REF:      return parseInterfaceMethodRefConstant(index);          case CP_STRING:      return parseStringConstant(index);          case CP_INTEGER:      return parseIntegerConstant(index);          case CP_FLOAT:      return parseFloatConstant(index);          case CP_LONG:      return parseLongConstant(index);          case CP_DOUBLE:      return parseDoubleConstant(index);          case CP_NAME_AND_TYPE:      return parseNameAndTypeConstant(index);          case CP_UTF8:      return parseUtf8Constant(index);    default:      throw error(L.l("'{0}' is an unknown constant pool type.",		      tag));    }  }  /**   * Parses a class constant pool entry.   */  private ClassConstant parseClassConstant(int index)    throws IOException  {    int nameIndex = readShort();    return new ClassConstant(_class.getConstantPool(), index, nameIndex);  }  /**   * Parses a field ref constant pool entry.   */  private FieldRefConstant parseFieldRefConstant(int index)    throws IOException  {    int classIndex = readShort();    int nameAndTypeIndex = readShort();    return new FieldRefConstant(_class.getConstantPool(), index,				classIndex, nameAndTypeIndex);  }  /**   * Parses a method ref constant pool entry.   */  private MethodRefConstant parseMethodRefConstant(int index)    throws IOException  {    int classIndex = readShort();    int nameAndTypeIndex = readShort();    return new MethodRefConstant(_class.getConstantPool(), index,				 classIndex, nameAndTypeIndex);  }  /**   * Parses an interface method ref constant pool entry.   */  private InterfaceMethodRefConstant parseInterfaceMethodRefConstant(int index)    throws IOException  {    int classIndex = readShort();    int nameAndTypeIndex = readShort();    return new InterfaceMethodRefConstant(_class.getConstantPool(), index,					  classIndex, nameAndTypeIndex);  }  /**   * Parses a string constant pool entry.   */  private StringConstant parseStringConstant(int index)    throws IOException  {    int stringIndex = readShort();    return new StringConstant(_class.getConstantPool(), index, stringIndex);  }  /**   * Parses an integer constant pool entry.   */  private IntegerConstant parseIntegerConstant(int index)    throws IOException  {    int value = readInt();    return new IntegerConstant(_class.getConstantPool(), index, value);  }  /**   * Parses a float constant pool entry.   */  private FloatConstant parseFloatConstant(int index)    throws IOException  {    int bits = readInt();    float value = Float.intBitsToFloat(bits);    return new FloatConstant(_class.getConstantPool(), index, value);  }  /**   * Parses a long constant pool entry.   */  private LongConstant parseLongConstant(int index)    throws IOException  {    long value = readLong();    return new LongConstant(_class.getConstantPool(), index, value);  }  /**   * Parses a double constant pool entry.   */  private DoubleConstant parseDoubleConstant(int index)    throws IOException  {    long bits = readLong();    double value = Double.longBitsToDouble(bits);    return new DoubleConstant(_class.getConstantPool(), index, value);  }  /**   * Parses a name and type pool entry.   */  private NameAndTypeConstant parseNameAndTypeConstant(int index)    throws IOException  {    int nameIndex = readShort();    int descriptorIndex = readShort();    return new NameAndTypeConstant(_class.getConstantPool(), index,				   nameIndex, descriptorIndex);  }  /**   * Parses a utf-8 constant pool entry.   */  private Utf8Constant parseUtf8Constant(int index)    throws IOException  {    int length = readShort();        CharBuffer cb = CharBuffer.allocate();    for (int i = 0; i < length; i++) {      int ch = read();      if (ch < 0x80) {	cb.append((char) ch);      }      else if ((ch & 0xe0) == 0xc0) {	int ch2 = read();	i++;	cb.append((char) (((ch & 0x1f) << 6)+			  (ch2 & 0x3f)));      }      else {	int ch2 = read();	int ch3 = read();	i += 2;      	cb.append((char) (((ch & 0xf) << 12)+			  ((ch2 & 0x3f) << 6) +			  ((ch3 & 0x3f))));      }    }    return new Utf8Constant(_class.getConstantPool(), index, cb.close());  }  /**   * Parses a field entry.   */  private void parseField()    throws IOException  {    int accessFlags = readShort();    int nameIndex = readShort();    int descriptorIndex = readShort();    JavaField field = new JavaField();    field.setJavaClass(_class);    field.setName(_cp.getUtf8(nameIndex).getValue());    field.setDescriptor(_cp.getUtf8(descriptorIndex).getValue());    field.setAccessFlags(accessFlags);    int attributesCount = readShort();    for (int i = 0; i < attributesCount; i++) {      Attribute attr = parseAttribute();      field.addAttribute(attr);    }    _class.addField(field);  }  /**   * Parses a method entry.   */  private void parseMethod()    throws IOException  {    int accessFlags = readShort();    int nameIndex = readShort();    int descriptorIndex = readShort();    JavaMethod method = new JavaMethod(_loader);    method.setJavaClass(_class);    method.setName(_cp.getUtf8(nameIndex).getValue());    method.setDescriptor(_cp.getUtf8(descriptorIndex).getValue());    method.setAccessFlags(accessFlags);    int attributesCount = readShort();    for (int i = 0; i < attributesCount; i++) {      Attribute attr = parseAttribute();      method.addAttribute(attr);            if (attr instanceof ExceptionsAttribute) {	ExceptionsAttribute exn = (ExceptionsAttribute) attr;	ArrayList<String> exnNames = exn.getExceptionList();	if (exnNames.size() > 0) {	  JClass []exnClasses = new JClass[exnNames.size()];	  for (int j = 0; j < exnNames.size(); j++) {	    String exnName = exnNames.get(j).replace('/', '.');	  	    exnClasses[j] = _loader.forName(exnName);	  }	  method.setExceptionTypes(exnClasses);	}      }    }    _class.addMethod(method);  }  /**   * Parses an attribute.   */  Attribute parseAttribute()    throws IOException  {    int nameIndex = readShort();    String name = _cp.getUtf8(nameIndex).getValue();    if (name.equals("Code")) {      CodeAttribute code = new CodeAttribute(name);      code.read(this);      return code;    }    else if (name.equals("Exceptions")) {      ExceptionsAttribute code = new ExceptionsAttribute(name);      code.read(this);      return code;    }    else if (name.equals("Signature")) {      SignatureAttribute code = new SignatureAttribute();      code.read(this);      return code;    }        OpaqueAttribute attr = new OpaqueAttribute(name);        int length = readInt();    byte []bytes = new byte[length];        read(bytes, 0, bytes.length);    attr.setValue(bytes);    return attr;  }  /**   * Parses a 64-bit int.   */  long readLong()    throws IOException  {    return (((long) _is.read() << 56) |	    ((long) _is.read() << 48) |	    ((long) _is.read() << 40) |	    ((long) _is.read() << 32) |	    ((long) _is.read() << 24) |	    ((long) _is.read() << 16) |	    ((long) _is.read() << 8) |	    ((long) _is.read()));  }  /**   * Parses a 32-bit int.   */  int readInt()    throws IOException  {    return ((_is.read() << 24) |	    (_is.read() << 16) |	    (_is.read() << 8) |	    (_is.read()));  }  /**   * Parses a 16-bit int.   */  int readShort()    throws IOException  {    int c1 = _is.read();    int c2 = _is.read();    return ((c1 << 8) | c2);  }  /**   * Parses a byte   */  int read()    throws IOException  {    return _is.read();  }  /**   * Reads a chunk   */  int read(byte []buffer, int offset, int length)    throws IOException  {    int readLength = 0;        while (length > 0) {      int sublen = _is.read(buffer, offset, length);      if (sublen < 0)	return readLength == 0 ? -1 : readLength;      offset += sublen;      length -= sublen;      readLength += sublen;    }    return readLength;  }  /**   * Returns an error message.   */  private IOException error(String message)  {    return new IOException(message);  }}

⌨️ 快捷键说明

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