示例#1
0
 public Assembler sub(Type t) {
   int opcode = -1;
   switch (t.getSort()) {
     case Type.SHORT:
     case Type.BYTE:
     case Type.INT:
       {
         opcode = ISUB;
         break;
       }
     case Type.LONG:
       {
         opcode = LSUB;
         break;
       }
     case Type.FLOAT:
       {
         opcode = FSUB;
         break;
       }
     case Type.DOUBLE:
       {
         opcode = DSUB;
         break;
       }
   }
   if (opcode != -1) {
     mv.visitInsn(opcode);
   }
   return this;
 }
  /** Generate class bytes for java.lang.Runnable implementation and return the same. */
  public byte[] generate(Method method, String className) {
    int modifiers = method.getModifiers();
    // make sure that the method is public static
    // and accepts no arguments
    if (!Modifier.isStatic(modifiers)
        || !Modifier.isPublic(modifiers)
        || method.getParameterTypes().length != 0) {
      throw new IllegalArgumentException();
    }
    Class clazz = method.getDeclaringClass();
    modifiers = clazz.getModifiers();
    // make sure that the class is public as well
    if (!Modifier.isPublic(modifiers)) {
      throw new IllegalArgumentException();
    }

    ClassWriter cw = InstrumentUtils.newClassWriter();
    cw.visit(
        V1_1, ACC_PUBLIC, className, null, "java/lang/Object", new String[] {"java/lang/Runnable"});
    // creates a MethodWriter for the (implicit) constructor
    MethodVisitor mw = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
    // pushes the 'this' variable
    mw.visitVarInsn(ALOAD, 0);
    // invokes the super class constructor
    mw.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
    mw.visitInsn(RETURN);
    mw.visitMaxs(1, 1);
    mw.visitEnd();

    // creates a MethodWriter for the 'main' method
    mw = cw.visitMethod(ACC_PUBLIC, "run", "()V", null, null);
    // invokes the given method
    mw.visitMethodInsn(
        INVOKESTATIC,
        Type.getInternalName(method.getDeclaringClass()),
        method.getName(),
        Type.getMethodDescriptor(method));
    mw.visitInsn(RETURN);
    mw.visitMaxs(1, 1);
    mw.visitEnd();
    return cw.toByteArray();
  }
示例#3
0
 public Assembler dupValue(Type type) {
   switch (type.getSize()) {
     case 1:
       dup();
       break;
     case 2:
       dup2();
       break;
   }
   return this;
 }
示例#4
0
  /**
   * Checks the type compatibility<br>
   * Two types are compatible when and only when:
   *
   * <ol>
   *   <li>They are exactly the same
   *   <li>The left parameter is {@linkplain Object} or {@linkplain AnyType} and the right parameter
   *       is either {@linkplain Object} or an array
   *   <li>The left parameter is assignable from the right one (is a superclass of the right one)
   * </ol>
   *
   * @param left The left type parameter
   * @param right The right type parameter
   * @return Returns true if a value of the left {@linkplain Type} can hold the value of the right
   *     {@linkplain Type}
   */
  public static boolean isCompatible(Type left, Type right) {
    if (left.equals(right)) {
      return true;
    } else if (isArray(left)) {
      return false;
    } else if (isObjectOrAnyType(left)) {
      int sort2 = right.getSort();
      return (sort2 == Type.OBJECT || sort2 == Type.ARRAY);
    } else if (isPrimitive(left)) {
      // a primitive type requires strict equality
      return left.equals(right);
    } else {
      ClassLoader cl = Thread.currentThread().getContextClassLoader();
      if (cl == null) {
        cl = ClassLoader.getSystemClassLoader();
      }
      // those classes should already have been loaded at this point
      Class clzLeft, clzRight;
      try {
        clzLeft = cl.loadClass(left.getClassName());
      } catch (Throwable e) {
        clzLeft = Object.class;
      }

      // anything is assignable to Object
      if (clzLeft == Object.class) {
        return true;
      }

      try {
        clzRight = cl.loadClass(right.getClassName());
      } catch (Throwable e) {
        clzRight = Object.class;
      }
      return (clzLeft.isAssignableFrom(clzRight));
    }
  }
示例#5
0
 public Assembler unbox(String desc) {
   int typeCode = desc.charAt(0);
   switch (typeCode) {
     case '[':
     case 'L':
       mv.visitTypeInsn(CHECKCAST, Type.getType(desc).getInternalName());
       break;
     case 'Z':
       mv.visitTypeInsn(CHECKCAST, JAVA_LANG_BOOLEAN);
       invokeVirtual(JAVA_LANG_BOOLEAN, BOOLEAN_VALUE, BOOLEAN_VALUE_DESC);
       break;
     case 'C':
       mv.visitTypeInsn(CHECKCAST, JAVA_LANG_CHARACTER);
       invokeVirtual(JAVA_LANG_CHARACTER, CHAR_VALUE, CHAR_VALUE_DESC);
       break;
     case 'B':
       mv.visitTypeInsn(CHECKCAST, JAVA_LANG_NUMBER);
       invokeVirtual(JAVA_LANG_NUMBER, BYTE_VALUE, BYTE_VALUE_DESC);
       break;
     case 'S':
       mv.visitTypeInsn(CHECKCAST, JAVA_LANG_NUMBER);
       invokeVirtual(JAVA_LANG_NUMBER, SHORT_VALUE, SHORT_VALUE_DESC);
       break;
     case 'I':
       mv.visitTypeInsn(CHECKCAST, JAVA_LANG_NUMBER);
       invokeVirtual(JAVA_LANG_NUMBER, INT_VALUE, INT_VALUE_DESC);
       break;
     case 'J':
       mv.visitTypeInsn(CHECKCAST, JAVA_LANG_NUMBER);
       invokeVirtual(JAVA_LANG_NUMBER, LONG_VALUE, LONG_VALUE_DESC);
       break;
     case 'F':
       mv.visitTypeInsn(CHECKCAST, JAVA_LANG_NUMBER);
       invokeVirtual(JAVA_LANG_NUMBER, FLOAT_VALUE, FLOAT_VALUE_DESC);
       break;
     case 'D':
       mv.visitTypeInsn(CHECKCAST, JAVA_LANG_NUMBER);
       invokeVirtual(JAVA_LANG_NUMBER, DOUBLE_VALUE, DOUBLE_VALUE_DESC);
       break;
   }
   return this;
 }
示例#6
0
  public static Type getArrayType(int arrayOpcode) {
    switch (arrayOpcode) {
      case IALOAD:
      case IASTORE:
        return Type.getType("[I");

      case BALOAD:
      case BASTORE:
        return Type.getType("[B");

      case AALOAD:
      case AASTORE:
        return objectArrayType;

      case CALOAD:
      case CASTORE:
        return Type.getType("[C");

      case FALOAD:
      case FASTORE:
        return Type.getType("[F");

      case SALOAD:
      case SASTORE:
        return Type.getType("[S");

      case LALOAD:
      case LASTORE:
        return Type.getType("[J");

      case DALOAD:
      case DASTORE:
        return Type.getType("[D");

      default:
        throw new RuntimeException("invalid array opcode");
    }
  }
示例#7
0
 public static boolean isString(Type t) {
   return t.equals(stringType);
 }
示例#8
0
 public static boolean isObject(Type t) {
   return t.equals(objectType);
 }
示例#9
0
 public static boolean isAnyTypeArray(Type t) {
   return t.equals(anyTypeArray);
 }
示例#10
0
 public static boolean isAnyType(Type t) {
   return t.equals(anyType);
 }
示例#11
0
class TypeUtils {
  private TypeUtils() {}

  public static final Type objectType = Type.getType(Object.class);
  public static final Type stringType = Type.getType(String.class);
  public static final Type throwableType = Type.getType(Throwable.class);
  public static final Type objectArrayType = Type.getType(Object[].class);
  public static final Type anyType = Type.getType(AnyType.class);
  public static final Type anyTypeArray = Type.getType(AnyType[].class);

  public static boolean isPrimitive(Type t) {
    return t == Type.BOOLEAN_TYPE
        || t == Type.BYTE_TYPE
        || t == Type.CHAR_TYPE
        || t == Type.DOUBLE_TYPE
        || t == Type.FLOAT_TYPE
        || t == Type.INT_TYPE
        || t == Type.LONG_TYPE
        || t == Type.SHORT_TYPE;
  }

  public static boolean isAnyType(Type t) {
    return t.equals(anyType);
  }

  public static boolean isAnyTypeArray(Type t) {
    return t.equals(anyTypeArray);
  }

  public static boolean isObject(Type t) {
    return t.equals(objectType);
  }

  public static boolean isObjectOrAnyType(Type t) {
    return isObject(t) || isAnyType(t);
  }

  public static boolean isString(Type t) {
    return t.equals(stringType);
  }

  public static boolean isArray(Type t) {
    return t.getSort() == Type.ARRAY;
  }

  public static boolean isThrowable(Type t) {
    return t.equals(throwableType);
  }

  /**
   * Checks the type compatibility<br>
   * Two types are compatible when and only when:
   *
   * <ol>
   *   <li>They are exactly the same
   *   <li>The left parameter is {@linkplain Object} or {@linkplain AnyType} and the right parameter
   *       is either {@linkplain Object} or an array
   *   <li>The left parameter is assignable from the right one (is a superclass of the right one)
   * </ol>
   *
   * @param left The left type parameter
   * @param right The right type parameter
   * @return Returns true if a value of the left {@linkplain Type} can hold the value of the right
   *     {@linkplain Type}
   */
  public static boolean isCompatible(Type left, Type right) {
    if (left.equals(right)) {
      return true;
    } else if (isArray(left)) {
      return false;
    } else if (isObjectOrAnyType(left)) {
      int sort2 = right.getSort();
      return (sort2 == Type.OBJECT || sort2 == Type.ARRAY);
    } else if (isPrimitive(left)) {
      // a primitive type requires strict equality
      return left.equals(right);
    } else {
      ClassLoader cl = Thread.currentThread().getContextClassLoader();
      if (cl == null) {
        cl = ClassLoader.getSystemClassLoader();
      }
      // those classes should already have been loaded at this point
      Class clzLeft, clzRight;
      try {
        clzLeft = cl.loadClass(left.getClassName());
      } catch (Throwable e) {
        clzLeft = Object.class;
      }

      // anything is assignable to Object
      if (clzLeft == Object.class) {
        return true;
      }

      try {
        clzRight = cl.loadClass(right.getClassName());
      } catch (Throwable e) {
        clzRight = Object.class;
      }
      return (clzLeft.isAssignableFrom(clzRight));
    }
  }

  public static boolean isCompatible(Type[] args1, Type[] args2) {
    if (args1.length != args2.length) {
      return false;
    }
    for (int i = 0; i < args1.length; i++) {
      if (!args1[i].equals(args2[i])) {
        int sort2 = args2[i].getSort();
        /*
         * if destination is AnyType and right side is
         * Object or Array (i.e., any reference type)
         * then we allow it - because AnyType is mapped to
         * java.lang.Object.
         */
        if (isAnyType(args1[i]) && (sort2 == Type.OBJECT || sort2 == Type.ARRAY)) {
          continue;
        } else {
          return false;
        }
      }
    }
    return true;
  }

  public static Type getArrayType(int arrayOpcode) {
    switch (arrayOpcode) {
      case IALOAD:
      case IASTORE:
        return Type.getType("[I");

      case BALOAD:
      case BASTORE:
        return Type.getType("[B");

      case AALOAD:
      case AASTORE:
        return objectArrayType;

      case CALOAD:
      case CASTORE:
        return Type.getType("[C");

      case FALOAD:
      case FASTORE:
        return Type.getType("[F");

      case SALOAD:
      case SASTORE:
        return Type.getType("[S");

      case LALOAD:
      case LASTORE:
        return Type.getType("[J");

      case DALOAD:
      case DASTORE:
        return Type.getType("[D");

      default:
        throw new RuntimeException("invalid array opcode");
    }
  }

  public static Type getElementType(int arrayOpcode) {
    switch (arrayOpcode) {
      case IALOAD:
      case IASTORE:
        return Type.INT_TYPE;

      case BALOAD:
      case BASTORE:
        return Type.BYTE_TYPE;

      case AALOAD:
      case AASTORE:
        return objectType;

      case CALOAD:
      case CASTORE:
        return Type.CHAR_TYPE;

      case FALOAD:
      case FASTORE:
        return Type.FLOAT_TYPE;

      case SALOAD:
      case SASTORE:
        return Type.SHORT_TYPE;

      case LALOAD:
      case LASTORE:
        return Type.LONG_TYPE;

      case DALOAD:
      case DASTORE:
        return Type.DOUBLE_TYPE;

      default:
        throw new RuntimeException("invalid array opcode");
    }
  }

  private static final Map<String, String> primitives;

  static {
    primitives = new HashMap<String, String>();
    primitives.put("void", "V");
    primitives.put("byte", "B");
    primitives.put("char", "C");
    primitives.put("double", "D");
    primitives.put("float", "F");
    primitives.put("int", "I");
    primitives.put("long", "J");
    primitives.put("short", "S");
    primitives.put("boolean", "Z");
  }

  public static String declarationToDescriptor(String decl) {
    int leftParen = decl.indexOf('(');
    int rightParen = decl.indexOf(')');
    if (leftParen == -1 || rightParen == -1) {
      throw new IllegalArgumentException();
    }

    StringBuilder buf = new StringBuilder();
    String descriptor;

    buf.append('(');
    String args = decl.substring(leftParen + 1, rightParen);
    StringTokenizer st = new StringTokenizer(args, ",");
    while (st.hasMoreTokens()) {
      String arg = st.nextToken().trim();
      descriptor = primitives.get(arg);
      if (arg.length() == 0) {
        throw new IllegalArgumentException();
      }
      if (descriptor == null) {
        descriptor = objectOrArrayType(arg);
      }
      buf.append(descriptor);
    }
    buf.append(')');

    String returnType = decl.substring(0, leftParen).trim();
    descriptor = primitives.get(returnType);
    if (returnType.length() == 0) {
      throw new IllegalArgumentException();
    }
    if (descriptor == null) {
      descriptor = objectOrArrayType(returnType);
    }
    buf.append(descriptor);
    return buf.toString();
  }

  public static String getJavaType(String desc) {
    int arrIndex = desc.lastIndexOf("[") + 1;
    desc = desc.substring(arrIndex);
    if (desc.startsWith("L")) {
      desc = desc.substring(1, desc.length() - 1).replace('/', '.');
    } else {
      for (Map.Entry<String, String> entry : primitives.entrySet()) {
        if (entry.getValue().equals(desc)) {
          desc = entry.getKey();
          break;
        }
      }
    }
    StringBuilder sb = new StringBuilder(desc);
    for (int i = 0; i < arrIndex; i++) {
      sb.append("[]");
    }
    return sb.toString();
  }

  public static String objectOrArrayType(String type) {
    StringBuilder buf = new StringBuilder();
    int index = 0;
    while ((index = type.indexOf("[]", index) + 1) > 0) {
      buf.append('[');
    }
    String t = type.substring(0, type.length() - buf.length() * 2);
    String desc = primitives.get(t);
    if (desc != null) {
      buf.append(desc);
    } else {
      buf.append('L');
      if (t.indexOf('.') < 0) {
        buf.append(t);
      } else {
        buf.append(t.replace('.', '/'));
      }
      buf.append(';');
    }
    return buf.toString();
  }
}
示例#12
0
 public Assembler storeField(Type owner, String name, Type t) {
   mv.visitFieldInsn(Opcodes.PUTFIELD, owner.getInternalName(), name, t.getDescriptor());
   return this;
 }
示例#13
0
 public Assembler arrayLoad(Type type) {
   mv.visitInsn(type.getOpcode(IALOAD));
   return this;
 }
示例#14
0
 public Assembler unbox(Type type) {
   return unbox(type.getDescriptor());
 }
示例#15
0
 public Assembler newArray(Type t) {
   mv.visitTypeInsn(ANEWARRAY, t.getInternalName());
   return this;
 }
示例#16
0
 public Assembler newInstance(Type t) {
   mv.visitTypeInsn(NEW, t.getInternalName());
   return this;
 }
示例#17
0
 public Assembler loadStaticField(Type owner, String name, Type t) {
   mv.visitFieldInsn(Opcodes.GETSTATIC, owner.getInternalName(), name, t.getDescriptor());
   return this;
 }
示例#18
0
 public static boolean isArray(Type t) {
   return t.getSort() == Type.ARRAY;
 }
示例#19
0
 public static boolean isThrowable(Type t) {
   return t.equals(throwableType);
 }
示例#20
0
 public Assembler loadLocal(Type type, int index) {
   mv.visitVarInsn(type.getOpcode(ILOAD), index);
   return this;
 }
示例#21
0
 public Assembler arrayStore(Type type) {
   mv.visitInsn(type.getOpcode(IASTORE));
   return this;
 }
示例#22
0
 public Assembler storeLocal(Type type, int index) {
   mv.visitVarInsn(type.getOpcode(ISTORE), index);
   return this;
 }