Example usage for org.objectweb.asm.commons GeneratorAdapter checkCast

List of usage examples for org.objectweb.asm.commons GeneratorAdapter checkCast

Introduction

In this page you can find the example usage for org.objectweb.asm.commons GeneratorAdapter checkCast.

Prototype

public void checkCast(final Type type) 

Source Link

Document

Generates the instruction to check that the top stack value is of the given type.

Usage

From source file:co.cask.cdap.app.runtime.spark.SparkRunnerClassLoader.java

License:Apache License

/**
 * Defines the org.apache.spark.deploy.yarn.Client class with rewriting of the createConfArchive method to
 * workaround the SPARK-13441 bug./*from w  ww.j ava 2  s.c om*/
 */
private Class<?> defineClient(String name, InputStream createConfArchive)
        throws IOException, ClassNotFoundException {
    // We only need to rewrite if listing either HADOOP_CONF_DIR or YARN_CONF_DIR return null.
    boolean needRewrite = false;
    for (String env : ImmutableList.of("HADOOP_CONF_DIR", "YARN_CONF_DIR")) {
        String value = System.getenv(env);
        if (value != null) {
            File path = new File(value);
            if (path.isDirectory() && path.listFiles() == null) {
                needRewrite = true;
                break;
            }
        }
    }

    // If rewrite is not needed
    if (!needRewrite) {
        return findClass(name);
    }

    ClassReader cr = new ClassReader(createConfArchive);
    ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
    cr.accept(new ClassVisitor(Opcodes.ASM5, cw) {
        @Override
        public MethodVisitor visitMethod(final int access, final String name, final String desc,
                String signature, String[] exceptions) {
            MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);

            // Only rewrite the createConfArchive method
            if (!"createConfArchive".equals(name)) {
                return mv;
            }

            // Check if it's a recognizable return type.
            // Spark 1.5+ return type is File
            boolean isReturnFile = Type.getReturnType(desc).equals(Type.getType(File.class));
            Type optionType = Type.getObjectType("scala/Option");
            if (!isReturnFile) {
                // Spark 1.4 return type is Option<File>
                if (!Type.getReturnType(desc).equals(optionType)) {
                    // Unknown type. Not going to modify the code.
                    return mv;
                }
            }

            // Generate this for Spark 1.5+
            // return SparkRuntimeUtils.createConfArchive(this.sparkConf, SPARK_CONF_FILE,
            //                                            LOCALIZED_CONF_DIR, LOCALIZED_CONF_DIR_ZIP);
            // Generate this for Spark 1.4
            // return Option.apply(SparkRuntimeUtils.createConfArchive(this.sparkConf, SPARK_CONF_FILE,
            //                                                         LOCALIZED_CONF_DIR, LOCALIZED_CONF_DIR_ZIP));
            GeneratorAdapter mg = new GeneratorAdapter(mv, access, name, desc);

            // load this.sparkConf to the stack
            mg.loadThis();
            mg.getField(Type.getObjectType("org/apache/spark/deploy/yarn/Client"), "sparkConf",
                    SPARK_CONF_TYPE);

            // push three constants to the stack
            mg.visitLdcInsn(SPARK_CONF_FILE);
            mg.visitLdcInsn(LOCALIZED_CONF_DIR);
            mg.visitLdcInsn(LOCALIZED_CONF_DIR_ZIP);

            // call SparkRuntimeUtils.createConfArchive, return a File and leave it in stack
            Type stringType = Type.getType(String.class);
            mg.invokeStatic(SPARK_RUNTIME_UTILS_TYPE, new Method("createConfArchive", Type.getType(File.class),
                    new Type[] { SPARK_CONF_TYPE, stringType, stringType, stringType }));
            if (isReturnFile) {
                // Spark 1.5+ return type is File, hence just return the File from the stack
                mg.returnValue();
                mg.endMethod();
            } else {
                // Spark 1.4 return type is Option<File>
                // return Option.apply(<file from stack>);
                // where the file is actually just popped from the stack
                mg.invokeStatic(optionType,
                        new Method("apply", optionType, new Type[] { Type.getType(Object.class) }));
                mg.checkCast(optionType);
                mg.returnValue();
                mg.endMethod();
            }

            return null;
        }
    }, ClassReader.EXPAND_FRAMES);

    byte[] byteCode = cw.toByteArray();
    return defineClass(name, byteCode, 0, byteCode.length);
}

From source file:co.cask.cdap.internal.io.DatumWriterGenerator.java

License:Apache License

/**
 * Generates the {@link DatumWriter#encode(Object, co.cask.cdap.common.io.Encoder)} method.
 * @param outputType Type information of the data type for output
 * @param schema Schema to use for output.
 *///w w  w. j  a  v  a 2 s  . co m
private void generateEncode(TypeToken<?> outputType, Schema schema) {
    TypeToken<?> callOutputType = getCallTypeToken(outputType, schema);

    Method encodeMethod = getMethod(void.class, "encode", callOutputType.getRawType(), Encoder.class);

    if (!Object.class.equals(callOutputType.getRawType())) {
        // Generate the synthetic method for the bridging
        Method method = getMethod(void.class, "encode", Object.class, Encoder.class);
        GeneratorAdapter mg = new GeneratorAdapter(
                Opcodes.ACC_PUBLIC + Opcodes.ACC_BRIDGE + Opcodes.ACC_SYNTHETIC, method, null,
                new Type[] { Type.getType(IOException.class) }, classWriter);

        mg.loadThis();
        mg.loadArg(0);
        mg.checkCast(Type.getType(callOutputType.getRawType()));
        mg.loadArg(1);
        mg.invokeVirtual(classType, encodeMethod);
        mg.returnValue();
        mg.endMethod();
    }

    // Generate the top level public encode method
    String methodSignature = null;
    if (callOutputType.getType() instanceof ParameterizedType) {
        methodSignature = Signatures.getMethodSignature(encodeMethod, callOutputType, null);
    }
    GeneratorAdapter mg = new GeneratorAdapter(Opcodes.ACC_PUBLIC, encodeMethod, methodSignature,
            new Type[] { Type.getType(IOException.class) }, classWriter);

    // Delegate to the actual encode method(value, encoder, schema, Sets.newIdentityHashSet());
    mg.loadThis();
    mg.loadArg(0);
    mg.loadArg(1);
    mg.loadThis();
    mg.getField(classType, "schema", Type.getType(Schema.class));
    // seenRefs Set
    mg.invokeStatic(Type.getType(Sets.class), getMethod(Set.class, "newIdentityHashSet"));
    mg.invokeVirtual(classType, getEncodeMethod(outputType, schema));
    mg.returnValue();
    mg.endMethod();
}

From source file:co.cask.cdap.internal.io.DatumWriterGenerator.java

License:Apache License

/**
 * Generates method body for encoding simple schema type by calling corresponding write method in Encoder.
 * @param mg Method body generator/*w  ww . j  av  a  2 s  . co m*/
 * @param type Data type to encode
 * @param encodeMethod Name of the encode method to invoke on the given encoder.
 * @param value Argument index of the value to encode.
 * @param encoder Method argument index of the encoder
 */
private void encodeSimple(GeneratorAdapter mg, TypeToken<?> type, Schema schema, String encodeMethod, int value,
        int encoder) {
    // encoder.writeXXX(value);
    TypeToken<?> encodeType = type;
    mg.loadArg(encoder);
    mg.loadArg(value);
    if (Primitives.isWrapperType(encodeType.getRawType())) {
        encodeType = TypeToken.of(Primitives.unwrap(encodeType.getRawType()));
        mg.unbox(Type.getType(encodeType.getRawType()));
        // A special case since INT type represents (byte, char, short and int).
        if (schema.getType() == Schema.Type.INT && !int.class.equals(encodeType.getRawType())) {
            encodeType = TypeToken.of(int.class);
        }
    } else if (schema.getType() == Schema.Type.STRING && !String.class.equals(encodeType.getRawType())) {
        // For non-string object that has a String schema, invoke toString().
        mg.invokeVirtual(Type.getType(encodeType.getRawType()), getMethod(String.class, "toString"));
        encodeType = TypeToken.of(String.class);
    } else if (schema.getType() == Schema.Type.BYTES && UUID.class.equals(encodeType.getRawType())) {
        // Special case UUID, encode as byte array

        // ByteBuffer buf = ByteBuffer.allocate(Longs.BYTES * 2)
        //                            .putLong(uuid.getMostSignificantBits())
        //                            .putLong(uuid.getLeastSignificantBits());
        // encoder.writeBytes((ByteBuffer) buf.flip());

        Type byteBufferType = Type.getType(ByteBuffer.class);
        Type uuidType = Type.getType(UUID.class);

        mg.push(Longs.BYTES * 2);
        mg.invokeStatic(byteBufferType, getMethod(ByteBuffer.class, "allocate", int.class));
        mg.swap();

        mg.invokeVirtual(uuidType, getMethod(long.class, "getMostSignificantBits"));
        mg.invokeVirtual(byteBufferType, getMethod(ByteBuffer.class, "putLong", long.class));

        mg.loadArg(value);
        mg.invokeVirtual(uuidType, getMethod(long.class, "getLeastSignificantBits"));
        mg.invokeVirtual(byteBufferType, getMethod(ByteBuffer.class, "putLong", long.class));

        mg.invokeVirtual(Type.getType(Buffer.class), getMethod(Buffer.class, "flip"));
        mg.checkCast(byteBufferType);

        encodeType = TypeToken.of(ByteBuffer.class);
    }
    mg.invokeInterface(Type.getType(Encoder.class),
            getMethod(Encoder.class, encodeMethod, encodeType.getRawType()));
    mg.pop();
}

From source file:co.cask.cdap.internal.io.DatumWriterGenerator.java

License:Apache License

/**
 * Generates method body for encoding map value. The logic is like this:
 *
 * <pre>/* w  w w .j a v  a2  s . c  om*/
 * {@code
 *
 * encoder.writeInt(map.size();
 *
 * for (Map.Entry<Key, Value> entry : map.entrySet()) {
 *   encodeKey(entry.getKey(), encoder, keySchema, seenRefs);
 *   encodeValue(entry.getValue(), encoder, valueSchema, seenRefs);
 * }
 *
 * if (map.size() > 0) {
 *   encoder.writeInt(0);
 * }
 * }
 * </pre>
 *
 * @param mg
 * @param keyType
 * @param valueType
 * @param keySchema
 * @param valueSchema
 * @param value
 * @param encoder
 * @param schemaLocal
 * @param seenRefs
 */
private void encodeMap(GeneratorAdapter mg, TypeToken<?> keyType, TypeToken<?> valueType, Schema keySchema,
        Schema valueSchema, int value, int encoder, int schemaLocal, int seenRefs) {
    // Encode and store the map length locally
    mg.loadArg(value);
    mg.invokeInterface(Type.getType(Map.class), getMethod(int.class, "size"));
    int length = mg.newLocal(Type.INT_TYPE);
    mg.storeLocal(length);

    mg.loadArg(encoder);
    mg.loadLocal(length);
    mg.invokeInterface(Type.getType(Encoder.class), getMethod(Encoder.class, "writeInt", int.class));
    mg.pop();

    // Stores the key and value schema
    mg.loadArg(schemaLocal);
    mg.invokeVirtual(Type.getType(Schema.class), getMethod(Map.Entry.class, "getMapSchema"));
    mg.dup();

    int keySchemaLocal = mg.newLocal(Type.getType(Schema.class));
    mg.invokeInterface(Type.getType(Map.Entry.class), getMethod(Object.class, "getKey"));
    mg.checkCast(Type.getType(Schema.class));
    mg.storeLocal(keySchemaLocal);

    int valueSchemaLocal = mg.newLocal(Type.getType(Schema.class));
    mg.invokeInterface(Type.getType(Map.Entry.class), getMethod(Object.class, "getValue"));
    mg.checkCast(Type.getType(Schema.class));
    mg.storeLocal(valueSchemaLocal);

    // Store the entry set iterator
    int iterator = mg.newLocal(Type.getType(Iterator.class));
    mg.loadArg(value);
    mg.invokeInterface(Type.getType(Map.class), getMethod(Set.class, "entrySet"));
    mg.invokeInterface(Type.getType(Set.class), getMethod(Iterator.class, "iterator"));
    mg.storeLocal(iterator);

    // For loop the entry set iterator, encode each key-value pairs
    Label beginFor = mg.mark();
    Label endFor = mg.newLabel();
    mg.loadLocal(iterator);
    mg.invokeInterface(Type.getType(Iterator.class), getMethod(boolean.class, "hasNext"));
    mg.ifZCmp(GeneratorAdapter.EQ, endFor);

    int entry = mg.newLocal(Type.getType(Map.Entry.class));
    mg.loadLocal(iterator);
    mg.invokeInterface(Type.getType(Iterator.class), getMethod(Object.class, "next"));
    mg.checkCast(Type.getType(Map.Entry.class));
    mg.storeLocal(entry);

    // encode key
    mg.loadThis();
    mg.loadLocal(entry);
    mg.invokeInterface(Type.getType(Map.Entry.class), getMethod(Object.class, "getKey"));
    doCast(mg, keyType, keySchema);
    mg.loadArg(encoder);
    mg.loadLocal(keySchemaLocal);
    mg.loadArg(seenRefs);
    mg.invokeVirtual(classType, getEncodeMethod(keyType, keySchema));

    // encode value
    mg.loadThis();
    mg.loadLocal(entry);
    mg.invokeInterface(Type.getType(Map.Entry.class), getMethod(Object.class, "getValue"));
    doCast(mg, valueType, valueSchema);
    mg.loadArg(encoder);
    mg.loadLocal(valueSchemaLocal);
    mg.loadArg(seenRefs);
    mg.invokeVirtual(classType, getEncodeMethod(valueType, valueSchema));

    mg.goTo(beginFor);
    mg.mark(endFor);

    // if length > 0, write out 0 at the end of map
    Label zeroLength = mg.newLabel();
    mg.loadLocal(length);
    mg.ifZCmp(GeneratorAdapter.LE, zeroLength);
    encodeInt(mg, 0, encoder);
    mg.mark(zeroLength);
}

From source file:co.cask.cdap.internal.io.DatumWriterGenerator.java

License:Apache License

/**
 * Generates method body for encoding java class. If the class given is an interface,
 * getter method will be used to access the field values, otherwise, it will assumes
 * fields are public.//w w  w  .  j  a va 2 s . c om
 *
 * @param mg
 * @param schema
 * @param outputType
 * @param value
 * @param encoder
 * @param schemaLocal
 * @param seenRefs
 */
private void encodeRecord(GeneratorAdapter mg, Schema schema, TypeToken<?> outputType, int value, int encoder,
        int schemaLocal, int seenRefs) {

    try {
        Class<?> rawType = outputType.getRawType();

        // Record type might be defined by the user, hence need to preserve class loading of it
        preservedClasses.add(rawType);
        boolean isInterface = rawType.isInterface();

        /*
          Check for circular reference
          if (value != null && !seenRefs.add(value)) {
             throw new IOException(...);
          }
        */
        Label notSeen = mg.newLabel();
        mg.loadArg(value);
        mg.ifNull(notSeen);
        mg.loadArg(seenRefs);
        mg.loadArg(value);
        mg.invokeInterface(Type.getType(Set.class), getMethod(boolean.class, "add", Object.class));
        mg.ifZCmp(GeneratorAdapter.NE, notSeen);
        mg.throwException(Type.getType(IOException.class), "Circular reference not supported.");
        mg.mark(notSeen);

        // Store the list of schema fields.
        mg.loadArg(schemaLocal);
        mg.invokeVirtual(Type.getType(Schema.class), getMethod(List.class, "getFields"));
        int fieldSchemas = mg.newLocal(Type.getType(List.class));
        mg.storeLocal(fieldSchemas);

        // For each field, call the encode method for the field
        List<Schema.Field> fields = schema.getFields();
        for (int i = 0; i < fields.size(); i++) {
            Schema.Field field = fields.get(i);

            TypeToken<?> fieldType;

            // this.encodeFieldMethod(value.fieldName, encoder, fieldSchemas.get(i).getSchema());
            if (isInterface) {
                mg.loadThis();
                mg.loadArg(value);
                Method getter = getGetter(outputType, field.getName());
                fieldType = outputType.resolveType(rawType.getMethod(getter.getName()).getGenericReturnType());
                mg.invokeInterface(Type.getType(rawType), getter);
            } else {
                fieldType = outputType
                        .resolveType(Fields.findField(outputType.getType(), field.getName()).getGenericType());
                fieldAccessorRequests.put(outputType, field.getName());
                mg.loadThis();
                mg.dup();
                mg.getField(classType, getFieldAccessorName(outputType, field.getName()),
                        Type.getType(FieldAccessor.class));
                mg.loadArg(value);
                mg.invokeInterface(Type.getType(FieldAccessor.class), getAccessorMethod(fieldType));
                if (!fieldType.getRawType().isPrimitive()) {
                    doCast(mg, fieldType, field.getSchema());
                }
            }
            mg.loadArg(encoder);
            mg.loadLocal(fieldSchemas);
            mg.push(i);
            mg.invokeInterface(Type.getType(List.class), getMethod(Object.class, "get", int.class));
            mg.checkCast(Type.getType(Schema.Field.class));
            mg.invokeVirtual(Type.getType(Schema.Field.class), getMethod(Schema.class, "getSchema"));
            mg.loadArg(seenRefs);
            mg.invokeVirtual(classType, getEncodeMethod(fieldType, field.getSchema()));
        }
    } catch (Exception e) {
        throw Throwables.propagate(e);
    }
}

From source file:co.cask.cdap.internal.io.DatumWriterGenerator.java

License:Apache License

/**
 * Optionally generates a type cast instruction based on the result of
 * {@link #getCallTypeToken(com.google.common.reflect.TypeToken, Schema)}.
 * @param mg A {@link GeneratorAdapter} for generating instructions
 * @param outputType/*from  w  w  w  .  ja  va 2s .c  o  m*/
 * @param schema
 */
private void doCast(GeneratorAdapter mg, TypeToken<?> outputType, Schema schema) {
    TypeToken<?> callTypeToken = getCallTypeToken(outputType, schema);
    if (!Object.class.equals(callTypeToken.getRawType()) && !outputType.getRawType().isPrimitive()) {
        mg.checkCast(Type.getType(callTypeToken.getRawType()));
    }
}

From source file:co.cask.cdap.internal.io.FieldAccessorGenerator.java

License:Apache License

/**
 * Generates a getter that get the value by directly accessing the class field.
 * @param field The reflection field object.
 *///w w w  .  j ava  2s .  c om
private void directGetter(Field field) {
    GeneratorAdapter mg = new GeneratorAdapter(Opcodes.ACC_PUBLIC, getMethod(Object.class, "get", Object.class),
            getterSignature(), new Type[0], classWriter);
    // Simply access by field
    // return ((classType)object).fieldName;
    mg.loadArg(0);
    mg.checkCast(Type.getType(field.getDeclaringClass()));
    mg.getField(Type.getType(field.getDeclaringClass()), field.getName(), Type.getType(field.getType()));
    if (field.getType().isPrimitive()) {
        mg.valueOf(Type.getType(field.getType()));
    }
    mg.returnValue();
    mg.endMethod();
}

From source file:co.cask.cdap.internal.io.FieldAccessorGenerator.java

License:Apache License

/**
 * Generates a setter that set the value by directly accessing the class field.
 * @param field The reflection field object.
 *//*from www. j  a  v a 2  s . co  m*/
private void directSetter(Field field) {
    GeneratorAdapter mg = new GeneratorAdapter(Opcodes.ACC_PUBLIC,
            getMethod(void.class, "set", Object.class, Object.class), setterSignature(), new Type[0],
            classWriter);
    // Simply access by field
    // ((classType)object).fieldName = (valueType)value;
    mg.loadArg(0);
    mg.checkCast(Type.getType(field.getDeclaringClass()));
    mg.loadArg(1);
    if (field.getType().isPrimitive()) {
        mg.unbox(Type.getType(field.getType()));
    } else {
        mg.checkCast(Type.getType(field.getType()));
    }
    mg.putField(Type.getType(field.getDeclaringClass()), field.getName(), Type.getType(field.getType()));
    mg.returnValue();
    mg.endMethod();
}

From source file:co.cask.cdap.internal.io.FieldAccessorGenerator.java

License:Apache License

/**
 * Generates the primitive getter (getXXX) based on the field type.
 * @param field The reflection field object.
 *///  ww w.  j  a  v a 2  s  . c  om
private void primitiveGetter(Field field) {
    String typeName = field.getType().getName();
    String methodName = String.format("get%c%s", Character.toUpperCase(typeName.charAt(0)),
            typeName.substring(1));

    GeneratorAdapter mg = new GeneratorAdapter(Opcodes.ACC_PUBLIC,
            getMethod(field.getType(), methodName, Object.class), null, new Type[0], classWriter);
    if (isPrivate) {
        // get the value using the generic Object get(Object) method and unbox the value
        mg.loadThis();
        mg.loadArg(0);
        mg.invokeVirtual(Type.getObjectType(className), getMethod(Object.class, "get", Object.class));
        mg.unbox(Type.getType(field.getType()));
    } else {
        // Simply access the field.
        mg.loadArg(0);
        mg.checkCast(Type.getType(field.getDeclaringClass()));
        mg.getField(Type.getType(field.getDeclaringClass()), field.getName(), Type.getType(field.getType()));
    }
    mg.returnValue();
    mg.endMethod();
}

From source file:co.cask.cdap.internal.io.FieldAccessorGenerator.java

License:Apache License

/**
 * Generates the primitive setter (setXXX) based on the field type.
 * @param field The reflection field object.
 *///from  ww  w. j av a 2  s  .  com
private void primitiveSetter(Field field) {
    String typeName = field.getType().getName();
    String methodName = String.format("set%c%s", Character.toUpperCase(typeName.charAt(0)),
            typeName.substring(1));

    GeneratorAdapter mg = new GeneratorAdapter(Opcodes.ACC_PUBLIC,
            getMethod(void.class, methodName, Object.class, field.getType()), null, new Type[0], classWriter);
    if (isPrivate) {
        // set the value using the generic void get(Object, Object) method with boxing the value.
        mg.loadThis();
        mg.loadArgs();
        mg.valueOf(Type.getType(field.getType()));
        mg.invokeVirtual(Type.getObjectType(className),
                getMethod(void.class, "set", Object.class, Object.class));
    } else {
        // Simply access the field.
        mg.loadArg(0);
        mg.checkCast(Type.getType(field.getDeclaringClass()));
        mg.loadArg(1);
        mg.putField(Type.getType(field.getDeclaringClass()), field.getName(), Type.getType(field.getType()));
    }
    mg.returnValue();
    mg.endMethod();

}