| // Copyright (c) 2018, the R8 project authors. Please see the AUTHORS file | |
| // for details. All rights reserved. Use of this source code is governed by a | |
| // BSD-style license that can be found in the LICENSE file. | |
| package com.android.tools.r8.debuginfo; | |
| import org.objectweb.asm.AnnotationVisitor; | |
| 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; | |
| public class KotlinReflectionDump implements Opcodes { | |
| private static final String reflectionFactory = | |
| "java/lang/Object"; // "kotlin/jvm/internal/ReflectionFactory"; | |
| private static final String kClass = "java/lang/Object"; // "kotlin/reflect/KClass"; | |
| private static final String INTERNAL_NAME = "kotlin/jvm/internal/Reflection"; | |
| public static final String CLASS_NAME = INTERNAL_NAME.replace('/', '.'); | |
| public static byte[] dump() throws Exception { | |
| ClassWriter cw = new ClassWriter(0); | |
| FieldVisitor fv; | |
| MethodVisitor mv; | |
| AnnotationVisitor av0; | |
| cw.visit(V1_6, ACC_PUBLIC + ACC_SUPER, INTERNAL_NAME, null, "java/lang/Object", null); | |
| cw.visitSource("Reflection.java", null); | |
| { | |
| fv = | |
| cw.visitField( | |
| ACC_PRIVATE + ACC_FINAL + ACC_STATIC, | |
| "factory", | |
| "L" + reflectionFactory + ";", | |
| null, | |
| null); | |
| fv.visitEnd(); | |
| } | |
| { | |
| fv = | |
| cw.visitField( | |
| ACC_FINAL + ACC_STATIC, | |
| "REFLECTION_NOT_AVAILABLE", | |
| "Ljava/lang/String;", | |
| null, | |
| " (Kotlin reflection is not available)"); | |
| fv.visitEnd(); | |
| } | |
| { | |
| fv = | |
| cw.visitField( | |
| ACC_PRIVATE + ACC_FINAL + ACC_STATIC, | |
| "EMPTY_K_CLASS_ARRAY", | |
| "[L" + kClass + ";", | |
| null, | |
| null); | |
| fv.visitEnd(); | |
| } | |
| method0(cw); | |
| mainMethod(cw); | |
| cw.visitEnd(); | |
| return cw.toByteArray(); | |
| } | |
| private static void mainMethod(ClassWriter cw) { | |
| MethodVisitor mv = | |
| cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "main", "([Ljava/lang/String;)V", null, null); | |
| mv.visitCode(); | |
| mv.visitInsn(RETURN); | |
| mv.visitMaxs(0, 1); | |
| mv.visitEnd(); | |
| } | |
| private static void method0(ClassWriter cw) { | |
| MethodVisitor mv = cw.visitMethod(ACC_STATIC, "<clinit>", "()V", null, null); | |
| Label[] labels = new Label[18]; | |
| for (int i = 0; i < labels.length; i++) { | |
| labels[i] = new Label(); | |
| } | |
| mv.visitCode(); | |
| mv.visitTryCatchBlock(labels[0], labels[1], labels[2], "java/lang/ClassCastException"); | |
| mv.visitTryCatchBlock(labels[0], labels[1], labels[3], "java/lang/ClassNotFoundException"); | |
| mv.visitTryCatchBlock(labels[0], labels[1], labels[4], "java/lang/InstantiationException"); | |
| mv.visitTryCatchBlock(labels[0], labels[1], labels[5], "java/lang/IllegalAccessException"); | |
| mv.visitLabel(labels[0]); | |
| mv.visitLineNumber(33, labels[0]); | |
| mv.visitLdcInsn("kotlin.reflect.jvm.internal.ReflectionFactoryImpl"); | |
| mv.visitMethodInsn( | |
| INVOKESTATIC, "java/lang/Class", "forName", "(Ljava/lang/String;)Ljava/lang/Class;", false); | |
| mv.visitVarInsn(ASTORE, 1); | |
| mv.visitLabel(labels[6]); | |
| mv.visitLineNumber(34, labels[6]); | |
| mv.visitVarInsn(ALOAD, 1); | |
| mv.visitMethodInsn( | |
| INVOKEVIRTUAL, "java/lang/Class", "newInstance", "()Ljava/lang/Object;", false); | |
| mv.visitTypeInsn(CHECKCAST, reflectionFactory); | |
| mv.visitVarInsn(ASTORE, 0); | |
| mv.visitLabel(labels[1]); | |
| mv.visitLineNumber(39, labels[1]); | |
| mv.visitJumpInsn(GOTO, labels[7]); | |
| mv.visitLabel(labels[2]); | |
| mv.visitLineNumber(36, labels[2]); | |
| mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] {"java/lang/ClassCastException"}); | |
| mv.visitVarInsn(ASTORE, 1); | |
| mv.visitLabel(labels[8]); | |
| mv.visitInsn(ACONST_NULL); | |
| mv.visitVarInsn(ASTORE, 0); | |
| mv.visitLabel(labels[9]); | |
| mv.visitLineNumber(39, labels[9]); | |
| mv.visitJumpInsn(GOTO, labels[7]); | |
| mv.visitLabel(labels[3]); | |
| mv.visitLineNumber(37, labels[3]); | |
| mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] {"java/lang/ClassNotFoundException"}); | |
| mv.visitVarInsn(ASTORE, 1); | |
| mv.visitLabel(labels[10]); | |
| mv.visitInsn(ACONST_NULL); | |
| mv.visitVarInsn(ASTORE, 0); | |
| mv.visitLabel(labels[11]); | |
| mv.visitLineNumber(39, labels[11]); | |
| mv.visitJumpInsn(GOTO, labels[7]); | |
| mv.visitLabel(labels[4]); | |
| mv.visitLineNumber(38, labels[4]); | |
| mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] {"java/lang/InstantiationException"}); | |
| mv.visitVarInsn(ASTORE, 1); | |
| mv.visitLabel(labels[12]); | |
| mv.visitInsn(ACONST_NULL); | |
| mv.visitVarInsn(ASTORE, 0); | |
| mv.visitLabel(labels[13]); | |
| mv.visitLineNumber(39, labels[13]); | |
| mv.visitJumpInsn(GOTO, labels[7]); | |
| mv.visitLabel(labels[5]); | |
| mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] {"java/lang/IllegalAccessException"}); | |
| mv.visitVarInsn(ASTORE, 1); | |
| mv.visitLabel(labels[14]); | |
| mv.visitInsn(ACONST_NULL); | |
| mv.visitVarInsn(ASTORE, 0); | |
| mv.visitLabel(labels[7]); | |
| mv.visitLineNumber(41, labels[7]); | |
| mv.visitFrame(Opcodes.F_APPEND, 1, new Object[] {reflectionFactory}, 0, null); | |
| mv.visitVarInsn(ALOAD, 0); | |
| mv.visitJumpInsn(IFNULL, labels[15]); | |
| mv.visitVarInsn(ALOAD, 0); | |
| mv.visitJumpInsn(GOTO, labels[16]); | |
| mv.visitLabel(labels[15]); | |
| mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null); | |
| mv.visitTypeInsn(NEW, reflectionFactory); | |
| mv.visitInsn(DUP); | |
| mv.visitMethodInsn(INVOKESPECIAL, reflectionFactory, "<init>", "()V", false); | |
| mv.visitLabel(labels[16]); | |
| mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] {reflectionFactory}); | |
| mv.visitFieldInsn(PUTSTATIC, INTERNAL_NAME, "factory", "L" + reflectionFactory + ";"); | |
| mv.visitLabel(labels[17]); | |
| mv.visitLineNumber(46, labels[17]); | |
| mv.visitInsn(ICONST_0); | |
| mv.visitTypeInsn(ANEWARRAY, kClass); | |
| mv.visitFieldInsn(PUTSTATIC, INTERNAL_NAME, "EMPTY_K_CLASS_ARRAY", "[L" + kClass + ";"); | |
| mv.visitInsn(RETURN); | |
| mv.visitLocalVariable( | |
| "implClass", "Ljava/lang/Class;", "Ljava/lang/Class<*>;", labels[6], labels[1], 1); | |
| mv.visitLocalVariable("e", "Ljava/lang/ClassCastException;", null, labels[8], labels[9], 1); | |
| mv.visitLocalVariable( | |
| "e", "Ljava/lang/ClassNotFoundException;", null, labels[10], labels[11], 1); | |
| mv.visitLocalVariable( | |
| "e", "Ljava/lang/InstantiationException;", null, labels[12], labels[13], 1); | |
| mv.visitLocalVariable( | |
| "e", "Ljava/lang/IllegalAccessException;", null, labels[14], labels[7], 1); | |
| mv.visitLocalVariable("impl", "L" + reflectionFactory + ";", null, labels[1], labels[17], 0); | |
| mv.visitMaxs(2, 2); | |
| mv.visitEnd(); | |
| } | |
| } |