Java tutorial
/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.directmemory.lightning.internal.generator; import java.io.File; import java.io.FileOutputStream; import java.io.PrintStream; import java.lang.reflect.Constructor; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import org.apache.directmemory.lightning.Marshaller; import org.apache.directmemory.lightning.MarshallerStrategy; import org.apache.directmemory.lightning.SerializationStrategy; import org.apache.directmemory.lightning.exceptions.SerializerMarshallerGeneratorException; import org.apache.directmemory.lightning.instantiator.ObjectInstantiatorFactory; import org.apache.directmemory.lightning.internal.ClassDescriptorAwareSerializer; import org.apache.directmemory.lightning.internal.InternalMarshallerStrategy; import org.apache.directmemory.lightning.internal.util.ClassUtil; import org.apache.directmemory.lightning.metadata.PropertyDescriptor; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.FieldVisitor; import org.objectweb.asm.Label; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; public class BytecodeMarshallerGenerator implements Opcodes, GeneratorConstants, MarshallerGenerator { private final GeneratorClassLoader classloader = CreateClassLoader .createClassLoader(getClass().getClassLoader()); @Override public Marshaller generateMarshaller(Class<?> type, List<PropertyDescriptor> propertyDescriptors, Map<Class<?>, Marshaller> marshallers, ClassDescriptorAwareSerializer serializer, SerializationStrategy serializationStrategy, ObjectInstantiatorFactory objectInstantiatorFactory, File debugCacheDirectory) { try { ClassWriter cw = new ClassWriter(0); // Copy properties and sort them by name List<PropertyDescriptor> propertyDescriptorsCopy = new ArrayList<PropertyDescriptor>( propertyDescriptors); Collections.sort(propertyDescriptorsCopy); // Build className e.g. "SomeTypeMarshaller$$X$$Lightning" String className = new StringBuilder( !type.isArray() ? type.getSimpleName() : type.getComponentType().getSimpleName() + "Array") .append("Marshaller").append(GENEREATED_CLASS_ID.getAndIncrement()).append("Lightning") .toString(); // Build class cw.visit(V1_6, ACC_PUBLIC & ACC_SUPER, className, null, SUPER_CLASS_INTERNAL_TYPE, null); // Build marshaller fields createMarshallerFields(cw, propertyDescriptorsCopy); // Build constructor createConstructor(cw, className, propertyDescriptorsCopy); // Build Marshaller#marshall method createMarshallMethod(cw, className, type, serializationStrategy, propertyDescriptorsCopy); // Build Marshaller#unmarshall method createUnmarshallMethod(cw, className, type, propertyDescriptorsCopy); // Closing class visit cw.visitEnd(); final byte[] bytecode = cw.toByteArray(); if (debugCacheDirectory != null) { File file = new File(debugCacheDirectory, className + ".class"); FileOutputStream out = new FileOutputStream(file); out.write(bytecode); out.flush(); out.close(); } Class<? extends Marshaller> generatedClass = classloader.loadClass(bytecode); Constructor<? extends Marshaller> constructor = generatedClass.getConstructor(Class.class, Map.class, ClassDescriptorAwareSerializer.class, ObjectInstantiatorFactory.class, List.class, MarshallerStrategy.class); constructor.setAccessible(true); return constructor.newInstance(type, marshallers, serializer, objectInstantiatorFactory, propertyDescriptorsCopy, new InternalMarshallerStrategy()); } catch (Exception e) { throw new SerializerMarshallerGeneratorException( "Marshaller for type " + type + " could not be generated", e); } } private void createMarshallerFields(ClassWriter cw, List<PropertyDescriptor> propertyDescriptors) { for (int i = 0; i < propertyDescriptors.size(); i++) { PropertyDescriptor propertyDescriptor = propertyDescriptors.get(i); FieldVisitor fv = null; // Write PropertyDescriptor field fv = cw.visitField(ACC_FINAL & ACC_PRIVATE, toFinalFieldName("descriptor", propertyDescriptor), PROPERTYDESCRIPTOR_CLASS_DESCRIPTOR, null, null); fv.visitEnd(); if (propertyDescriptor.getType().isArray() && !propertyDescriptor.getType().getComponentType().isPrimitive()) { // Write ComponentType PropertyDescriptor field fv = cw.visitField(ACC_FINAL & ACC_PRIVATE, toFinalFieldName("component", propertyDescriptor), CHEATINGPROPERTYDESCRIPTOR_CLASS_DESCRIPTOR, null, null); fv.visitEnd(); } // Write Marshaller field fv = cw.visitField(ACC_FINAL & ACC_PRIVATE, toFinalFieldName("marshaller", propertyDescriptor), MARSHALLER_CLASS_DESCRIPTOR, null, null); fv.visitEnd(); // Write PropertyAccessor field fv = cw.visitField(ACC_FINAL & ACC_PRIVATE, toFinalFieldName("accessor", propertyDescriptor), PROPERTYACCESSOR_CLASS_DESCRIPTOR, null, null); fv.visitEnd(); } } private void createConstructor(ClassWriter cw, String className, List<PropertyDescriptor> propertyDescriptors) { MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", MARSHALLER_CONSTRUCTOR_SIGNATURE, null, null); mv.visitCode(); // Load this mv.visitVarInsn(ALOAD, 0); // Load first parameter type (Class) mv.visitVarInsn(ALOAD, 1); // Load second parameter type (Map) mv.visitVarInsn(ALOAD, 2); // Load third parameter type (ClassDescriptorAwaySerializer) mv.visitVarInsn(ALOAD, 3); // Load fourth parameter type (ObjenesisSerializer) mv.visitVarInsn(ALOAD, 4); // Call super(Class, Map) mv.visitMethodInsn(INVOKESPECIAL, SUPER_CLASS_INTERNAL_TYPE, "<init>", MARSHALLER_SUPER_CONSTRUCTOR_SIGNATURE); // Fill fields with marshallers for (int i = 0; i < propertyDescriptors.size(); i++) { PropertyDescriptor propertyDescriptor = propertyDescriptors.get(i); String fieldName = toFinalFieldName("marshaller", propertyDescriptor); mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 0); // Load property type mv.visitVarInsn(ALOAD, 5); mv.visitIntInsn(BIPUSH, i); mv.visitMethodInsn(INVOKEINTERFACE, LIST_CLASS_INTERNAL_TYPE, "get", "(I)Ljava/lang/Object;"); // Store PropertyDescriptor mv.visitTypeInsn(CHECKCAST, PROPERTYDESCRIPTOR_CLASS_INTERNAL_TYPE); mv.visitFieldInsn(PUTFIELD, className, toFinalFieldName("descriptor", propertyDescriptor), PROPERTYDESCRIPTOR_CLASS_DESCRIPTOR); if (propertyDescriptor.getType().isArray() && !propertyDescriptor.getType().getComponentType().isPrimitive()) { Label labelNonNull = new Label(); // Get type from PropertyAccessor mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn(GETFIELD, className, toFinalFieldName("descriptor", propertyDescriptor), PROPERTYDESCRIPTOR_CLASS_DESCRIPTOR); mv.visitMethodInsn(INVOKEINTERFACE, PROPERTYDESCRIPTOR_CLASS_INTERNAL_TYPE, "getType", "()Ljava/lang/Class;"); // Get array component type mv.visitMethodInsn(INVOKEVIRTUAL, CLASS_CLASS_INTERNAL_TYPE, "getComponentType", CLASS_GET_COMPONENT_TYPE); mv.visitVarInsn(ASTORE, 9); // Generate cheating PropertyDescriptor for component type mv.visitVarInsn(ALOAD, 0); mv.visitTypeInsn(NEW, CHEATINGPROPERTYDESCRIPTOR_CLASS_INTERNAL_TYPE); mv.visitInsn(DUP); mv.visitLdcInsn(propertyDescriptor.getPropertyName() + "Element"); mv.visitVarInsn(ALOAD, 9); mv.visitInsn(ACONST_NULL); mv.visitMethodInsn(INVOKESPECIAL, CHEATINGPROPERTYDESCRIPTOR_CLASS_INTERNAL_TYPE, "<init>", CHEATINGPROPERTYDESCRIPTOR_CONSTRUCTOR); mv.visitFieldInsn(PUTFIELD, className, toFinalFieldName("component", propertyDescriptor), CHEATINGPROPERTYDESCRIPTOR_CLASS_DESCRIPTOR); // Search marshaller by using interal ones mv.visitVarInsn(ALOAD, 6); mv.visitVarInsn(ALOAD, 9); mv.visitInsn(ACONST_NULL); mv.visitMethodInsn(INVOKEINTERFACE, MARSHALLERSTRATEGY_CLASS_INTERNAL_TYPE, "getMarshaller", MARSHALLERSTRATEGY_GET_MARSHALLER_SIGNATURE); mv.visitVarInsn(ASTORE, 8); mv.visitVarInsn(ALOAD, 8); // Search marshaller for property type mv.visitJumpInsn(IFNONNULL, labelNonNull); mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn(GETFIELD, className, toFinalFieldName("component", propertyDescriptor), CHEATINGPROPERTYDESCRIPTOR_CLASS_DESCRIPTOR); mv.visitMethodInsn(INVOKEVIRTUAL, SUPER_CLASS_INTERNAL_TYPE, "findMarshaller", MARSHALLER_FIND_MARSHALLER_SIGNATURE); mv.visitVarInsn(ASTORE, 8); // Save marshaller to field mv.visitLabel(labelNonNull); mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 8); mv.visitFieldInsn(PUTFIELD, className, toFinalFieldName("marshaller", propertyDescriptor), MARSHALLER_CLASS_DESCRIPTOR); } else { // Check if marshaller is defined mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn(GETFIELD, className, toFinalFieldName("descriptor", propertyDescriptor), PROPERTYDESCRIPTOR_CLASS_DESCRIPTOR); mv.visitMethodInsn(INVOKEVIRTUAL, SUPER_CLASS_INTERNAL_TYPE, "findMarshaller", MARSHALLER_FIND_MARSHALLER_SIGNATURE); mv.visitFieldInsn(PUTFIELD, className, fieldName, MARSHALLER_CLASS_DESCRIPTOR); } // Load this to method stack mv.visitVarInsn(ALOAD, 0); mv.visitInsn(DUP); // Load property accessor mv.visitFieldInsn(GETFIELD, className, toFinalFieldName("descriptor", propertyDescriptor), PROPERTYDESCRIPTOR_CLASS_DESCRIPTOR); mv.visitMethodInsn(INVOKEINTERFACE, PROPERTYDESCRIPTOR_CLASS_INTERNAL_TYPE, "getPropertyAccessor", PROPERTY_DESCRIPTOR_GET_PROPERTYACCESSOR_SIGNATURE); // Save PropertyAccessor to field mv.visitFieldInsn(PUTFIELD, className, toFinalFieldName("accessor", propertyDescriptor), PROPERTYACCESSOR_CLASS_DESCRIPTOR); } mv.visitInsn(RETURN); mv.visitMaxs(-1, 12); mv.visitEnd(); } private void createMarshallMethod(ClassWriter cw, String className, Class<?> type, SerializationStrategy serializationStrategy, List<PropertyDescriptor> propertyDescriptors) { MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "marshall", MARSHALLER_MARSHALL_SIGNATURE, null, MARSHALLER_EXCEPTIONS); // If element type is not reference capable or SerializationStrategy is // not SizeOptimized just prevent generation of code if (serializationStrategy == SerializationStrategy.SizeOptimized && ClassUtil.isReferenceCapable(type)) { // Load this to method stack mv.visitVarInsn(ALOAD, 0); // Load value to method stack mv.visitVarInsn(ALOAD, 1); // Load type to method stack mv.visitVarInsn(ALOAD, 2); // Load dataOutput to method stack mv.visitVarInsn(ALOAD, 3); // Load serializationContext to method stack mv.visitVarInsn(ALOAD, 4); // Call super.isAlreadyMarshalled(...); mv.visitMethodInsn(INVOKEVIRTUAL, SUPER_CLASS_INTERNAL_TYPE, "isAlreadyMarshalled", MARSHALLER_IS_ALREADY_MARSHALLED_SIGNATURE); // Label if value is not yet marshalled Label notYetMarshalled = new Label(); // Test if already marshalled mv.visitJumpInsn(IFEQ, notYetMarshalled); // If marshalled - just return mv.visitInsn(RETURN); // Visit label - if not yet marshalled - marshall it mv.visitLabel(notYetMarshalled); } for (PropertyDescriptor propertyDescriptor : propertyDescriptors) { if (propertyDescriptor.getType().isArray() && !propertyDescriptor.getType().getComponentType().isPrimitive()) { visitObjectArrayPropertyAccessorRead(mv, className, propertyDescriptor); } else { visitValuePropertyAccessorRead(mv, className, propertyDescriptor); } } // Add Return instruction mv.visitInsn(RETURN); // End visiting mv.visitMaxs(9, 9); mv.visitEnd(); } private void visitValuePropertyAccessorRead(MethodVisitor mv, String className, PropertyDescriptor propertyDescriptor) { Class<?> propertyType = propertyDescriptor.getType(); // Load this to method stack mv.visitVarInsn(ALOAD, 0); // Load property marshaller on stack mv.visitFieldInsn(GETFIELD, className, toFinalFieldName("marshaller", propertyDescriptor), MARSHALLER_CLASS_DESCRIPTOR); // Load this to method stack mv.visitVarInsn(ALOAD, 0); // Read PropertyAccessor from field mv.visitFieldInsn(GETFIELD, className, toFinalFieldName("accessor", propertyDescriptor), PROPERTYACCESSOR_CLASS_DESCRIPTOR); // Load value to method stack mv.visitVarInsn(ALOAD, 1); // Load value by type on stack visitPropertyAccessorValueRead(propertyType, mv); // If type is primitive add some "autoboxing" magic if (propertyType.isPrimitive()) { visitWrapperAutoboxing(propertyType, mv); } // Load type to method stack mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn(GETFIELD, className, toFinalFieldName("descriptor", propertyDescriptor), PROPERTYDESCRIPTOR_CLASS_DESCRIPTOR); // Load DataOutput to method stack mv.visitVarInsn(ALOAD, 3); // Load SerializationContext to method stack mv.visitVarInsn(ALOAD, 4); // Call Marshaller#marshall on properties marshaller mv.visitMethodInsn(INVOKEINTERFACE, MARSHALLER_CLASS_INTERNAL_TYPE, "marshall", MARSHALLER_MARSHALL_SIGNATURE); } private void visitObjectArrayPropertyAccessorRead(MethodVisitor mv, String className, PropertyDescriptor propertyDescriptor) { Class<?> propertyType = propertyDescriptor.getType(); // Load this to method stack mv.visitVarInsn(ALOAD, 0); // Read PropertyAccessor from field mv.visitFieldInsn(GETFIELD, className, toFinalFieldName("accessor", propertyDescriptor), PROPERTYACCESSOR_CLASS_DESCRIPTOR); mv.visitTypeInsn(CHECKCAST, ARRAYPROPERTYACCESSOR_CLASS_INTERNAL_TYPE); mv.visitVarInsn(ASTORE, 8); // Load property type mv.visitVarInsn(ALOAD, 8); mv.visitInsn(DUP); mv.visitMethodInsn(INVOKEINTERFACE, PROPERTYACCESSOR_CLASS_INTERNAL_TYPE, "getType", OBJECT_GET_CLASS_SIGNATURE); mv.visitVarInsn(ASTORE, 5); // Load value to method stack mv.visitVarInsn(ALOAD, 1); // Save array to stack position 6 visitPropertyAccessorValueRead(propertyType, mv); mv.visitTypeInsn(CHECKCAST, Type.getType(propertyType).getInternalName()); mv.visitVarInsn(ASTORE, 6); // Save length to stream mv.visitVarInsn(ALOAD, 3); mv.visitVarInsn(ALOAD, 6); mv.visitInsn(ARRAYLENGTH); mv.visitMethodInsn(INVOKEINTERFACE, DATAOUTPUT_CLASS_INTERNAL_TYPE, "writeInt", "(I)V"); // Loop over every element in array Label forLoopEnd = new Label(); Label forLoopStart = new Label(); mv.visitInsn(ICONST_0); mv.visitVarInsn(ISTORE, 7); mv.visitJumpInsn(GOTO, forLoopEnd); mv.visitLabel(forLoopStart); // Load this to method stack mv.visitVarInsn(ALOAD, 0); // Load property marshaller on stack mv.visitFieldInsn(GETFIELD, className, toFinalFieldName("marshaller", propertyDescriptor), MARSHALLER_CLASS_DESCRIPTOR); // Load PropertyAccessor to method stack mv.visitVarInsn(ALOAD, 8); // Load array to method stack mv.visitVarInsn(ALOAD, 6); // Load index to method stack mv.visitVarInsn(ILOAD, 7); // Get value from array mv.visitMethodInsn(INVOKEINTERFACE, ARRAYPROPERTYACCESSOR_CLASS_INTERNAL_TYPE, "readObject", PROPERTY_ACCESSOR_ARRAY_READ_OBJECT_SIGNATURE); mv.visitTypeInsn(CHECKCAST, Type.getType(propertyType.getComponentType()).getInternalName()); // If type is primitive add some "autoboxing" magic if (propertyType.getComponentType().isPrimitive()) { visitWrapperAutoboxing(propertyType.getComponentType(), mv); } // Load type to method stack mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn(GETFIELD, className, toFinalFieldName("component", propertyDescriptor), CHEATINGPROPERTYDESCRIPTOR_CLASS_DESCRIPTOR); // Load DataOutput to method stack mv.visitVarInsn(ALOAD, 3); // Load SerializationContext to method stack mv.visitVarInsn(ALOAD, 4); // Call Marshaller#marshall on properties marshaller mv.visitMethodInsn(INVOKEINTERFACE, MARSHALLER_CLASS_INTERNAL_TYPE, "marshall", MARSHALLER_MARSHALL_SIGNATURE); // Test if loop ends mv.visitIincInsn(7, 1); mv.visitLabel(forLoopEnd); mv.visitVarInsn(ILOAD, 7); mv.visitVarInsn(ALOAD, 6); mv.visitInsn(ARRAYLENGTH); mv.visitJumpInsn(IF_ICMPLT, forLoopStart); } private void createUnmarshallMethod(ClassWriter cw, String className, Class<?> type, List<PropertyDescriptor> propertyDescriptors) { MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "unmarshall", MARSHALLER_UNMARSHALL_SIGNATURE, null, MARSHALLER_EXCEPTIONS); for (PropertyDescriptor propertyDescriptor : propertyDescriptors) { if (propertyDescriptor.getType().isArray() && !propertyDescriptor.getType().getComponentType().isPrimitive()) { visitObjectArrayPropertyAccessorWrite(mv, className, propertyDescriptor); } else { visitValuePropertyAccessorWrite(mv, className, propertyDescriptor); } } // Load instance to method stack mv.visitVarInsn(ALOAD, 1); // Add Return statement visitReturn(type, mv); // End visiting mv.visitMaxs(11, 11); mv.visitEnd(); } private void visitValuePropertyAccessorWrite(MethodVisitor mv, String className, PropertyDescriptor propertyDescriptor) { Class<?> propertyType = propertyDescriptor.getType(); // Load this to method stack mv.visitVarInsn(ALOAD, 0); // Read PropertyAccessor from field mv.visitFieldInsn(GETFIELD, className, toFinalFieldName("accessor", propertyDescriptor), PROPERTYACCESSOR_CLASS_DESCRIPTOR); // Store PropertyAccessor for later use mv.visitVarInsn(ASTORE, 5); // Load this to method stack mv.visitVarInsn(ALOAD, 0); // Load property marshaller to method stack mv.visitFieldInsn(GETFIELD, className, toFinalFieldName("marshaller", propertyDescriptor), MARSHALLER_CLASS_DESCRIPTOR); // Load this to method stack mv.visitVarInsn(ALOAD, 0); // Load PropertyDescriptor to method stack mv.visitFieldInsn(GETFIELD, className, toFinalFieldName("descriptor", propertyDescriptor), PROPERTYDESCRIPTOR_CLASS_DESCRIPTOR); // Load DataInput to method stack mv.visitVarInsn(ALOAD, 3); // Load SerializationContext to method stack mv.visitVarInsn(ALOAD, 4); // Call Marshaller#unmarshall on properties marshaller mv.visitMethodInsn(INVOKEINTERFACE, MARSHALLER_CLASS_INTERNAL_TYPE, "unmarshall", MARSHALLER_BASE_UNMARSHALL_SIGNATURE); // Save value mv.visitVarInsn(ASTORE, 6); // Load PropertyAccessor to method stack mv.visitVarInsn(ALOAD, 5); // Load instance to method stack mv.visitVarInsn(ALOAD, 1); // Load value to method stack mv.visitVarInsn(ALOAD, 6); // If type is primitive add some "autoboxing" magic if (propertyType.isPrimitive()) { visitPrimitiveAutoboxing(propertyType, mv); } // Call PropertyAccessor#writeX visitPropertyAccessorValueWrite(propertyType, mv); } private void visitObjectArrayPropertyAccessorWrite(MethodVisitor mv, String className, PropertyDescriptor propertyDescriptor) { Class<?> propertyType = propertyDescriptor.getType(); Class<?> componentType = propertyType.getComponentType(); // Read size mv.visitVarInsn(ALOAD, 3); mv.visitMethodInsn(INVOKEINTERFACE, DATAINPUT_CLASS_INTERNAL_TYPE, "readInt", "()I"); mv.visitInsn(DUP); mv.visitVarInsn(ISTORE, 5); // Instantiate array mv.visitTypeInsn(ANEWARRAY, Type.getType(componentType).getInternalName()); mv.visitVarInsn(ASTORE, 6); // Read PropertyAccessor from field mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn(GETFIELD, className, toFinalFieldName("accessor", propertyDescriptor), PROPERTYACCESSOR_CLASS_DESCRIPTOR); mv.visitVarInsn(ASTORE, 9); // Get component type mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn(GETFIELD, className, toFinalFieldName("component", propertyDescriptor), CHEATINGPROPERTYDESCRIPTOR_CLASS_DESCRIPTOR); mv.visitVarInsn(ASTORE, 8); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn(GETFIELD, className, toFinalFieldName("marshaller", propertyDescriptor), MARSHALLER_CLASS_DESCRIPTOR); mv.visitVarInsn(ASTORE, 10); // For loop Label forLoopStart = new Label(); Label forLoopEnd = new Label(); mv.visitInsn(ICONST_0); mv.visitVarInsn(ISTORE, 7); mv.visitJumpInsn(GOTO, forLoopEnd); mv.visitLabel(forLoopStart); // Write value to array mv.visitVarInsn(ALOAD, 9); mv.visitVarInsn(ALOAD, 6); mv.visitVarInsn(ILOAD, 7); // Read value from stream to 4th stack position mv.visitVarInsn(ALOAD, 10); mv.visitVarInsn(ALOAD, 8); mv.visitVarInsn(ALOAD, 3); mv.visitVarInsn(ALOAD, 4); mv.visitMethodInsn(INVOKEINTERFACE, MARSHALLER_CLASS_INTERNAL_TYPE, "unmarshall", MARSHALLER_BASE_UNMARSHALL_SIGNATURE); mv.visitMethodInsn(INVOKEINTERFACE, ARRAYPROPERTYACCESSOR_CLASS_INTERNAL_TYPE, "writeObject", PROPERTY_ACCESSOR_ARRAY_WRITE_OBJECT_SIGNATURE); // Increment counter mv.visitIincInsn(7, 1); // Test for loop end mv.visitLabel(forLoopEnd); mv.visitVarInsn(ILOAD, 7); mv.visitVarInsn(ILOAD, 5); mv.visitJumpInsn(IF_ICMPLT, forLoopStart); // Write array to object mv.visitVarInsn(ALOAD, 9); mv.visitVarInsn(ALOAD, 1); mv.visitVarInsn(ALOAD, 6); visitPropertyAccessorValueWrite(propertyType.getComponentType(), mv); } private void visitReturn(Class<?> type, MethodVisitor mv) { int returnOpcode = ARETURN; if (type == boolean.class) { returnOpcode = IRETURN; } else if (type == byte.class) { returnOpcode = IRETURN; } else if (type == char.class) { returnOpcode = IRETURN; } else if (type == short.class) { returnOpcode = IRETURN; } else if (type == int.class) { returnOpcode = IRETURN; } else if (type == long.class) { returnOpcode = LRETURN; } else if (type == float.class) { returnOpcode = FRETURN; } else if (type == double.class) { returnOpcode = DRETURN; } else { returnOpcode = ARETURN; } mv.visitInsn(returnOpcode); } private void visitPropertyAccessorValueRead(Class<?> type, MethodVisitor mv) { String methodName = null; String methodSignature = null; if (type == boolean.class) { methodName = "readBoolean"; methodSignature = PROPERTY_ACCESSOR_READ_BOOLEAN_SIGNATURE; } else if (type == byte.class) { methodName = "readByte"; methodSignature = PROPERTY_ACCESSOR_READ_BYTE_SIGNATURE; } else if (type == char.class) { methodName = "readChar"; methodSignature = PROPERTY_ACCESSOR_READ_CHAR_SIGNATURE; } else if (type == short.class) { methodName = "readShort"; methodSignature = PROPERTY_ACCESSOR_READ_SHORT_SIGNATURE; } else if (type == int.class) { methodName = "readInt"; methodSignature = PROPERTY_ACCESSOR_READ_INT_SIGNATURE; } else if (type == long.class) { methodName = "readLong"; methodSignature = PROPERTY_ACCESSOR_READ_LONG_SIGNATURE; } else if (type == float.class) { methodName = "readFloat"; methodSignature = PROPERTY_ACCESSOR_READ_FLOAT_SIGNATURE; } else if (type == double.class) { methodName = "readDouble"; methodSignature = PROPERTY_ACCESSOR_READ_DOUBLE_SIGNATURE; } else { methodName = "readObject"; methodSignature = PROPERTY_ACCESSOR_READ_OBJECT_SIGNATURE; } mv.visitMethodInsn(INVOKEINTERFACE, VALUEPROPERTYACCESSOR_CLASS_INTERNAL_TYPE, methodName, methodSignature); } private void visitPropertyAccessorValueWrite(Class<?> type, MethodVisitor mv) { String methodName = null; String methodSignature = null; if (type == boolean.class) { methodName = "writeBoolean"; methodSignature = PROPERTY_ACCESSOR_WRITE_BOOLEAN_SIGNATURE; } else if (type == byte.class) { methodName = "writeByte"; methodSignature = PROPERTY_ACCESSOR_WRITE_BYTE_SIGNATURE; } else if (type == char.class) { methodName = "writeChar"; methodSignature = PROPERTY_ACCESSOR_WRITE_CHAR_SIGNATURE; } else if (type == short.class) { methodName = "writeShort"; methodSignature = PROPERTY_ACCESSOR_WRITE_SHORT_SIGNATURE; } else if (type == int.class) { methodName = "writeInt"; methodSignature = PROPERTY_ACCESSOR_WRITE_INT_SIGNATURE; } else if (type == long.class) { methodName = "writeLong"; methodSignature = PROPERTY_ACCESSOR_WRITE_LONG_SIGNATURE; } else if (type == float.class) { methodName = "writeFloat"; methodSignature = PROPERTY_ACCESSOR_WRITE_FLOAT_SIGNATURE; } else if (type == double.class) { methodName = "writeDouble"; methodSignature = PROPERTY_ACCESSOR_WRITE_DOUBLE_SIGNATURE; } else { methodName = "writeObject"; methodSignature = PROPERTY_ACCESSOR_WRITE_OBJECT_SIGNATURE; } mv.visitMethodInsn(INVOKEINTERFACE, VALUEPROPERTYACCESSOR_CLASS_INTERNAL_TYPE, methodName, methodSignature); } private void visitPrimitiveAutoboxing(Class<?> type, MethodVisitor mv) { if (type == boolean.class) { mv.visitTypeInsn(CHECKCAST, "java/lang/Boolean"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z"); } else if (type == byte.class) { mv.visitTypeInsn(CHECKCAST, "java/lang/Byte"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B"); } else if (type == char.class) { mv.visitTypeInsn(CHECKCAST, "java/lang/Character"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C"); } else if (type == short.class) { mv.visitTypeInsn(CHECKCAST, "java/lang/Short"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S"); } else if (type == int.class) { mv.visitTypeInsn(CHECKCAST, "java/lang/Integer"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I"); } else if (type == long.class) { mv.visitTypeInsn(CHECKCAST, "java/lang/Long"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J"); } else if (type == float.class) { mv.visitTypeInsn(CHECKCAST, "java/lang/Float"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F"); } else if (type == double.class) { mv.visitTypeInsn(CHECKCAST, "java/lang/Double"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D"); } } private void visitWrapperAutoboxing(Class<?> type, MethodVisitor mv) { if (type == boolean.class) { mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", BOOLEAN_VALUE_OF_SIGNATURE); } else if (type == byte.class) { mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "valueOf", BYTE_VALUE_OF_SIGNATURE); } else if (type == char.class) { mv.visitMethodInsn(INVOKESTATIC, "java/lang/Character", "valueOf", CHAR_VALUE_OF_SIGNATURE); } else if (type == short.class) { mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "valueOf", SHORT_VALUE_OF_SIGNATURE); } else if (type == int.class) { mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", INT_VALUE_OF_SIGNATURE); } else if (type == long.class) { mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", LONG_VALUE_OF_SIGNATURE); } else if (type == float.class) { mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf", FLOAT_VALUE_OF_SIGNATURE); } else if (type == double.class) { mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf", DOUBLE_VALUE_OF_SIGNATURE); } } private String toFinalFieldName(String prefix, PropertyDescriptor propertyDescriptor) { return new StringBuilder(prefix.toUpperCase()).append("_") .append(propertyDescriptor.getPropertyName().toUpperCase()).append("_LIGHTNING").toString(); } protected void visitSystemOutPrintln(MethodVisitor mv, int stackPosition) { mv.visitVarInsn(ASTORE, stackPosition); mv.visitFieldInsn(GETSTATIC, Type.getType(System.class).getInternalName(), "out", Type.getType(PrintStream.class).getDescriptor()); mv.visitVarInsn(ALOAD, stackPosition); mv.visitMethodInsn(INVOKEVIRTUAL, Type.getType(Object.class).getInternalName(), "toString", "()Ljava/lang/String;"); mv.visitMethodInsn(INVOKEVIRTUAL, Type.getType(PrintStream.class).getInternalName(), "println", "(Ljava/lang/String;)V"); mv.visitVarInsn(ALOAD, stackPosition); } }