protected void injectGetByIndex( ClassWriter classWriter, String targetClassName, List<Field> fields) { MethodVisitor methodVisitor = classWriter.visitMethod( ACC_PUBLIC, "get", "(Ljava/lang/Object;I)Ljava/lang/Object;", null, new String[] {getInternalName(ILLEGAL_ACCESS_EXCEPTION.getCanonicalName())}); Boxer boxer = new Boxer(methodVisitor); methodVisitor.visitCode(); methodVisitor.visitVarInsn(ILOAD, 2); int maxStack = 6; Label[] labels = new Label[fields.size()]; Label errorLabel = new Label(); for (int i = 0; i < fields.size(); i++) { labels[i] = new Label(); } methodVisitor.visitTableSwitchInsn(0, labels.length - 1, errorLabel, labels); if (!fields.isEmpty()) { maxStack--; for (int i = 0; i < fields.size(); i++) { Field field = fields.get(i); Class<?> type = field.getType(); String fieldDescriptor = Type.getDescriptor(type); methodVisitor.visitLabel(labels[i]); if (i == 0) methodVisitor.visitFrame(F_APPEND, 1, new Object[] {targetClassName}, 0, null); else methodVisitor.visitFrame(F_SAME, 0, null, 0, null); if (isPublic(field)) { methodVisitor.visitVarInsn(ALOAD, 1); methodVisitor.visitTypeInsn(CHECKCAST, targetClassName); methodVisitor.visitFieldInsn(GETFIELD, targetClassName, field.getName(), fieldDescriptor); boxer.box(Type.getType(type)); } else { injectReflectiveGetter(methodVisitor); } methodVisitor.visitInsn(ARETURN); } methodVisitor.visitLabel(errorLabel); methodVisitor.visitFrame(F_SAME, 0, null, 0, null); } injectException(methodVisitor, IllegalAccessException.class); methodVisitor.visitMaxs(maxStack, 3); methodVisitor.visitEnd(); }
protected void injectException( MethodVisitor methodVisitor, Class<? extends Throwable> throwable) { methodVisitor.visitTypeInsn(NEW, getInternalName(throwable.getCanonicalName())); methodVisitor.visitInsn(DUP); methodVisitor.visitTypeInsn(NEW, "java/lang/StringBuilder"); methodVisitor.visitInsn(DUP); methodVisitor.visitLdcInsn("Invalid index: "); methodVisitor.visitMethodInsn( INVOKESPECIAL, "java/lang/StringBuilder", "<init>", "(Ljava/lang/String;)V"); methodVisitor.visitVarInsn(ILOAD, 2); methodVisitor.visitMethodInsn( INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(I)Ljava/lang/StringBuilder;"); methodVisitor.visitMethodInsn( INVOKEVIRTUAL, "java/lang/StringBuilder", "toString", "()Ljava/lang/String;"); methodVisitor.visitMethodInsn( INVOKESPECIAL, getInternalName(throwable.getCanonicalName()), "<init>", "(Ljava/lang/String;)V"); methodVisitor.visitInsn(ATHROW); }
protected static String toSafeName(Class<?> clazz) { return clazz.getCanonicalName().replace("[]", "Array").replace(".", "_"); }