List of usage examples for org.objectweb.asm.commons GeneratorAdapter checkCast
public void checkCast(final Type type)
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(); }