Beispiel #1
0
  /**
   * Gets the bytecode of a native code replacement method.
   *
   * @param method
   * @param cl
   * @return the bytecode
   */
  private static VmByteCode getNativeCodeReplacement(
      VmMethod method, VmClassLoader cl, boolean verbose) {
    final String className = method.getDeclaringClass().getName();
    final String nativeClassName = VmUtils.getNativeClassName(className);
    final VmType nativeType;
    try {
      nativeType = cl.loadClass(nativeClassName, false);
    } catch (ClassNotFoundException ex) {
      if (verbose) {
        BootLogInstance.get().error("Native class replacement (" + nativeClassName + ") not found");
      }
      return null;
    }

    String signature = method.getSignature();
    if (!method.isStatic()) {
      signature = '(' + Signature.toSignature(method.getDeclaringClass()) + signature.substring(1);
    }

    final VmMethod nativeMethod =
        nativeType.getNativeMethodReplacement(method.getName(), signature);

    if (nativeMethod == null) {
      if (verbose) {
        BootLogInstance.get().error("Native method replacement (" + method + ") not found");
      }
      return null;
    }
    if (!nativeMethod.isStatic()) {
      throw new ClassFormatError("Native method replacement must be static");
    }
    return nativeMethod.getBytecode();
  }
Beispiel #2
0
  /**
   * Decode a given class.
   *
   * @param data
   * @param rejectNatives
   * @param clc
   * @param protectionDomain
   * @return The decoded class
   * @throws ClassFormatError
   */
  private static final VmType decodeClass(
      ByteBuffer data, boolean rejectNatives, VmClassLoader clc, ProtectionDomain protectionDomain)
      throws ClassFormatError {
    final VmSharedStatics sharedStatics = clc.getSharedStatics();
    final VmIsolatedStatics isolatedStatics = clc.getIsolatedStatics();
    final int slotSize = clc.getArchitecture().getReferenceSize();

    final int magic = data.getInt();
    if (magic != 0xCAFEBABE) {
      throw new ClassFormatError("invalid magic");
    }
    final int min_version = data.getChar();
    final int maj_version = data.getChar();

    if (false) {
      BootLogInstance.get().debug("Class file version " + maj_version + ';' + min_version);
    }

    final int cpcount = data.getChar();
    // allocate enough space for the CP
    final byte[] tags = new byte[cpcount];
    final VmCP cp = new VmCP(cpcount);
    for (int i = 1; i < cpcount; i++) {
      final int tag = data.get() & 0xFF;
      tags[i] = (byte) tag;
      switch (tag) {
        case 1:
          // Utf8
          cp.setUTF8(i, readUTF(data));
          break;
        case 3:
          // int
          cp.setInt(i, data.getInt());
          break;
        case 4:
          // float
          // cp.setInt(i, data.getInt());
          final int ival = data.getInt();
          final float fval = Float.intBitsToFloat(ival);
          cp.setFloat(i, fval);
          break;
        case 5:
          // long
          cp.setLong(i, data.getLong());
          i++;
          break;
        case 6:
          // double
          // cp.setLong(i, data.getLong());
          final long lval = data.getLong();
          final double dval = Double.longBitsToDouble(lval);
          cp.setDouble(i, dval);
          i++;
          break;
        case 7:
          // class
          cp.setInt(i, data.getChar());
          break;
        case 8:
          // String
          cp.setInt(i, data.getChar());
          break;
        case 9: // Fieldref
        case 10: // Methodref
        case 11: // IMethodref
          {
            final int clsIdx = data.getChar();
            final int ntIdx = data.getChar();
            cp.setInt(i, clsIdx << 16 | ntIdx);
            break;
          }
        case 12:
          // Name and Type
          {
            final int nIdx = data.getChar();
            final int dIdx = data.getChar();
            cp.setInt(i, nIdx << 16 | dIdx);
            break;
          }
        default:
          throw new ClassFormatError("Invalid constantpool tag: " + tags[i]);
      }
    }

    // Now patch the required entries (level 1)
    for (int i = 1; i < cpcount; i++) {
      switch (tags[i]) {
        case 7:
          {
            // Class
            final int idx = cp.getInt(i);
            final VmConstClass constClass = new VmConstClass(cp.getUTF8(idx));
            cp.setConstClass(i, constClass);
            break;
          }
        case 8:
          {
            // String
            final int idx = cp.getInt(i);
            final int staticsIdx = sharedStatics.allocConstantStringField(cp.getUTF8(idx));
            final VmConstString constStr = new VmConstString(staticsIdx);
            cp.setString(i, constStr);
            break;
          }
      }
    }

    // Now patch the required entries (level 2)
    for (int i = 1; i < cpcount; i++) {
      final int tag = tags[i];
      if ((tag >= 9) && (tag <= 11)) {
        final int v = cp.getInt(i);
        final VmConstClass constClass = cp.getConstClass(v >>> 16);
        final int nat = cp.getInt(v & 0xFFFF);
        final String name = cp.getUTF8(nat >>> 16);
        final String descriptor = cp.getUTF8(nat & 0xFFFF);
        switch (tag) {
          case 9:
            // FieldRef
            cp.setConstFieldRef(i, new VmConstFieldRef(constClass, name, descriptor));
            break;
          case 10:
            // MethodRef
            cp.setConstMethodRef(i, new VmConstMethodRef(constClass, name, descriptor));
            break;
          case 11:
            // IMethodRef
            cp.setConstIMethodRef(i, new VmConstIMethodRef(constClass, name, descriptor));
            break;
        }
      }
    }

    // Cleanup the unwantend entries
    for (int i = 1; i < cpcount; i++) {
      switch (tags[i]) {
        case 12:
          // Name and Type
          cp.reset(i);
          break;
      }
    }

    final int classModifiers = data.getChar();

    final VmConstClass this_class = cp.getConstClass(data.getChar());
    final String clsName = this_class.getClassName();

    final VmConstClass super_class = cp.getConstClass(data.getChar());
    final String superClassName;
    if (super_class != null) {
      superClassName = super_class.getClassName();
    } else {
      superClassName = null;
    }

    // Allocate the class object
    final VmType cls;
    if (Modifier.isInterface(classModifiers)) {
      cls = new VmInterfaceClass(clsName, superClassName, clc, classModifiers, protectionDomain);
    } else {
      cls = new VmNormalClass(clsName, superClassName, clc, classModifiers, protectionDomain);
    }
    cls.setCp(cp);

    // Determine if we can safely align the fields
    // int pragmaFlags = 0;
    if (isBootType(cls)) {
      cls.addPragmaFlags(TypePragmaFlags.NO_FIELD_ALIGNMENT);
    }
    cls.addPragmaFlags(getClassNamePragmaFlags(clsName));

    // Interface table
    cls.addPragmaFlags(readInterfaces(data, cls, cp));

    // Field table
    final FieldData[] fieldData = readFields(data, cp, slotSize, clc);

    // Method Table
    readMethods(data, rejectNatives, cls, cp, sharedStatics, clc);

    // Read class attributes
    final int acount = data.getChar();
    VmAnnotation[] rVisAnn = null;
    VmAnnotation[] rInvisAnn = null;
    String sourceFile = null;
    String signature = null;
    for (int a = 0; a < acount; a++) {
      final String attrName = cp.getUTF8(data.getChar());
      final int length = data.getInt();
      if (VmArray.equals(RuntimeVisibleAnnotationsAttrName, attrName)) {
        byte[] buf = new byte[length];
        data.slice().get(buf);
        cls.setRawAnnotations(buf);
        rVisAnn = readRuntimeAnnotations(data, cp, true, clc);
      } else if (VmArray.equals(RuntimeInvisibleAnnotationsAttrName, attrName)) {
        rInvisAnn = readRuntimeAnnotations(data, cp, false, clc);
      } else if (VmArray.equals(SourceFileAttrName, attrName)) {
        sourceFile = cp.getUTF8(data.getChar());
      } else if (VmArray.equals(SignatureAttrName, attrName)) {
        signature = cp.getUTF8(data.getChar());
      } else {
        skip(data, length);
      }
    }
    cls.setRuntimeAnnotations(rVisAnn);
    cls.setSourceFile(sourceFile);
    cls.setSignature(signature);
    if (rInvisAnn != null) {
      cls.addPragmaFlags(getClassPragmaFlags(rInvisAnn, clsName));
    }
    if (rVisAnn != null) {
      cls.addPragmaFlags(getClassPragmaFlags(rVisAnn, clsName));
    }

    // Create the fields
    if (fieldData != null) {
      createFields(cls, fieldData, sharedStatics, isolatedStatics, slotSize, cls.getPragmaFlags());
    }

    return cls;
  }