Search in sources :

Example 1 with Type

use of org.redkale.asm.Type in project redkale by redkale.

the class Rest method createRestWebSocketServlet.

public static <T extends HttpServlet> T createRestWebSocketServlet(final ClassLoader classLoader, final Class<? extends WebSocket> webSocketType) {
    if (webSocketType == null)
        throw new RuntimeException("Rest WebSocket Class is null on createRestWebSocketServlet");
    if (Modifier.isAbstract(webSocketType.getModifiers()))
        throw new RuntimeException("Rest WebSocket Class(" + webSocketType + ") cannot abstract on createRestWebSocketServlet");
    if (Modifier.isFinal(webSocketType.getModifiers()))
        throw new RuntimeException("Rest WebSocket Class(" + webSocketType + ") cannot final on createRestWebSocketServlet");
    final RestWebSocket rws = webSocketType.getAnnotation(RestWebSocket.class);
    if (rws == null || rws.ignore())
        throw new RuntimeException("Rest WebSocket Class(" + webSocketType + ") have not @RestWebSocket or @RestWebSocket.ignore=true on createRestWebSocketServlet");
    boolean valid = false;
    for (Constructor c : webSocketType.getDeclaredConstructors()) {
        if (c.getParameterCount() == 0 && (Modifier.isPublic(c.getModifiers()) || Modifier.isProtected(c.getModifiers()))) {
            valid = true;
            break;
        }
    }
    if (!valid)
        throw new RuntimeException("Rest WebSocket Class(" + webSocketType + ") must have public or protected Constructor on createRestWebSocketServlet");
    final String rwsname = ResourceFactory.formatResourceName(rws.name());
    if (!checkName(rws.catalog()))
        throw new RuntimeException(webSocketType.getName() + " have illegal " + RestWebSocket.class.getSimpleName() + ".catalog, only 0-9 a-z A-Z _ cannot begin 0-9");
    if (!checkName(rwsname))
        throw new RuntimeException(webSocketType.getName() + " have illegal " + RestWebSocket.class.getSimpleName() + ".name, only 0-9 a-z A-Z _ cannot begin 0-9");
    // ----------------------------------------------------------------------------------------
    final Set<Field> resourcesFieldSet = new LinkedHashSet<>();
    final ClassLoader loader = classLoader == null ? Thread.currentThread().getContextClassLoader() : classLoader;
    final Set<String> resourcesFieldNameSet = new HashSet<>();
    Class clzz = webSocketType;
    do {
        for (Field field : clzz.getDeclaredFields()) {
            if (field.getAnnotation(Resource.class) == null)
                continue;
            if (resourcesFieldNameSet.contains(field.getName()))
                continue;
            if (Modifier.isStatic(field.getModifiers()))
                throw new RuntimeException(field + " cannot static on createRestWebSocketServlet");
            if (Modifier.isFinal(field.getModifiers()))
                throw new RuntimeException(field + " cannot final on createRestWebSocketServlet");
            if (!Modifier.isPublic(field.getModifiers()) && !Modifier.isProtected(field.getModifiers())) {
                throw new RuntimeException(field + " must be public or protected on createRestWebSocketServlet");
            }
            resourcesFieldNameSet.add(field.getName());
            resourcesFieldSet.add(field);
        }
    } while ((clzz = clzz.getSuperclass()) != Object.class);
    final List<Field> resourcesFields = new ArrayList<>(resourcesFieldSet);
    StringBuilder sb1 = new StringBuilder();
    StringBuilder sb2 = new StringBuilder();
    for (int i = 0; i < resourcesFields.size(); i++) {
        Field field = resourcesFields.get(i);
        sb1.append(Type.getDescriptor(field.getType()));
        sb2.append(Utility.getTypeDescriptor(field.getGenericType()));
    }
    final String resourceDescriptor = sb1.toString();
    final String resourceGenericDescriptor = sb1.length() == sb2.length() ? null : sb2.toString();
    // ----------------------------------------------------------------------------------------
    final Map<String, List<String>> asmParamMap = MethodParamClassVisitor.getMethodParamNames(new HashMap<>(), webSocketType);
    final Set<String> messageNames = new HashSet<>();
    final List<Method> messageMethods = new ArrayList<>();
    for (Method method : webSocketType.getMethods()) {
        RestOnMessage rom = method.getAnnotation(RestOnMessage.class);
        if (rom == null)
            continue;
        String name = rom.name();
        if (Modifier.isFinal(method.getModifiers()))
            throw new RuntimeException("@RestOnMessage method can not final but (" + method + ")");
        if (Modifier.isStatic(method.getModifiers()))
            throw new RuntimeException("@RestOnMessage method can not static but (" + method + ")");
        if (method.getReturnType() != void.class)
            throw new RuntimeException("@RestOnMessage method must return void but (" + method + ")");
        if (method.getExceptionTypes().length > 0)
            throw new RuntimeException("@RestOnMessage method can not throw exception but (" + method + ")");
        if (name.isEmpty())
            throw new RuntimeException(method + " RestOnMessage.name is empty createRestWebSocketServlet");
        if (messageNames.contains(name))
            throw new RuntimeException(method + " repeat RestOnMessage.name(" + name + ") createRestWebSocketServlet");
        messageNames.add(name);
        messageMethods.add(method);
    }
    // ----------------------------------------------------------------------------------------
    final String resDesc = Type.getDescriptor(Resource.class);
    final String wsDesc = Type.getDescriptor(WebSocket.class);
    final String wsParamDesc = Type.getDescriptor(WebSocketParam.class);
    final String jsonConvertDesc = Type.getDescriptor(JsonConvert.class);
    final String convertDisabledDesc = Type.getDescriptor(ConvertDisabled.class);
    final String webSocketParamName = Type.getInternalName(WebSocketParam.class);
    final String supDynName = WebSocketServlet.class.getName().replace('.', '/');
    final String webServletDesc = Type.getDescriptor(WebServlet.class);
    final String webSocketInternalName = Type.getInternalName(webSocketType);
    final String newDynName = webSocketInternalName.substring(0, webSocketInternalName.lastIndexOf('/') + 1) + "_Dyn" + webSocketType.getSimpleName() + "Servlet";
    final String newDynWebSokcetSimpleName = "_Dyn" + webSocketType.getSimpleName();
    final String newDynWebSokcetFullName = newDynName + "$" + newDynWebSokcetSimpleName;
    final String newDynMessageSimpleName = "_Dyn" + webSocketType.getSimpleName() + "Message";
    final String newDynMessageFullName = newDynName + "$" + newDynMessageSimpleName;
    final String newDynConsumerSimpleName = "_DynRestOnMessageConsumer";
    final String newDynConsumerFullName = newDynName + "$" + newDynConsumerSimpleName;
    // ----------------------------------------------------------------------------------------
    ClassWriter cw = new ClassWriter(COMPUTE_FRAMES);
    FieldVisitor fv;
    MethodDebugVisitor mv;
    AnnotationVisitor av0;
    cw.visit(V1_8, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, newDynName, null, supDynName, null);
    {
        // RestDynSourceType
        av0 = cw.visitAnnotation(Type.getDescriptor(RestDynSourceType.class), true);
        av0.visit("value", Type.getType(Type.getDescriptor(webSocketType)));
        av0.visitEnd();
    }
    {
        // 注入 @WebServlet 注解
        String urlpath = (rws.catalog().isEmpty() ? "/" : ("/" + rws.catalog() + "/")) + rwsname;
        av0 = cw.visitAnnotation(webServletDesc, true);
        {
            AnnotationVisitor av1 = av0.visitArray("value");
            av1.visit(null, urlpath);
            av1.visitEnd();
        }
        av0.visit("moduleid", 0);
        av0.visit("repair", rws.repair());
        av0.visit("comment", rws.comment());
        av0.visitEnd();
    }
    {
        // 内部类
        cw.visitInnerClass(newDynConsumerFullName, newDynName, newDynConsumerSimpleName, ACC_PUBLIC + ACC_STATIC);
        cw.visitInnerClass(newDynWebSokcetFullName, newDynName, newDynWebSokcetSimpleName, ACC_PUBLIC + ACC_STATIC);
        cw.visitInnerClass(newDynMessageFullName, newDynName, newDynMessageSimpleName, ACC_PUBLIC + ACC_STATIC);
        for (int i = 0; i < messageMethods.size(); i++) {
            Method method = messageMethods.get(i);
            String endfix = "_" + method.getName() + "_" + (i > 9 ? i : ("0" + i));
            cw.visitInnerClass(newDynMessageFullName + endfix, newDynName, newDynMessageSimpleName + endfix, ACC_PUBLIC + ACC_STATIC);
        }
    }
    {
        // @Resource
        for (int i = 0; i < resourcesFields.size(); i++) {
            Field field = resourcesFields.get(i);
            Resource res = field.getAnnotation(Resource.class);
            java.lang.reflect.Type fieldType = field.getGenericType();
            fv = cw.visitField(ACC_PRIVATE, "_redkale_resource_" + i, Type.getDescriptor(field.getType()), fieldType == field.getType() ? null : Utility.getTypeDescriptor(fieldType), null);
            {
                av0 = fv.visitAnnotation(resDesc, true);
                av0.visit("name", res.name());
                av0.visitEnd();
            }
            fv.visitEnd();
        }
    }
    {
        // _DynWebSocketServlet构造函数
        mv = new MethodDebugVisitor(cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null));
        mv.visitVarInsn(ALOAD, 0);
        mv.visitMethodInsn(INVOKESPECIAL, supDynName, "<init>", "()V", false);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitLdcInsn(Type.getObjectType(newDynName + "$" + newDynWebSokcetSimpleName + "Message"));
        mv.visitFieldInsn(PUTFIELD, newDynName, "messageTextType", "Ljava/lang/reflect/Type;");
        mv.visitVarInsn(ALOAD, 0);
        pushInt(mv, rws.liveinterval());
        mv.visitFieldInsn(PUTFIELD, newDynName, "liveinterval", "I");
        mv.visitVarInsn(ALOAD, 0);
        pushInt(mv, rws.wsmaxconns());
        mv.visitFieldInsn(PUTFIELD, newDynName, "wsmaxconns", "I");
        mv.visitVarInsn(ALOAD, 0);
        pushInt(mv, rws.wsmaxbody());
        mv.visitFieldInsn(PUTFIELD, newDynName, "wsmaxbody", "I");
        mv.visitVarInsn(ALOAD, 0);
        mv.visitInsn(rws.single() ? ICONST_1 : ICONST_0);
        mv.visitFieldInsn(PUTFIELD, newDynName, "single", "Z");
        mv.visitVarInsn(ALOAD, 0);
        mv.visitInsn(rws.anyuser() ? ICONST_1 : ICONST_0);
        mv.visitFieldInsn(PUTFIELD, newDynName, "anyuser", "Z");
        mv.visitInsn(RETURN);
        mv.visitMaxs(3, 1);
        mv.visitEnd();
    }
    {
        // createWebSocket 方法
        mv = new MethodDebugVisitor(cw.visitMethod(ACC_PROTECTED, "createWebSocket", "()" + wsDesc, "<G::Ljava/io/Serializable;T:Ljava/lang/Object;>()L" + WebSocket.class.getName().replace('.', '/') + "<TG;TT;>;", null));
        mv.visitTypeInsn(NEW, newDynName + "$" + newDynWebSokcetSimpleName);
        mv.visitInsn(DUP);
        for (int i = 0; i < resourcesFields.size(); i++) {
            mv.visitVarInsn(ALOAD, 0);
            mv.visitFieldInsn(GETFIELD, newDynName, "_redkale_resource_" + i, Type.getDescriptor(resourcesFields.get(i).getType()));
        }
        mv.visitMethodInsn(INVOKESPECIAL, newDynWebSokcetFullName, "<init>", "(" + resourceDescriptor + ")V", false);
        mv.visitInsn(ARETURN);
        mv.visitMaxs(2 + resourcesFields.size(), 1);
        mv.visitEnd();
    }
    {
        // createRestOnMessageConsumer
        mv = new MethodDebugVisitor(cw.visitMethod(ACC_PROTECTED, "createRestOnMessageConsumer", "()Ljava/util/function/BiConsumer;", "()Ljava/util/function/BiConsumer<" + wsDesc + "Ljava/lang/Object;>;", null));
        mv.visitTypeInsn(NEW, newDynConsumerFullName);
        mv.visitInsn(DUP);
        mv.visitMethodInsn(INVOKESPECIAL, newDynConsumerFullName, "<init>", "()V", false);
        mv.visitInsn(ARETURN);
        mv.visitMaxs(2, 1);
        mv.visitEnd();
    }
    {
        // resourceName
        mv = new MethodDebugVisitor(cw.visitMethod(ACC_PUBLIC, "resourceName", "()Ljava/lang/String;", null, null));
        mv.visitLdcInsn(rwsname);
        mv.visitInsn(ARETURN);
        mv.visitMaxs(1, 1);
        mv.visitEnd();
    }
    RestClassLoader newLoader = new RestClassLoader(loader);
    for (int i = 0; i < messageMethods.size(); i++) {
        // _DyncXXXWebSocketMessage 子消息List
        Method method = messageMethods.get(i);
        String endfix = "_" + method.getName() + "_" + (i > 9 ? i : ("0" + i));
        ClassWriter cw2 = new ClassWriter(COMPUTE_FRAMES);
        cw2.visit(V1_8, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, newDynMessageFullName + endfix, null, "java/lang/Object", new String[] { webSocketParamName, "java/lang/Runnable" });
        cw2.visitInnerClass(newDynMessageFullName + endfix, newDynName, newDynMessageSimpleName + endfix, ACC_PUBLIC + ACC_STATIC);
        Set<String> paramnames = new HashSet<>();
        String methodesc = method.getName() + ":" + Type.getMethodDescriptor(method);
        List<String> names = asmParamMap.get(methodesc);
        Parameter[] params = method.getParameters();
        // 必须使用LinkedHashMap确保顺序
        final LinkedHashMap<String, Parameter> paramap = new LinkedHashMap();
        for (int j = 0; j < params.length; j++) {
            // 字段列表
            Parameter param = params[j];
            String paramname = param.getName();
            RestParam rp = param.getAnnotation(RestParam.class);
            if (rp != null && !rp.name().isEmpty()) {
                paramname = rp.name();
            } else if (names != null && names.size() > j) {
                paramname = names.get(j);
            }
            if (paramnames.contains(paramname))
                throw new RuntimeException(method + " has same @RestParam.name");
            paramnames.add(paramname);
            paramap.put(paramname, param);
            fv = cw2.visitField(ACC_PUBLIC, paramname, Type.getDescriptor(param.getType()), param.getType() == param.getParameterizedType() ? null : Utility.getTypeDescriptor(param.getParameterizedType()), null);
            fv.visitEnd();
        }
        {
            // _redkale_websocket
            fv = cw2.visitField(ACC_PUBLIC, "_redkale_websocket", "L" + newDynWebSokcetFullName + ";", null, null);
            av0 = fv.visitAnnotation(convertDisabledDesc, true);
            av0.visitEnd();
            fv.visitEnd();
        }
        {
            // 空构造函数
            mv = new MethodDebugVisitor(cw2.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null));
            mv.visitVarInsn(ALOAD, 0);
            mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
            mv.visitInsn(RETURN);
            mv.visitMaxs(1, 1);
            mv.visitEnd();
        }
        {
            // getNames
            mv = new MethodDebugVisitor(cw2.visitMethod(ACC_PUBLIC, "getNames", "()[Ljava/lang/String;", null, null));
            pushInt(mv, paramap.size());
            mv.visitTypeInsn(ANEWARRAY, "java/lang/String");
            int index = -1;
            for (Map.Entry<String, Parameter> en : paramap.entrySet()) {
                mv.visitInsn(DUP);
                pushInt(mv, ++index);
                mv.visitLdcInsn(en.getKey());
                mv.visitInsn(AASTORE);
            }
            mv.visitInsn(ARETURN);
            mv.visitMaxs(paramap.size() + 2, 1);
            mv.visitEnd();
        }
        {
            // getValue
            mv = new MethodDebugVisitor(cw2.visitMethod(ACC_PUBLIC, "getValue", "(Ljava/lang/String;)Ljava/lang/Object;", "<T:Ljava/lang/Object;>(Ljava/lang/String;)TT;", null));
            for (Map.Entry<String, Parameter> en : paramap.entrySet()) {
                Class paramType = en.getValue().getType();
                mv.visitLdcInsn(en.getKey());
                mv.visitVarInsn(ALOAD, 1);
                mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z", false);
                Label l1 = new Label();
                mv.visitJumpInsn(IFEQ, l1);
                mv.visitVarInsn(ALOAD, 0);
                mv.visitFieldInsn(GETFIELD, newDynMessageFullName + endfix, en.getKey(), Type.getDescriptor(paramType));
                if (paramType.isPrimitive()) {
                    Class bigclaz = java.lang.reflect.Array.get(java.lang.reflect.Array.newInstance(paramType, 1), 0).getClass();
                    mv.visitMethodInsn(INVOKESTATIC, bigclaz.getName().replace('.', '/'), "valueOf", "(" + Type.getDescriptor(paramType) + ")" + Type.getDescriptor(bigclaz), false);
                }
                mv.visitInsn(ARETURN);
                mv.visitLabel(l1);
            }
            mv.visitInsn(ACONST_NULL);
            mv.visitInsn(ARETURN);
            mv.visitMaxs(2, 2);
            mv.visitEnd();
        }
        {
            // execute
            mv = new MethodDebugVisitor(cw2.visitMethod(ACC_PUBLIC, "execute", "(L" + newDynWebSokcetFullName + ";)V", null, null));
            mv.visitVarInsn(ALOAD, 0);
            mv.visitVarInsn(ALOAD, 1);
            mv.visitFieldInsn(PUTFIELD, newDynMessageFullName + endfix, "_redkale_websocket", "L" + newDynWebSokcetFullName + ";");
            mv.visitVarInsn(ALOAD, 1);
            mv.visitLdcInsn(method.getAnnotation(RestOnMessage.class).name());
            mv.visitVarInsn(ALOAD, 0);
            mv.visitVarInsn(ALOAD, 0);
            mv.visitMethodInsn(INVOKEVIRTUAL, newDynWebSokcetFullName, "preOnMessage", "(Ljava/lang/String;" + wsParamDesc + "Ljava/lang/Runnable;)V", false);
            mv.visitInsn(RETURN);
            mv.visitMaxs(4, 2);
            mv.visitEnd();
        }
        {
            // run
            mv = new MethodDebugVisitor(cw2.visitMethod(ACC_PUBLIC, "run", "()V", null, null));
            mv.visitVarInsn(ALOAD, 0);
            mv.visitFieldInsn(GETFIELD, newDynMessageFullName + endfix, "_redkale_websocket", "L" + newDynWebSokcetFullName + ";");
            for (Map.Entry<String, Parameter> en : paramap.entrySet()) {
                mv.visitVarInsn(ALOAD, 0);
                mv.visitFieldInsn(GETFIELD, (newDynMessageFullName + endfix), en.getKey(), Type.getDescriptor(en.getValue().getType()));
            }
            mv.visitMethodInsn(INVOKEVIRTUAL, newDynWebSokcetFullName, method.getName(), Type.getMethodDescriptor(method), false);
            mv.visitInsn(RETURN);
            mv.visitMaxs(3, 1);
            mv.visitEnd();
        }
        {
            // toString
            mv = new MethodDebugVisitor(cw2.visitMethod(ACC_PUBLIC, "toString", "()Ljava/lang/String;", null, null));
            mv.visitMethodInsn(INVOKESTATIC, JsonConvert.class.getName().replace('.', '/'), "root", "()" + jsonConvertDesc, false);
            mv.visitVarInsn(ALOAD, 0);
            mv.visitMethodInsn(INVOKEVIRTUAL, JsonConvert.class.getName().replace('.', '/'), "convertTo", "(Ljava/lang/Object;)Ljava/lang/String;", false);
            mv.visitInsn(ARETURN);
            mv.visitMaxs(2, 1);
            mv.visitEnd();
        }
        cw2.visitEnd();
        newLoader.loadClass((newDynMessageFullName + endfix).replace('/', '.'), cw2.toByteArray());
    }
    {
        // _DynXXXWebSocketMessage class
        ClassWriter cw2 = new ClassWriter(COMPUTE_FRAMES);
        cw2.visit(V1_8, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, newDynMessageFullName, null, "java/lang/Object", null);
        cw2.visitInnerClass(newDynMessageFullName, newDynName, newDynMessageSimpleName, ACC_PUBLIC + ACC_STATIC);
        for (int i = 0; i < messageMethods.size(); i++) {
            Method method = messageMethods.get(i);
            String endfix = "_" + method.getName() + "_" + (i > 9 ? i : ("0" + i));
            cw2.visitInnerClass(newDynMessageFullName + endfix, newDynName, newDynMessageSimpleName + endfix, ACC_PUBLIC + ACC_STATIC);
            fv = cw2.visitField(ACC_PUBLIC, method.getAnnotation(RestOnMessage.class).name(), "L" + newDynMessageFullName + endfix + ";", null, null);
            fv.visitEnd();
        }
        {
            // 构造函数
            mv = new MethodDebugVisitor(cw2.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null));
            mv.visitVarInsn(ALOAD, 0);
            mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
            mv.visitInsn(RETURN);
            mv.visitMaxs(1, 1);
            mv.visitEnd();
        }
        {
            // toString
            mv = new MethodDebugVisitor(cw2.visitMethod(ACC_PUBLIC, "toString", "()Ljava/lang/String;", null, null));
            mv.visitMethodInsn(INVOKESTATIC, JsonConvert.class.getName().replace('.', '/'), "root", "()" + jsonConvertDesc, false);
            mv.visitVarInsn(ALOAD, 0);
            mv.visitMethodInsn(INVOKEVIRTUAL, JsonConvert.class.getName().replace('.', '/'), "convertTo", "(Ljava/lang/Object;)Ljava/lang/String;", false);
            mv.visitInsn(ARETURN);
            mv.visitMaxs(2, 1);
            mv.visitEnd();
        }
        cw2.visitEnd();
        newLoader.loadClass(newDynMessageFullName.replace('/', '.'), cw2.toByteArray());
    }
    {
        // _DynXXXWebSocket class
        ClassWriter cw2 = new ClassWriter(COMPUTE_FRAMES);
        cw2.visit(V1_8, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, newDynWebSokcetFullName, null, webSocketInternalName, null);
        cw2.visitInnerClass(newDynWebSokcetFullName, newDynName, newDynWebSokcetSimpleName, ACC_PUBLIC + ACC_STATIC);
        {
            mv = new MethodDebugVisitor(cw2.visitMethod(ACC_PUBLIC, "<init>", "(" + resourceDescriptor + ")V", resourceGenericDescriptor == null ? null : ("(" + resourceGenericDescriptor + ")V"), null));
            mv.visitVarInsn(ALOAD, 0);
            mv.visitMethodInsn(INVOKESPECIAL, webSocketInternalName, "<init>", "()V", false);
            for (int i = 0; i < resourcesFields.size(); i++) {
                Field field = resourcesFields.get(i);
                mv.visitVarInsn(ALOAD, 0);
                mv.visitVarInsn(ALOAD, i + 1);
                mv.visitFieldInsn(PUTFIELD, newDynWebSokcetFullName, field.getName(), Type.getDescriptor(field.getType()));
            }
            mv.visitInsn(RETURN);
            mv.visitMaxs(2, 1 + resourcesFields.size());
            mv.visitEnd();
        }
        cw2.visitEnd();
        newLoader.loadClass(newDynWebSokcetFullName.replace('/', '.'), cw2.toByteArray());
    }
    {
        // _DynRestOnMessageConsumer class
        ClassWriter cw2 = new ClassWriter(COMPUTE_FRAMES);
        cw2.visit(V1_8, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, newDynConsumerFullName, "Ljava/lang/Object;Ljava/util/function/BiConsumer<" + wsDesc + "Ljava/lang/Object;>;", "java/lang/Object", new String[] { "java/util/function/BiConsumer" });
        cw2.visitInnerClass(newDynConsumerFullName, newDynName, newDynConsumerSimpleName, ACC_PUBLIC + ACC_STATIC);
        cw2.visitInnerClass(newDynMessageFullName, newDynName, newDynMessageSimpleName, ACC_PUBLIC + ACC_STATIC);
        for (int i = 0; i < messageMethods.size(); i++) {
            Method method = messageMethods.get(i);
            String endfix = "_" + method.getName() + "_" + (i > 9 ? i : ("0" + i));
            cw2.visitInnerClass(newDynMessageFullName + endfix, newDynName, newDynMessageSimpleName + endfix, ACC_PUBLIC + ACC_STATIC);
        }
        {
            // 构造函数
            mv = new MethodDebugVisitor(cw2.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null));
            mv.visitVarInsn(ALOAD, 0);
            mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
            mv.visitInsn(RETURN);
            mv.visitMaxs(1, 1);
            mv.visitEnd();
        }
        {
            // accept函数
            mv = new MethodDebugVisitor(cw2.visitMethod(ACC_PUBLIC, "accept", "(" + wsDesc + "Ljava/lang/Object;)V", null, null));
            mv.visitVarInsn(ALOAD, 1);
            mv.visitTypeInsn(CHECKCAST, newDynWebSokcetFullName);
            mv.visitVarInsn(ASTORE, 3);
            mv.visitVarInsn(ALOAD, 2);
            mv.visitTypeInsn(CHECKCAST, newDynMessageFullName);
            mv.visitVarInsn(ASTORE, 4);
            for (int i = 0; i < messageMethods.size(); i++) {
                final Method method = messageMethods.get(i);
                String endfix = "_" + method.getName() + "_" + (i > 9 ? i : ("0" + i));
                final String messagename = method.getAnnotation(RestOnMessage.class).name();
                mv.visitVarInsn(ALOAD, 4);
                mv.visitFieldInsn(GETFIELD, newDynMessageFullName, messagename, "L" + (newDynMessageFullName + endfix) + ";");
                Label ifLabel = new Label();
                mv.visitJumpInsn(IFNULL, ifLabel);
                mv.visitVarInsn(ALOAD, 4);
                mv.visitFieldInsn(GETFIELD, newDynMessageFullName, messagename, "L" + (newDynMessageFullName + endfix) + ";");
                mv.visitVarInsn(ALOAD, 3);
                mv.visitMethodInsn(INVOKEVIRTUAL, (newDynMessageFullName + endfix), "execute", "(L" + newDynWebSokcetFullName + ";)V", false);
                mv.visitInsn(RETURN);
                mv.visitLabel(ifLabel);
            }
            mv.visitInsn(RETURN);
            mv.visitMaxs(3, 3 + messageMethods.size());
            mv.visitEnd();
        }
        {
            // 虚拟accept函数
            mv = new MethodDebugVisitor(cw2.visitMethod(ACC_PUBLIC + ACC_BRIDGE + ACC_SYNTHETIC, "accept", "(Ljava/lang/Object;Ljava/lang/Object;)V", null, null));
            mv.visitVarInsn(ALOAD, 0);
            mv.visitVarInsn(ALOAD, 1);
            mv.visitTypeInsn(CHECKCAST, WebSocket.class.getName().replace('.', '/'));
            mv.visitVarInsn(ALOAD, 2);
            mv.visitTypeInsn(CHECKCAST, "java/lang/Object");
            mv.visitMethodInsn(INVOKEVIRTUAL, newDynConsumerFullName, "accept", "(" + wsDesc + "Ljava/lang/Object;)V", false);
            mv.visitInsn(RETURN);
            mv.visitMaxs(3, 3);
            mv.visitEnd();
        }
        cw2.visitEnd();
        newLoader.loadClass(newDynConsumerFullName.replace('/', '.'), cw2.toByteArray());
    }
    cw.visitEnd();
    Class<?> newClazz = newLoader.loadClass(newDynName.replace('/', '.'), cw.toByteArray());
    try {
        return (T) newClazz.getDeclaredConstructor().newInstance();
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}
Also used : MethodDebugVisitor(org.redkale.asm.MethodDebugVisitor) Resource(javax.annotation.Resource) Type(org.redkale.asm.Type) ElementType(java.lang.annotation.ElementType)

Example 2 with Type

use of org.redkale.asm.Type in project redkale by redkale.

the class Rest method createRestWebSocketServlet.

public static <T extends WebSocketServlet> T createRestWebSocketServlet(final ClassLoader classLoader, final Class<? extends WebSocket> webSocketType, MessageAgent messageAgent) {
    if (webSocketType == null)
        throw new RuntimeException("Rest WebSocket Class is null on createRestWebSocketServlet");
    if (Modifier.isAbstract(webSocketType.getModifiers()))
        throw new RuntimeException("Rest WebSocket Class(" + webSocketType + ") cannot abstract on createRestWebSocketServlet");
    if (Modifier.isFinal(webSocketType.getModifiers()))
        throw new RuntimeException("Rest WebSocket Class(" + webSocketType + ") cannot final on createRestWebSocketServlet");
    final RestWebSocket rws = webSocketType.getAnnotation(RestWebSocket.class);
    if (rws == null || rws.ignore())
        throw new RuntimeException("Rest WebSocket Class(" + webSocketType + ") have not @RestWebSocket or @RestWebSocket.ignore=true on createRestWebSocketServlet");
    boolean valid = false;
    for (Constructor c : webSocketType.getDeclaredConstructors()) {
        if (c.getParameterCount() == 0 && (Modifier.isPublic(c.getModifiers()) || Modifier.isProtected(c.getModifiers()))) {
            valid = true;
            break;
        }
    }
    if (!valid)
        throw new RuntimeException("Rest WebSocket Class(" + webSocketType + ") must have public or protected Constructor on createRestWebSocketServlet");
    final String rwsname = ResourceFactory.formatResourceName(rws.name());
    if (!checkName(rws.catalog()))
        throw new RuntimeException(webSocketType.getName() + " have illegal " + RestWebSocket.class.getSimpleName() + ".catalog, only 0-9 a-z A-Z _ cannot begin 0-9");
    if (!checkName(rwsname))
        throw new RuntimeException(webSocketType.getName() + " have illegal " + RestWebSocket.class.getSimpleName() + ".name, only 0-9 a-z A-Z _ cannot begin 0-9");
    // ----------------------------------------------------------------------------------------
    final Set<Field> resourcesFieldSet = new LinkedHashSet<>();
    final ClassLoader loader = classLoader == null ? Thread.currentThread().getContextClassLoader() : classLoader;
    final Set<String> resourcesFieldNameSet = new HashSet<>();
    Class clzz = webSocketType;
    do {
        for (Field field : clzz.getDeclaredFields()) {
            if (field.getAnnotation(Resource.class) == null)
                continue;
            if (resourcesFieldNameSet.contains(field.getName()))
                continue;
            if (Modifier.isStatic(field.getModifiers()))
                throw new RuntimeException(field + " cannot static on createRestWebSocketServlet");
            if (Modifier.isFinal(field.getModifiers()))
                throw new RuntimeException(field + " cannot final on createRestWebSocketServlet");
            if (!Modifier.isPublic(field.getModifiers()) && !Modifier.isProtected(field.getModifiers())) {
                throw new RuntimeException(field + " must be public or protected on createRestWebSocketServlet");
            }
            resourcesFieldNameSet.add(field.getName());
            resourcesFieldSet.add(field);
        }
    } while ((clzz = clzz.getSuperclass()) != Object.class);
    // ----------------------------------------------------------------------------------------
    boolean namePresent = false;
    try {
        Method m0 = null;
        for (Method method : webSocketType.getMethods()) {
            if (method.getParameterCount() > 0) {
                m0 = method;
                break;
            }
        }
        namePresent = m0 == null ? true : m0.getParameters()[0].isNamePresent();
    } catch (Exception e) {
    }
    final Map<String, List<String>> asmParamMap = namePresent ? null : MethodParamClassVisitor.getMethodParamNames(new HashMap<>(), webSocketType);
    final Set<String> messageNames = new HashSet<>();
    Method wildcardMethod = null;
    List<Method> mmethods = new ArrayList<>();
    for (Method method : webSocketType.getMethods()) {
        RestOnMessage rom = method.getAnnotation(RestOnMessage.class);
        if (rom == null)
            continue;
        String name = rom.name();
        if (!"*".equals(name) && !checkName(name))
            throw new RuntimeException("@RestOnMessage.name contains illegal characters on (" + method + ")");
        if (Modifier.isFinal(method.getModifiers()))
            throw new RuntimeException("@RestOnMessage method can not final but (" + method + ")");
        if (Modifier.isStatic(method.getModifiers()))
            throw new RuntimeException("@RestOnMessage method can not static but (" + method + ")");
        if (method.getReturnType() != void.class)
            throw new RuntimeException("@RestOnMessage method must return void but (" + method + ")");
        if (method.getExceptionTypes().length > 0)
            throw new RuntimeException("@RestOnMessage method can not throw exception but (" + method + ")");
        if (name.isEmpty())
            throw new RuntimeException(method + " RestOnMessage.name is empty createRestWebSocketServlet");
        if (messageNames.contains(name))
            throw new RuntimeException(method + " repeat RestOnMessage.name(" + name + ") createRestWebSocketServlet");
        messageNames.add(name);
        if ("*".equals(name)) {
            wildcardMethod = method;
        } else {
            mmethods.add(method);
        }
    }
    final List<Method> messageMethods = new ArrayList<>();
    messageMethods.addAll(mmethods);
    // wildcardMethod 必须放最后, _DynRestOnMessageConsumer 是按messageMethods顺序来判断的
    if (wildcardMethod != null)
        messageMethods.add(wildcardMethod);
    // ----------------------------------------------------------------------------------------
    final String resDesc = Type.getDescriptor(Resource.class);
    final String wsDesc = Type.getDescriptor(WebSocket.class);
    final String wsParamDesc = Type.getDescriptor(WebSocketParam.class);
    final String jsonConvertDesc = Type.getDescriptor(JsonConvert.class);
    final String convertDisabledDesc = Type.getDescriptor(ConvertDisabled.class);
    final String webSocketParamName = Type.getInternalName(WebSocketParam.class);
    final String supDynName = WebSocketServlet.class.getName().replace('.', '/');
    final String webServletDesc = Type.getDescriptor(WebServlet.class);
    final String webSocketInternalName = Type.getInternalName(webSocketType);
    final String newDynName = "org/redkaledyn/http/restws/" + "_DynWebScoketServlet__" + webSocketType.getName().replace('.', '_').replace('$', '_');
    final String newDynWebSokcetSimpleName = "_Dyn" + webSocketType.getSimpleName();
    final String newDynWebSokcetFullName = newDynName + "$" + newDynWebSokcetSimpleName;
    final String newDynMessageSimpleName = "_Dyn" + webSocketType.getSimpleName() + "Message";
    final String newDynMessageFullName = newDynName + "$" + newDynMessageSimpleName;
    final String newDynConsumerSimpleName = "_DynRestOnMessageConsumer";
    final String newDynConsumerFullName = newDynName + "$" + newDynConsumerSimpleName;
    try {
        Class clz = RedkaleClassLoader.findDynClass(newDynName.replace('/', '.'));
        if (clz == null)
            clz = loader.loadClass(newDynName.replace('/', '.'));
        T servlet = (T) clz.getDeclaredConstructor().newInstance();
        Map<String, Annotation[]> msgclassToAnnotations = new HashMap<>();
        for (int i = 0; i < messageMethods.size(); i++) {
            // _DyncXXXWebSocketMessage 子消息List
            Method method = messageMethods.get(i);
            String endfix = "_" + method.getName() + "_" + (i > 9 ? i : ("0" + i));
            String newDynSuperMessageFullName = newDynMessageFullName + (method == wildcardMethod ? "" : endfix);
            msgclassToAnnotations.put(newDynSuperMessageFullName, method.getAnnotations());
        }
        clz.getField("_redkale_annotations").set(null, msgclassToAnnotations);
        if (rws.cryptor() != Cryptor.class) {
            Cryptor cryptor = rws.cryptor().getDeclaredConstructor().newInstance();
            // WebSocketServlet
            Field cryptorField = clz.getSuperclass().getDeclaredField("cryptor");
            cryptorField.setAccessible(true);
            cryptorField.set(servlet, cryptor);
        }
        if (messageAgent != null)
            ((WebSocketServlet) servlet).messageAgent = messageAgent;
        return servlet;
    } catch (Throwable e) {
    }
    final List<Field> resourcesFields = new ArrayList<>(resourcesFieldSet);
    StringBuilder sb1 = new StringBuilder();
    StringBuilder sb2 = new StringBuilder();
    for (int i = 0; i < resourcesFields.size(); i++) {
        Field field = resourcesFields.get(i);
        sb1.append(Type.getDescriptor(field.getType()));
        sb2.append(Utility.getTypeDescriptor(field.getGenericType()));
    }
    final String resourceDescriptor = sb1.toString();
    final String resourceGenericDescriptor = sb1.length() == sb2.length() ? null : sb2.toString();
    // ----------------------------------------------------------------------------------------
    ClassWriter cw = new ClassWriter(COMPUTE_FRAMES);
    FieldVisitor fv;
    MethodDebugVisitor mv;
    AnnotationVisitor av0;
    cw.visit(V11, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, newDynName, null, supDynName, null);
    {
        // RestDyn
        av0 = cw.visitAnnotation(Type.getDescriptor(RestDyn.class), true);
        av0.visit("simple", false);
        {
            AnnotationVisitor av1 = av0.visitArray("types");
            av1.visit(null, Type.getType("L" + newDynConsumerFullName.replace('.', '/') + ";"));
            av1.visit(null, Type.getType("L" + newDynWebSokcetFullName.replace('.', '/') + ";"));
            // 位置固定第三个,下面用Message类进行loadDecoder会用到
            av1.visit(null, Type.getType("L" + newDynMessageFullName.replace('.', '/') + ";"));
            av1.visitEnd();
        }
        av0.visitEnd();
    }
    {
        // RestDynSourceType
        av0 = cw.visitAnnotation(Type.getDescriptor(RestDynSourceType.class), true);
        av0.visit("value", Type.getType(Type.getDescriptor(webSocketType)));
        av0.visitEnd();
    }
    {
        // 注入 @WebServlet 注解
        String urlpath = (rws.catalog().isEmpty() ? "/" : ("/" + rws.catalog() + "/")) + rwsname;
        av0 = cw.visitAnnotation(webServletDesc, true);
        {
            AnnotationVisitor av1 = av0.visitArray("value");
            av1.visit(null, urlpath);
            av1.visitEnd();
        }
        av0.visit("name", rwsname);
        av0.visit("moduleid", 0);
        av0.visit("repair", rws.repair());
        av0.visit("comment", rws.comment());
        av0.visitEnd();
    }
    {
        // 内部类
        cw.visitInnerClass(newDynConsumerFullName, newDynName, newDynConsumerSimpleName, ACC_PUBLIC + ACC_STATIC);
        cw.visitInnerClass(newDynWebSokcetFullName, newDynName, newDynWebSokcetSimpleName, ACC_PUBLIC + ACC_STATIC);
        cw.visitInnerClass(newDynMessageFullName, newDynName, newDynMessageSimpleName, ACC_PUBLIC + ACC_STATIC);
        for (int i = 0; i < messageMethods.size(); i++) {
            Method method = messageMethods.get(i);
            String endfix = "_" + method.getName() + "_" + (i > 9 ? i : ("0" + i));
            String newDynSuperMessageFullName = newDynMessageFullName + (method == wildcardMethod ? "" : endfix);
            cw.visitInnerClass(newDynSuperMessageFullName, newDynName, newDynMessageSimpleName + endfix, ACC_PUBLIC + ACC_STATIC);
        }
    }
    {
        // @Resource
        for (int i = 0; i < resourcesFields.size(); i++) {
            Field field = resourcesFields.get(i);
            Resource res = field.getAnnotation(Resource.class);
            java.lang.reflect.Type fieldType = field.getGenericType();
            fv = cw.visitField(ACC_PRIVATE, "_redkale_resource_" + i, Type.getDescriptor(field.getType()), fieldType == field.getType() ? null : Utility.getTypeDescriptor(fieldType), null);
            {
                av0 = fv.visitAnnotation(resDesc, true);
                av0.visit("name", res.name());
                av0.visitEnd();
            }
            fv.visitEnd();
        }
    }
    {
        // _redkale_annotations
        fv = cw.visitField(ACC_PUBLIC + ACC_STATIC, "_redkale_annotations", "Ljava/util/Map;", "Ljava/util/Map<Ljava/lang/String;[Ljava/lang/annotation/Annotation;>;", null);
        fv.visitEnd();
    }
    {
        // _DynWebSocketServlet构造函数
        mv = new MethodDebugVisitor(cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null));
        mv.visitVarInsn(ALOAD, 0);
        mv.visitMethodInsn(INVOKESPECIAL, supDynName, "<init>", "()V", false);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitLdcInsn(Type.getObjectType(newDynName + "$" + newDynWebSokcetSimpleName + "Message"));
        mv.visitFieldInsn(PUTFIELD, newDynName, "messageRestType", "Ljava/lang/reflect/Type;");
        mv.visitVarInsn(ALOAD, 0);
        MethodDebugVisitor.pushInt(mv, rws.liveinterval());
        mv.visitFieldInsn(PUTFIELD, newDynName, "liveinterval", "I");
        mv.visitVarInsn(ALOAD, 0);
        MethodDebugVisitor.pushInt(mv, rws.wsmaxconns());
        mv.visitFieldInsn(PUTFIELD, newDynName, "wsmaxconns", "I");
        mv.visitVarInsn(ALOAD, 0);
        MethodDebugVisitor.pushInt(mv, rws.wsmaxbody());
        mv.visitFieldInsn(PUTFIELD, newDynName, "wsmaxbody", "I");
        mv.visitVarInsn(ALOAD, 0);
        mv.visitInsn(rws.mergemsg() ? ICONST_1 : ICONST_0);
        mv.visitFieldInsn(PUTFIELD, newDynName, "mergemsg", "Z");
        mv.visitVarInsn(ALOAD, 0);
        mv.visitInsn(rws.single() ? ICONST_1 : ICONST_0);
        mv.visitFieldInsn(PUTFIELD, newDynName, "single", "Z");
        mv.visitVarInsn(ALOAD, 0);
        mv.visitInsn(rws.anyuser() ? ICONST_1 : ICONST_0);
        mv.visitFieldInsn(PUTFIELD, newDynName, "anyuser", "Z");
        mv.visitInsn(RETURN);
        mv.visitMaxs(3, 1);
        mv.visitEnd();
    }
    {
        // createWebSocket 方法
        mv = new MethodDebugVisitor(cw.visitMethod(ACC_PROTECTED, "createWebSocket", "()" + wsDesc, "<G::Ljava/io/Serializable;T:Ljava/lang/Object;>()L" + WebSocket.class.getName().replace('.', '/') + "<TG;TT;>;", null));
        mv.visitTypeInsn(NEW, newDynName + "$" + newDynWebSokcetSimpleName);
        mv.visitInsn(DUP);
        for (int i = 0; i < resourcesFields.size(); i++) {
            mv.visitVarInsn(ALOAD, 0);
            mv.visitFieldInsn(GETFIELD, newDynName, "_redkale_resource_" + i, Type.getDescriptor(resourcesFields.get(i).getType()));
        }
        mv.visitMethodInsn(INVOKESPECIAL, newDynWebSokcetFullName, "<init>", "(" + resourceDescriptor + ")V", false);
        mv.visitInsn(ARETURN);
        mv.visitMaxs(2 + resourcesFields.size(), 1);
        mv.visitEnd();
    }
    {
        // createRestOnMessageConsumer
        mv = new MethodDebugVisitor(cw.visitMethod(ACC_PROTECTED, "createRestOnMessageConsumer", "()Ljava/util/function/BiConsumer;", "()Ljava/util/function/BiConsumer<" + wsDesc + "Ljava/lang/Object;>;", null));
        mv.visitTypeInsn(NEW, newDynConsumerFullName);
        mv.visitInsn(DUP);
        mv.visitMethodInsn(INVOKESPECIAL, newDynConsumerFullName, "<init>", "()V", false);
        mv.visitInsn(ARETURN);
        mv.visitMaxs(2, 1);
        mv.visitEnd();
    }
    {
        // resourceName
        mv = new MethodDebugVisitor(cw.visitMethod(ACC_PUBLIC, "resourceName", "()Ljava/lang/String;", null, null));
        mv.visitLdcInsn(rwsname);
        mv.visitInsn(ARETURN);
        mv.visitMaxs(1, 1);
        mv.visitEnd();
    }
    RestClassLoader newLoader = new RestClassLoader(loader);
    Map<String, Annotation[]> msgclassToAnnotations = new HashMap<>();
    for (int i = 0; i < messageMethods.size(); i++) {
        // _DyncXXXWebSocketMessage 子消息List
        final Method method = messageMethods.get(i);
        String endfix = "_" + method.getName() + "_" + (i > 9 ? i : ("0" + i));
        String newDynSuperMessageFullName = newDynMessageFullName + (method == wildcardMethod ? "" : endfix);
        msgclassToAnnotations.put(newDynSuperMessageFullName, method.getAnnotations());
        ClassWriter cw2 = new ClassWriter(COMPUTE_FRAMES);
        cw2.visit(V11, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, newDynSuperMessageFullName, null, "java/lang/Object", new String[] { webSocketParamName, "java/lang/Runnable" });
        cw2.visitInnerClass(newDynSuperMessageFullName, newDynName, newDynMessageSimpleName + endfix, ACC_PUBLIC + ACC_STATIC);
        Set<String> paramnames = new HashSet<>();
        String methodesc = method.getName() + ":" + Type.getMethodDescriptor(method);
        List<String> names = asmParamMap == null ? null : asmParamMap.get(methodesc);
        // 删掉空元素
        if (names != null)
            while (names.remove(" ")) ;
        Parameter[] params = method.getParameters();
        // 必须使用LinkedHashMap确保顺序
        final LinkedHashMap<String, Parameter> paramap = new LinkedHashMap();
        for (int j = 0; j < params.length; j++) {
            // 字段列表
            Parameter param = params[j];
            String paramname = param.getName();
            RestParam rp = param.getAnnotation(RestParam.class);
            if (rp != null && !rp.name().isEmpty()) {
                paramname = rp.name();
            } else if (names != null && names.size() > j) {
                paramname = names.get(j);
            }
            if (paramnames.contains(paramname))
                throw new RuntimeException(method + " has same @RestParam.name");
            paramnames.add(paramname);
            paramap.put(paramname, param);
            fv = cw2.visitField(ACC_PUBLIC, paramname, Type.getDescriptor(param.getType()), param.getType() == param.getParameterizedType() ? null : Utility.getTypeDescriptor(param.getParameterizedType()), null);
            fv.visitEnd();
        }
        if (method == wildcardMethod) {
            for (int j = 0; j < messageMethods.size(); j++) {
                Method method2 = messageMethods.get(j);
                if (method2 == wildcardMethod)
                    continue;
                String endfix2 = "_" + method2.getName() + "_" + (j > 9 ? j : ("0" + j));
                String newDynSuperMessageFullName2 = newDynMessageFullName + (method2 == wildcardMethod ? "" : endfix2);
                cw2.visitInnerClass(newDynSuperMessageFullName2, newDynName, newDynMessageSimpleName + endfix2, ACC_PUBLIC + ACC_STATIC);
                fv = cw2.visitField(ACC_PUBLIC, method2.getAnnotation(RestOnMessage.class).name(), "L" + newDynSuperMessageFullName2 + ";", null, null);
                fv.visitEnd();
            }
        }
        {
            // _redkale_websocket
            fv = cw2.visitField(ACC_PUBLIC, "_redkale_websocket", "L" + newDynWebSokcetFullName + ";", null, null);
            av0 = fv.visitAnnotation(convertDisabledDesc, true);
            av0.visitEnd();
            fv.visitEnd();
        }
        {
            // 空构造函数
            mv = new MethodDebugVisitor(cw2.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null));
            mv.visitVarInsn(ALOAD, 0);
            mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
            mv.visitInsn(RETURN);
            mv.visitMaxs(1, 1);
            mv.visitEnd();
        }
        {
            // getNames
            mv = new MethodDebugVisitor(cw2.visitMethod(ACC_PUBLIC, "getNames", "()[Ljava/lang/String;", null, null));
            av0 = mv.visitAnnotation(convertDisabledDesc, true);
            av0.visitEnd();
            MethodDebugVisitor.pushInt(mv, paramap.size());
            mv.visitTypeInsn(ANEWARRAY, "java/lang/String");
            int index = -1;
            for (Map.Entry<String, Parameter> en : paramap.entrySet()) {
                mv.visitInsn(DUP);
                MethodDebugVisitor.pushInt(mv, ++index);
                mv.visitLdcInsn(en.getKey());
                mv.visitInsn(AASTORE);
            }
            mv.visitInsn(ARETURN);
            mv.visitMaxs(paramap.size() + 2, 1);
            mv.visitEnd();
        }
        {
            // getValue
            mv = new MethodDebugVisitor(cw2.visitMethod(ACC_PUBLIC, "getValue", "(Ljava/lang/String;)Ljava/lang/Object;", "<T:Ljava/lang/Object;>(Ljava/lang/String;)TT;", null));
            for (Map.Entry<String, Parameter> en : paramap.entrySet()) {
                Class paramType = en.getValue().getType();
                mv.visitLdcInsn(en.getKey());
                mv.visitVarInsn(ALOAD, 1);
                mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z", false);
                Label l1 = new Label();
                mv.visitJumpInsn(IFEQ, l1);
                mv.visitVarInsn(ALOAD, 0);
                mv.visitFieldInsn(GETFIELD, newDynSuperMessageFullName, en.getKey(), Type.getDescriptor(paramType));
                if (paramType.isPrimitive()) {
                    Class bigclaz = java.lang.reflect.Array.get(java.lang.reflect.Array.newInstance(paramType, 1), 0).getClass();
                    mv.visitMethodInsn(INVOKESTATIC, bigclaz.getName().replace('.', '/'), "valueOf", "(" + Type.getDescriptor(paramType) + ")" + Type.getDescriptor(bigclaz), false);
                }
                mv.visitInsn(ARETURN);
                mv.visitLabel(l1);
            }
            mv.visitInsn(ACONST_NULL);
            mv.visitInsn(ARETURN);
            mv.visitMaxs(2, 2);
            mv.visitEnd();
        }
        {
            // getAnnotations
            mv = new MethodDebugVisitor(cw2.visitMethod(ACC_PUBLIC, "getAnnotations", "()[Ljava/lang/annotation/Annotation;", null, null));
            av0 = mv.visitAnnotation(convertDisabledDesc, true);
            av0.visitEnd();
            mv.visitFieldInsn(GETSTATIC, newDynName, "_redkale_annotations", "Ljava/util/Map;");
            mv.visitLdcInsn(newDynSuperMessageFullName);
            mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Map", "get", "(Ljava/lang/Object;)Ljava/lang/Object;", true);
            mv.visitTypeInsn(CHECKCAST, "[Ljava/lang/annotation/Annotation;");
            mv.visitVarInsn(ASTORE, 1);
            mv.visitVarInsn(ALOAD, 1);
            Label l2 = new Label();
            mv.visitJumpInsn(IFNONNULL, l2);
            mv.visitInsn(ICONST_0);
            mv.visitTypeInsn(ANEWARRAY, "java/lang/annotation/Annotation");
            mv.visitInsn(ARETURN);
            mv.visitLabel(l2);
            mv.visitFrame(Opcodes.F_APPEND, 1, new Object[] { "[Ljava/lang/annotation/Annotation;" }, 0, null);
            mv.visitVarInsn(ALOAD, 1);
            mv.visitVarInsn(ALOAD, 1);
            mv.visitInsn(ARRAYLENGTH);
            mv.visitMethodInsn(INVOKESTATIC, "java/util/Arrays", "copyOf", "([Ljava/lang/Object;I)[Ljava/lang/Object;", false);
            mv.visitTypeInsn(CHECKCAST, "[Ljava/lang/annotation/Annotation;");
            mv.visitInsn(ARETURN);
            mv.visitMaxs(2, 2);
            mv.visitEnd();
        }
        {
            // execute
            mv = new MethodDebugVisitor(cw2.visitMethod(ACC_PUBLIC, "execute", "(L" + newDynWebSokcetFullName + ";)V", null, null));
            mv.visitVarInsn(ALOAD, 0);
            mv.visitVarInsn(ALOAD, 1);
            mv.visitFieldInsn(PUTFIELD, newDynSuperMessageFullName, "_redkale_websocket", "L" + newDynWebSokcetFullName + ";");
            mv.visitVarInsn(ALOAD, 1);
            mv.visitLdcInsn(method.getAnnotation(RestOnMessage.class).name());
            mv.visitVarInsn(ALOAD, 0);
            mv.visitVarInsn(ALOAD, 0);
            mv.visitMethodInsn(INVOKEVIRTUAL, newDynWebSokcetFullName, "preOnMessage", "(Ljava/lang/String;" + wsParamDesc + "Ljava/lang/Runnable;)V", false);
            mv.visitInsn(RETURN);
            mv.visitMaxs(4, 2);
            mv.visitEnd();
        }
        {
            // run
            mv = new MethodDebugVisitor(cw2.visitMethod(ACC_PUBLIC, "run", "()V", null, null));
            mv.visitVarInsn(ALOAD, 0);
            mv.visitFieldInsn(GETFIELD, newDynSuperMessageFullName, "_redkale_websocket", "L" + newDynWebSokcetFullName + ";");
            for (Map.Entry<String, Parameter> en : paramap.entrySet()) {
                mv.visitVarInsn(ALOAD, 0);
                mv.visitFieldInsn(GETFIELD, (newDynSuperMessageFullName), en.getKey(), Type.getDescriptor(en.getValue().getType()));
            }
            mv.visitMethodInsn(INVOKEVIRTUAL, newDynWebSokcetFullName, method.getName(), Type.getMethodDescriptor(method), false);
            mv.visitInsn(RETURN);
            mv.visitMaxs(3, 1);
            mv.visitEnd();
        }
        {
            // toString
            mv = new MethodDebugVisitor(cw2.visitMethod(ACC_PUBLIC, "toString", "()Ljava/lang/String;", null, null));
            mv.visitMethodInsn(INVOKESTATIC, JsonConvert.class.getName().replace('.', '/'), "root", "()" + jsonConvertDesc, false);
            mv.visitVarInsn(ALOAD, 0);
            mv.visitMethodInsn(INVOKEVIRTUAL, JsonConvert.class.getName().replace('.', '/'), "convertTo", "(Ljava/lang/Object;)Ljava/lang/String;", false);
            mv.visitInsn(ARETURN);
            mv.visitMaxs(2, 1);
            mv.visitEnd();
        }
        cw2.visitEnd();
        byte[] bytes = cw2.toByteArray();
        Class cz = newLoader.loadClass((newDynSuperMessageFullName).replace('/', '.'), bytes);
        RedkaleClassLoader.putDynClass((newDynSuperMessageFullName).replace('/', '.'), bytes, cz);
    }
    if (wildcardMethod == null) {
        // _DynXXXWebSocketMessage class
        ClassWriter cw2 = new ClassWriter(COMPUTE_FRAMES);
        cw2.visit(V11, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, newDynMessageFullName, null, "java/lang/Object", null);
        cw2.visitInnerClass(newDynMessageFullName, newDynName, newDynMessageSimpleName, ACC_PUBLIC + ACC_STATIC);
        for (int i = 0; i < messageMethods.size(); i++) {
            Method method = messageMethods.get(i);
            String endfix = "_" + method.getName() + "_" + (i > 9 ? i : ("0" + i));
            String newDynSuperMessageFullName = newDynMessageFullName + (method == wildcardMethod ? "" : endfix);
            cw2.visitInnerClass(newDynSuperMessageFullName, newDynName, newDynMessageSimpleName + endfix, ACC_PUBLIC + ACC_STATIC);
            fv = cw2.visitField(ACC_PUBLIC, method.getAnnotation(RestOnMessage.class).name(), "L" + newDynSuperMessageFullName + ";", null, null);
            fv.visitEnd();
        }
        {
            // 构造函数
            mv = new MethodDebugVisitor(cw2.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null));
            mv.visitVarInsn(ALOAD, 0);
            mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
            mv.visitInsn(RETURN);
            mv.visitMaxs(1, 1);
            mv.visitEnd();
        }
        {
            // toString
            mv = new MethodDebugVisitor(cw2.visitMethod(ACC_PUBLIC, "toString", "()Ljava/lang/String;", null, null));
            mv.visitMethodInsn(INVOKESTATIC, JsonConvert.class.getName().replace('.', '/'), "root", "()" + jsonConvertDesc, false);
            mv.visitVarInsn(ALOAD, 0);
            mv.visitMethodInsn(INVOKEVIRTUAL, JsonConvert.class.getName().replace('.', '/'), "convertTo", "(Ljava/lang/Object;)Ljava/lang/String;", false);
            mv.visitInsn(ARETURN);
            mv.visitMaxs(2, 1);
            mv.visitEnd();
        }
        cw2.visitEnd();
        byte[] bytes = cw2.toByteArray();
        Class cz = newLoader.loadClass(newDynMessageFullName.replace('/', '.'), bytes);
        RedkaleClassLoader.putDynClass(newDynMessageFullName.replace('/', '.'), bytes, cz);
    }
    {
        // _DynXXXWebSocket class
        ClassWriter cw2 = new ClassWriter(COMPUTE_FRAMES);
        cw2.visit(V11, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, newDynWebSokcetFullName, null, webSocketInternalName, null);
        cw2.visitInnerClass(newDynWebSokcetFullName, newDynName, newDynWebSokcetSimpleName, ACC_PUBLIC + ACC_STATIC);
        {
            mv = new MethodDebugVisitor(cw2.visitMethod(ACC_PUBLIC, "<init>", "(" + resourceDescriptor + ")V", resourceGenericDescriptor == null ? null : ("(" + resourceGenericDescriptor + ")V"), null));
            mv.visitVarInsn(ALOAD, 0);
            mv.visitMethodInsn(INVOKESPECIAL, webSocketInternalName, "<init>", "()V", false);
            for (int i = 0; i < resourcesFields.size(); i++) {
                Field field = resourcesFields.get(i);
                mv.visitVarInsn(ALOAD, 0);
                mv.visitVarInsn(ALOAD, i + 1);
                mv.visitFieldInsn(PUTFIELD, newDynWebSokcetFullName, field.getName(), Type.getDescriptor(field.getType()));
            }
            mv.visitInsn(RETURN);
            mv.visitMaxs(2, 1 + resourcesFields.size());
            mv.visitEnd();
        }
        {
            // RestDyn
            av0 = cw2.visitAnnotation(Type.getDescriptor(RestDyn.class), true);
            av0.visit("simple", false);
            av0.visitEnd();
        }
        cw2.visitEnd();
        byte[] bytes = cw2.toByteArray();
        Class cz = newLoader.loadClass(newDynWebSokcetFullName.replace('/', '.'), bytes);
        RedkaleClassLoader.putDynClass(newDynWebSokcetFullName.replace('/', '.'), bytes, cz);
    }
    {
        // _DynRestOnMessageConsumer class
        ClassWriter cw2 = new ClassWriter(COMPUTE_FRAMES);
        cw2.visit(V11, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, newDynConsumerFullName, "Ljava/lang/Object;Ljava/util/function/BiConsumer<" + wsDesc + "Ljava/lang/Object;>;", "java/lang/Object", new String[] { "java/util/function/BiConsumer" });
        cw2.visitInnerClass(newDynConsumerFullName, newDynName, newDynConsumerSimpleName, ACC_PUBLIC + ACC_STATIC);
        cw2.visitInnerClass(newDynMessageFullName, newDynName, newDynMessageSimpleName, ACC_PUBLIC + ACC_STATIC);
        for (int i = 0; i < messageMethods.size(); i++) {
            Method method = messageMethods.get(i);
            String endfix = "_" + method.getName() + "_" + (i > 9 ? i : ("0" + i));
            String newDynSuperMessageFullName = newDynMessageFullName + (method == wildcardMethod ? "" : endfix);
            cw2.visitInnerClass(newDynSuperMessageFullName, newDynName, newDynMessageSimpleName + endfix, ACC_PUBLIC + ACC_STATIC);
        }
        {
            // 构造函数
            mv = new MethodDebugVisitor(cw2.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null));
            mv.visitVarInsn(ALOAD, 0);
            mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
            mv.visitInsn(RETURN);
            mv.visitMaxs(1, 1);
            mv.visitEnd();
        }
        {
            // accept函数
            mv = new MethodDebugVisitor(cw2.visitMethod(ACC_PUBLIC, "accept", "(" + wsDesc + "Ljava/lang/Object;)V", null, null));
            mv.visitVarInsn(ALOAD, 1);
            mv.visitTypeInsn(CHECKCAST, newDynWebSokcetFullName);
            mv.visitVarInsn(ASTORE, 3);
            mv.visitVarInsn(ALOAD, 2);
            mv.visitTypeInsn(CHECKCAST, newDynMessageFullName);
            mv.visitVarInsn(ASTORE, 4);
            for (int i = 0; i < messageMethods.size(); i++) {
                final Method method = messageMethods.get(i);
                String endfix = "_" + method.getName() + "_" + (i > 9 ? i : ("0" + i));
                String newDynSuperMessageFullName = newDynMessageFullName + (method == wildcardMethod ? "" : endfix);
                final String messagename = method.getAnnotation(RestOnMessage.class).name();
                if (method == wildcardMethod) {
                    mv.visitVarInsn(ALOAD, 4);
                    mv.visitVarInsn(ALOAD, 3);
                    mv.visitMethodInsn(INVOKEVIRTUAL, newDynSuperMessageFullName, "execute", "(L" + newDynWebSokcetFullName + ";)V", false);
                } else {
                    mv.visitVarInsn(ALOAD, 4);
                    mv.visitFieldInsn(GETFIELD, newDynMessageFullName, messagename, "L" + newDynSuperMessageFullName + ";");
                    Label ifLabel = new Label();
                    mv.visitJumpInsn(IFNULL, ifLabel);
                    mv.visitVarInsn(ALOAD, 4);
                    mv.visitFieldInsn(GETFIELD, newDynMessageFullName, messagename, "L" + newDynSuperMessageFullName + ";");
                    mv.visitVarInsn(ALOAD, 3);
                    mv.visitMethodInsn(INVOKEVIRTUAL, newDynSuperMessageFullName, "execute", "(L" + newDynWebSokcetFullName + ";)V", false);
                    mv.visitInsn(RETURN);
                    mv.visitLabel(ifLabel);
                }
            }
            mv.visitInsn(RETURN);
            mv.visitMaxs(3, 3 + messageMethods.size());
            mv.visitEnd();
        }
        {
            // 虚拟accept函数
            mv = new MethodDebugVisitor(cw2.visitMethod(ACC_PUBLIC + ACC_BRIDGE + ACC_SYNTHETIC, "accept", "(Ljava/lang/Object;Ljava/lang/Object;)V", null, null));
            mv.visitVarInsn(ALOAD, 0);
            mv.visitVarInsn(ALOAD, 1);
            mv.visitTypeInsn(CHECKCAST, WebSocket.class.getName().replace('.', '/'));
            mv.visitVarInsn(ALOAD, 2);
            mv.visitTypeInsn(CHECKCAST, "java/lang/Object");
            mv.visitMethodInsn(INVOKEVIRTUAL, newDynConsumerFullName, "accept", "(" + wsDesc + "Ljava/lang/Object;)V", false);
            mv.visitInsn(RETURN);
            mv.visitMaxs(3, 3);
            mv.visitEnd();
        }
        cw2.visitEnd();
        byte[] bytes = cw2.toByteArray();
        Class cz = newLoader.loadClass(newDynConsumerFullName.replace('/', '.'), bytes);
        RedkaleClassLoader.putDynClass(newDynConsumerFullName.replace('/', '.'), bytes, cz);
    }
    cw.visitEnd();
    byte[] bytes = cw.toByteArray();
    Class<?> newClazz = newLoader.loadClass(newDynName.replace('/', '.'), bytes);
    RedkaleClassLoader.putDynClass(newDynName.replace('/', '.'), bytes, newClazz);
    RedkaleClassLoader.putReflectionDeclaredConstructors(newClazz, newDynName.replace('/', '.'));
    // 固定Message类
    JsonFactory.root().loadDecoder(newClazz.getAnnotation(RestDyn.class).types()[2]);
    RedkaleClassLoader.putReflectionPublicMethods(webSocketType.getName());
    Class cwt = webSocketType;
    do {
        RedkaleClassLoader.putReflectionDeclaredFields(cwt.getName());
    } while ((cwt = cwt.getSuperclass()) != Object.class);
    RedkaleClassLoader.putReflectionDeclaredConstructors(webSocketType, webSocketType.getName());
    try {
        T servlet = (T) newClazz.getDeclaredConstructor().newInstance();
        Field field = newClazz.getField("_redkale_annotations");
        field.set(null, msgclassToAnnotations);
        RedkaleClassLoader.putReflectionField(newDynName.replace('/', '.'), field);
        if (rws.cryptor() != Cryptor.class) {
            RedkaleClassLoader.putReflectionDeclaredConstructors(rws.cryptor(), rws.cryptor().getName());
            Cryptor cryptor = rws.cryptor().getDeclaredConstructor().newInstance();
            // WebSocketServlet
            Field cryptorField = newClazz.getSuperclass().getDeclaredField("cryptor");
            RedkaleClassLoader.putReflectionField(newDynName.replace('/', '.'), cryptorField);
            cryptorField.setAccessible(true);
            cryptorField.set(servlet, cryptor);
        }
        if (messageAgent != null)
            ((WebSocketServlet) servlet).messageAgent = messageAgent;
        return servlet;
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}
Also used : Resource(javax.annotation.Resource) MethodDebugVisitor(org.redkale.asm.MethodDebugVisitor) Type(org.redkale.asm.Type) ElementType(java.lang.annotation.ElementType)

Example 3 with Type

use of org.redkale.asm.Type in project redkale by redkale.

the class Rest method createRestServlet.

public static <T extends HttpServlet> T createRestServlet(final ClassLoader classLoader, final Class userType0, final Class<T> baseServletType, final Class<? extends Service> serviceType) {
    if (baseServletType == null || serviceType == null)
        throw new RuntimeException(" Servlet or Service is null Class on createRestServlet");
    if (!HttpServlet.class.isAssignableFrom(baseServletType))
        throw new RuntimeException(baseServletType + " is not HttpServlet Class on createRestServlet");
    int mod = baseServletType.getModifiers();
    if (!java.lang.reflect.Modifier.isPublic(mod))
        throw new RuntimeException(baseServletType + " is not Public Class on createRestServlet");
    if (java.lang.reflect.Modifier.isAbstract(mod)) {
        for (Method m : baseServletType.getDeclaredMethods()) {
            if (java.lang.reflect.Modifier.isAbstract(m.getModifiers())) {
                // @since 2.4.0
                throw new RuntimeException(baseServletType + " cannot contains a abstract Method on " + baseServletType);
            }
        }
    }
    final String restInternalName = Type.getInternalName(Rest.class);
    final String serviceDesc = Type.getDescriptor(serviceType);
    final String webServletDesc = Type.getDescriptor(WebServlet.class);
    final String resDesc = Type.getDescriptor(Resource.class);
    final String reqDesc = Type.getDescriptor(HttpRequest.class);
    final String respDesc = Type.getDescriptor(HttpResponse.class);
    final String convertDesc = Type.getDescriptor(Convert.class);
    final String typeDesc = Type.getDescriptor(java.lang.reflect.Type.class);
    final String retDesc = Type.getDescriptor(RetResult.class);
    final String httpResultDesc = Type.getDescriptor(HttpResult.class);
    final String httpScopeDesc = Type.getDescriptor(HttpScope.class);
    final String stageDesc = Type.getDescriptor(CompletionStage.class);
    final String flipperDesc = Type.getDescriptor(Flipper.class);
    final String channelDesc = Type.getDescriptor(ChannelContext.class);
    final String httpServletName = HttpServlet.class.getName().replace('.', '/');
    final String actionEntryName = HttpServlet.ActionEntry.class.getName().replace('.', '/');
    final String attrDesc = Type.getDescriptor(org.redkale.util.Attribute.class);
    final String multiContextDesc = Type.getDescriptor(MultiContext.class);
    final String multiContextName = MultiContext.class.getName().replace('.', '/');
    final String mappingDesc = Type.getDescriptor(HttpMapping.class);
    final String httpParamDesc = Type.getDescriptor(HttpParam.class);
    final String httpParamsDesc = Type.getDescriptor(HttpParam.HttpParams.class);
    final String sourcetypeDesc = Type.getDescriptor(HttpParam.HttpParameterStyle.class);
    final String reqInternalName = Type.getInternalName(HttpRequest.class);
    final String respInternalName = Type.getInternalName(HttpResponse.class);
    final String attrInternalName = Type.getInternalName(org.redkale.util.Attribute.class);
    final String retInternalName = Type.getInternalName(RetResult.class);
    final String serviceTypeInternalName = Type.getInternalName(serviceType);
    HttpUserType hut = baseServletType.getAnnotation(HttpUserType.class);
    final Class userType = (userType0 == null || userType0 == Object.class) ? (hut == null ? null : hut.value()) : userType0;
    if (userType != null && (userType.isPrimitive() || userType.getName().startsWith("java.") || userType.getName().startsWith("javax."))) {
        throw new RuntimeException(HttpUserType.class.getSimpleName() + " must be a JavaBean but found " + userType);
    }
    final String supDynName = baseServletType.getName().replace('.', '/');
    final RestService controller = serviceType.getAnnotation(RestService.class);
    // 标记为ignore=true不创建Servlet
    if (controller != null && controller.ignore())
        throw new RuntimeException(serviceType + " is ignore Rest Service Class");
    final boolean serrpconly = controller != null && controller.rpconly();
    ClassLoader loader = classLoader == null ? Thread.currentThread().getContextClassLoader() : classLoader;
    String stname = serviceType.getSimpleName();
    if (stname.startsWith("Service")) {
        // 类似ServiceWatchService这样的类保留第一个Service字样
        stname = "Service" + stname.substring("Service".length()).replaceAll("Service.*$", "");
    } else {
        stname = stname.replaceAll("Service.*$", "");
    }
    // String newDynName = serviceTypeInternalName.substring(0, serviceTypeInternalName.lastIndexOf('/') + 1) + "_Dyn" + stname + "RestServlet";
    final String newDynName = "org/redkaledyn/http/rest/" + "_Dyn" + stname + "RestServlet__" + serviceType.getName().replace('.', '_').replace('$', '_') + "DynServlet";
    try {
        Class newClazz = RedkaleClassLoader.findDynClass(newDynName.replace('/', '.'));
        if (newClazz == null)
            newClazz = loader.loadClass(newDynName.replace('/', '.'));
        T obj = (T) newClazz.getDeclaredConstructor().newInstance();
        final String defmodulename = getWebModuleNameLowerCase(serviceType);
        final String bigmodulename = getWebModuleName(serviceType);
        final Map<String, Object> classMap = new LinkedHashMap<>();
        final List<MappingEntry> entrys = new ArrayList<>();
        final List<java.lang.reflect.Type[]> paramTypes = new ArrayList<>();
        final List<java.lang.reflect.Type> retvalTypes = new ArrayList<>();
        final List<Object[]> restConverts = new ArrayList<>();
        final Map<java.lang.reflect.Type, String> typeRefs = new LinkedHashMap<>();
        final Map<String, Method> mappingurlToMethod = new HashMap<>();
        final Map<String, org.redkale.util.Attribute> restAttributes = new LinkedHashMap<>();
        final Map<String, java.lang.reflect.Type> bodyTypes = new HashMap<>();
        {
            // entrys、paramTypes赋值
            final Method[] allMethods = serviceType.getMethods();
            Arrays.sort(allMethods, (m1, m2) -> {
                // 必须排序,否则paramTypes顺序容易乱
                int s = m1.getName().compareTo(m2.getName());
                if (s != 0)
                    return s;
                s = Arrays.toString(m1.getParameterTypes()).compareTo(Arrays.toString(m2.getParameterTypes()));
                return s;
            });
            int methodidex = 0;
            for (final Method method : allMethods) {
                if (Modifier.isStatic(method.getModifiers()))
                    continue;
                if (method.isSynthetic())
                    continue;
                if (EXCLUDERMETHODS.contains(method.getName()))
                    continue;
                if (method.getParameterCount() == 1 && method.getParameterTypes()[0] == AnyValue.class) {
                    if ("init".equals(method.getName()))
                        continue;
                    if ("stop".equals(method.getName()))
                        continue;
                    if ("destroy".equals(method.getName()))
                        continue;
                }
                if (controller == null)
                    continue;
                RestMapping[] mappings = method.getAnnotationsByType(RestMapping.class);
                if (!controller.automapping() && mappings.length < 1)
                    continue;
                boolean ignore = false;
                for (RestMapping mapping : mappings) {
                    if (mapping.ignore()) {
                        ignore = true;
                        break;
                    }
                }
                if (ignore)
                    continue;
                paramTypes.add(TypeToken.getGenericType(method.getGenericParameterTypes(), serviceType));
                retvalTypes.add(formatRestReturnType(method, serviceType));
                if (mappings.length == 0) {
                    // 没有Mapping,设置一个默认值
                    MappingEntry entry = new MappingEntry(serrpconly, methodidex, null, bigmodulename, method);
                    entrys.add(entry);
                } else {
                    for (RestMapping mapping : mappings) {
                        MappingEntry entry = new MappingEntry(serrpconly, methodidex, mapping, defmodulename, method);
                        entrys.add(entry);
                    }
                }
                methodidex++;
            }
            Collections.sort(entrys);
        }
        {
            // restConverts、typeRefs、mappingurlToMethod、restAttributes、bodyTypes赋值
            for (final MappingEntry entry : entrys) {
                mappingurlToMethod.put(entry.mappingurl, entry.mappingMethod);
                final Method method = entry.mappingMethod;
                final Class returnType = method.getReturnType();
                final Parameter[] params = method.getParameters();
                final RestConvert[] rcs = method.getAnnotationsByType(RestConvert.class);
                final RestConvertCoder[] rcc = method.getAnnotationsByType(RestConvertCoder.class);
                if ((rcs != null && rcs.length > 0) || (rcc != null && rcc.length > 0)) {
                    restConverts.add(new Object[] { rcs, rcc });
                }
                // 解析方法中的每个参数
                List<Object[]> paramlist = new ArrayList<>();
                for (int i = 0; i < params.length; i++) {
                    final Parameter param = params[i];
                    final Class ptype = param.getType();
                    String n = null;
                    String comment = "";
                    boolean required = true;
                    int radix = 10;
                    RestHeader annhead = param.getAnnotation(RestHeader.class);
                    if (annhead != null) {
                        n = annhead.name();
                        radix = annhead.radix();
                        comment = annhead.comment();
                        required = annhead.required();
                    }
                    RestCookie anncookie = param.getAnnotation(RestCookie.class);
                    if (anncookie != null) {
                        n = anncookie.name();
                        radix = anncookie.radix();
                        comment = anncookie.comment();
                    }
                    RestSessionid annsid = param.getAnnotation(RestSessionid.class);
                    RestAddress annaddr = param.getAnnotation(RestAddress.class);
                    if (annaddr != null) {
                        comment = annaddr.comment();
                    }
                    RestBody annbody = param.getAnnotation(RestBody.class);
                    if (annbody != null) {
                        comment = annbody.comment();
                    }
                    RestUploadFile annfile = param.getAnnotation(RestUploadFile.class);
                    if (annfile != null) {
                        comment = annfile.comment();
                    }
                    RestURI annuri = param.getAnnotation(RestURI.class);
                    if (annuri != null) {
                        comment = annuri.comment();
                    }
                    RestUserid userid = param.getAnnotation(RestUserid.class);
                    if (userid != null) {
                        comment = "";
                    }
                    RestHeaders annheaders = param.getAnnotation(RestHeaders.class);
                    if (annheaders != null) {
                        comment = "";
                    }
                    RestParams annparams = param.getAnnotation(RestParams.class);
                    if (annparams != null) {
                        comment = "";
                    }
                    RestParam annpara = param.getAnnotation(RestParam.class);
                    if (annpara != null)
                        radix = annpara.radix();
                    if (annpara != null)
                        comment = annpara.comment();
                    if (annpara != null)
                        required = annpara.required();
                    if (n == null)
                        n = (annpara == null || annpara.name().isEmpty()) ? null : annpara.name();
                    // 用户类型特殊处理
                    if (n == null && ptype == userType)
                        n = "&";
                    if (n == null) {
                        if (param.isNamePresent()) {
                            n = param.getName();
                        } else if (ptype == Flipper.class) {
                            n = "flipper";
                        }
                    }
                    // n maybe is null
                    java.lang.reflect.Type paramtype = TypeToken.getGenericType(param.getParameterizedType(), serviceType);
                    paramlist.add(new Object[] { param, n, ptype, radix, comment, required, annpara, annsid, annaddr, annhead, anncookie, annbody, annfile, annuri, userid, annheaders, annparams, paramtype });
                }
                for (Object[] ps : paramlist) {
                    // {param, n, ptype, radix, comment, required, annpara, annsid, annaddr, annhead, anncookie, annbody, annfile, annuri, annuserid, annheaders, annparams, paramtype}
                    // 是否取userid
                    final boolean isuserid = ((RestUserid) ps[14]) != null;
                    // @RestUserid 不需要生成 @HttpParam
                    if ((ps[1] != null && ps[1].toString().indexOf('&') >= 0) || isuserid)
                        continue;
                    // @RestAddress 不需要生成 @HttpParam
                    if (((RestAddress) ps[8]) != null)
                        continue;
                    java.lang.reflect.Type pgtype = TypeToken.getGenericType(((Parameter) ps[0]).getParameterizedType(), serviceType);
                    if (pgtype != (Class) ps[2]) {
                        String refid = typeRefs.get(pgtype);
                        if (refid == null) {
                            refid = "_typeref_" + typeRefs.size();
                            typeRefs.put(pgtype, refid);
                        }
                    }
                    // 参数类型
                    final Parameter param = (Parameter) ps[0];
                    // 参数名
                    String pname = (String) ps[1];
                    // 参数类型
                    Class ptype = (Class) ps[2];
                    int radix = (Integer) ps[3];
                    String comment = (String) ps[4];
                    boolean required = (Boolean) ps[5];
                    RestParam annpara = (RestParam) ps[6];
                    RestSessionid annsid = (RestSessionid) ps[7];
                    RestAddress annaddr = (RestAddress) ps[8];
                    RestHeader annhead = (RestHeader) ps[9];
                    RestCookie anncookie = (RestCookie) ps[10];
                    RestBody annbody = (RestBody) ps[11];
                    RestUploadFile annfile = (RestUploadFile) ps[12];
                    RestURI annuri = (RestURI) ps[13];
                    RestUserid annuserid = (RestUserid) ps[14];
                    RestHeaders annheaders = (RestHeaders) ps[15];
                    RestParams annparams = (RestParams) ps[16];
                    if (CompletionHandler.class.isAssignableFrom(ptype)) {
                    // HttpResponse.createAsyncHandler() or HttpResponse.createAsyncHandler(Class)
                    } else if (annsid != null) {
                    // HttpRequest.getSessionid(true|false)
                    } else if (annaddr != null) {
                    // HttpRequest.getRemoteAddr
                    } else if (annheaders != null) {
                    // HttpRequest.getHeaders
                    } else if (annparams != null) {
                    // HttpRequest.getParameters
                    } else if (annbody != null) {
                    // HttpRequest.getBodyUTF8 / HttpRequest.getBody
                    } else if (annfile != null) {
                    // MultiContext.partsFirstBytes / HttpRequest.partsFirstFile / HttpRequest.partsFiles
                    } else if (annuri != null) {
                    // HttpRequest.getRequestURI
                    } else if (annuserid != null) {
                    // HttpRequest.currentUserid
                    } else if ("#".equals(pname)) {
                    // 从request.getRequstURI 中取参数
                    } else if (pname != null && pname.charAt(0) == '#') {
                    // 从request.getRequstURIPath 中去参数
                    } else if ("&".equals(pname) && ptype == userType) {
                    // 当前用户对象的类名
                    } else if (ptype.isPrimitive()) {
                    } else if (ptype == String.class) {
                    } else if (ptype == ChannelContext.class) {
                    } else if (ptype == Flipper.class) {
                    } else {
                        // 其他Json对象
                        // 构建 RestHeader、RestCookie、RestAddress 等赋值操作
                        Class loop = ptype;
                        Set<String> fields = new HashSet<>();
                        Map<String, Object[]> attrParaNames = new LinkedHashMap<>();
                        do {
                            // 接口时getSuperclass可能会得到null
                            if (loop == null || loop.isInterface())
                                break;
                            for (Field field : loop.getDeclaredFields()) {
                                if (Modifier.isStatic(field.getModifiers()))
                                    continue;
                                if (Modifier.isFinal(field.getModifiers()))
                                    continue;
                                if (fields.contains(field.getName()))
                                    continue;
                                RestHeader rh = field.getAnnotation(RestHeader.class);
                                RestCookie rc = field.getAnnotation(RestCookie.class);
                                RestSessionid rs = field.getAnnotation(RestSessionid.class);
                                RestAddress ra = field.getAnnotation(RestAddress.class);
                                RestBody rb = field.getAnnotation(RestBody.class);
                                RestUploadFile ru = field.getAnnotation(RestUploadFile.class);
                                RestURI ri = field.getAnnotation(RestURI.class);
                                if (rh == null && rc == null && ra == null && rb == null && rs == null && ru == null && ri == null)
                                    continue;
                                org.redkale.util.Attribute attr = org.redkale.util.Attribute.create(loop, field);
                                String attrFieldName;
                                String restname = "";
                                if (rh != null) {
                                    attrFieldName = "_redkale_attr_header_" + (field.getType() != String.class ? "json_" : "") + restAttributes.size();
                                    restname = rh.name();
                                } else if (rc != null) {
                                    attrFieldName = "_redkale_attr_cookie_" + restAttributes.size();
                                    restname = rc.name();
                                } else if (rs != null) {
                                    attrFieldName = "_redkale_attr_sessionid_" + restAttributes.size();
                                    // 用于下面区分create值
                                    restname = rs.create() ? "1" : "";
                                } else if (ra != null) {
                                    attrFieldName = "_redkale_attr_address_" + restAttributes.size();
                                // restname = "";
                                } else if (rb != null && field.getType() == String.class) {
                                    attrFieldName = "_redkale_attr_bodystring_" + restAttributes.size();
                                // restname = "";
                                } else if (rb != null && field.getType() == byte[].class) {
                                    attrFieldName = "_redkale_attr_bodybytes_" + restAttributes.size();
                                // restname = "";
                                } else if (rb != null && field.getType() != String.class && field.getType() != byte[].class) {
                                    attrFieldName = "_redkale_attr_bodyjson_" + restAttributes.size();
                                // restname = "";
                                } else if (ru != null && field.getType() == byte[].class) {
                                    attrFieldName = "_redkale_attr_uploadbytes_" + restAttributes.size();
                                // restname = "";
                                } else if (ru != null && field.getType() == File.class) {
                                    attrFieldName = "_redkale_attr_uploadfile_" + restAttributes.size();
                                // restname = "";
                                } else if (ru != null && field.getType() == File[].class) {
                                    attrFieldName = "_redkale_attr_uploadfiles_" + restAttributes.size();
                                // restname = "";
                                } else if (ri != null && field.getType() == String.class) {
                                    attrFieldName = "_redkale_attr_uri_" + restAttributes.size();
                                // restname = "";
                                } else {
                                    continue;
                                }
                                restAttributes.put(attrFieldName, attr);
                                attrParaNames.put(attrFieldName, new Object[] { restname, field.getType(), field.getGenericType(), ru });
                                fields.add(field.getName());
                            }
                        } while ((loop = loop.getSuperclass()) != Object.class);
                        if (!attrParaNames.isEmpty()) {
                            // 参数存在 RestHeader、RestCookie、RestSessionid、RestAddress、RestBody字段
                            for (Map.Entry<String, Object[]> en : attrParaNames.entrySet()) {
                                if (en.getKey().contains("_header_")) {
                                    String headerkey = en.getValue()[0].toString();
                                    if ("Host".equalsIgnoreCase(headerkey)) {
                                    } else if ("Content-Type".equalsIgnoreCase(headerkey)) {
                                    } else if ("Connection".equalsIgnoreCase(headerkey)) {
                                    } else if ("Method".equalsIgnoreCase(headerkey)) {
                                    } else if (en.getKey().contains("_header_json_")) {
                                        String typefieldname = "_redkale_body_jsontype_" + bodyTypes.size();
                                        bodyTypes.put(typefieldname, (java.lang.reflect.Type) en.getValue()[2]);
                                    }
                                } else if (en.getKey().contains("_cookie_")) {
                                } else if (en.getKey().contains("_sessionid_")) {
                                } else if (en.getKey().contains("_address_")) {
                                } else if (en.getKey().contains("_uri_")) {
                                } else if (en.getKey().contains("_bodystring_")) {
                                } else if (en.getKey().contains("_bodybytes_")) {
                                } else if (en.getKey().contains("_bodyjson_")) {
                                    // JavaBean 转 Json
                                    String typefieldname = "_redkale_body_jsontype_" + bodyTypes.size();
                                    bodyTypes.put(typefieldname, (java.lang.reflect.Type) en.getValue()[2]);
                                } else if (en.getKey().contains("_uploadbytes_")) {
                                // 只需mv.visitVarInsn(ALOAD, 4), 无需处理
                                } else if (en.getKey().contains("_uploadfile_")) {
                                // 只需mv.visitVarInsn(ALOAD, 4), 无需处理
                                } else if (en.getKey().contains("_uploadfiles_")) {
                                // 只需mv.visitVarInsn(ALOAD, 4), 无需处理
                                }
                            }
                        }
                    }
                }
                java.lang.reflect.Type grt = TypeToken.getGenericType(method.getGenericReturnType(), serviceType);
                Class rtc = returnType;
                if (rtc == void.class) {
                    rtc = RetResult.class;
                    grt = TYPE_RETRESULT_STRING;
                } else if (CompletionStage.class.isAssignableFrom(returnType)) {
                    ParameterizedType ptgrt = (ParameterizedType) grt;
                    grt = ptgrt.getActualTypeArguments()[0];
                    rtc = TypeToken.typeToClass(grt);
                    // 应该不会发生吧?
                    if (rtc == null)
                        rtc = Object.class;
                } else if (Flows.maybePublisherClass(returnType)) {
                    java.lang.reflect.Type grt0 = Flows.maybePublisherSubType(grt);
                    if (grt0 != null)
                        grt = grt0;
                }
                if (grt != rtc) {
                    String refid = typeRefs.get(grt);
                    if (refid == null) {
                        refid = "_typeref_" + typeRefs.size();
                        typeRefs.put(grt, refid);
                    }
                }
            }
        }
        for (Map.Entry<java.lang.reflect.Type, String> en : typeRefs.entrySet()) {
            Field refField = newClazz.getDeclaredField(en.getValue());
            refField.setAccessible(true);
            refField.set(obj, en.getKey());
        }
        for (Map.Entry<String, org.redkale.util.Attribute> en : restAttributes.entrySet()) {
            Field attrField = newClazz.getDeclaredField(en.getKey());
            attrField.setAccessible(true);
            attrField.set(obj, en.getValue());
        }
        for (Map.Entry<String, java.lang.reflect.Type> en : bodyTypes.entrySet()) {
            Field genField = newClazz.getDeclaredField(en.getKey());
            genField.setAccessible(true);
            genField.set(obj, en.getValue());
        }
        for (int i = 0; i < restConverts.size(); i++) {
            Field genField = newClazz.getDeclaredField(REST_CONVERT_FIELD_PREFIX + (i + 1));
            genField.setAccessible(true);
            Object[] rc = restConverts.get(i);
            genField.set(obj, createJsonConvert((RestConvert[]) rc[0], (RestConvertCoder[]) rc[1]));
        }
        Field typesfield = newClazz.getDeclaredField(REST_PARAMTYPES_FIELD_NAME);
        typesfield.setAccessible(true);
        java.lang.reflect.Type[][] paramtypeArray = new java.lang.reflect.Type[paramTypes.size()][];
        paramtypeArray = paramTypes.toArray(paramtypeArray);
        typesfield.set(obj, paramtypeArray);
        Field retfield = newClazz.getDeclaredField(REST_RETURNTYPES_FIELD_NAME);
        retfield.setAccessible(true);
        java.lang.reflect.Type[] rettypeArray = new java.lang.reflect.Type[retvalTypes.size()];
        rettypeArray = retvalTypes.toArray(rettypeArray);
        retfield.set(obj, rettypeArray);
        Field tostringfield = newClazz.getDeclaredField(REST_TOSTRINGOBJ_FIELD_NAME);
        tostringfield.setAccessible(true);
        java.util.function.Supplier<String> sSupplier = () -> JsonConvert.root().convertTo(classMap);
        tostringfield.set(obj, sSupplier);
        Method restactMethod = newClazz.getDeclaredMethod("_createRestActionEntry");
        restactMethod.setAccessible(true);
        Field tmpentrysfield = HttpServlet.class.getDeclaredField("_actionmap");
        tmpentrysfield.setAccessible(true);
        HashMap<String, HttpServlet.ActionEntry> innerEntryMap = (HashMap) restactMethod.invoke(obj);
        for (Map.Entry<String, HttpServlet.ActionEntry> en : innerEntryMap.entrySet()) {
            Method m = mappingurlToMethod.get(en.getKey());
            if (m != null)
                en.getValue().annotations = HttpServlet.ActionEntry.annotations(m);
        }
        tmpentrysfield.set(obj, innerEntryMap);
        return obj;
    } catch (ClassNotFoundException e) {
    } catch (Throwable e) {
        e.printStackTrace();
    }
    // ------------------------------------------------------------------------------
    final String defmodulename = getWebModuleNameLowerCase(serviceType);
    final String bigmodulename = getWebModuleName(serviceType);
    final String catalog = controller == null ? "" : controller.catalog();
    if (!checkName(catalog))
        throw new RuntimeException(serviceType.getName() + " have illegal " + RestService.class.getSimpleName() + ".catalog, only 0-9 a-z A-Z _ cannot begin 0-9");
    if (!checkName(defmodulename))
        throw new RuntimeException(serviceType.getName() + " have illegal " + RestService.class.getSimpleName() + ".value, only 0-9 a-z A-Z _ cannot begin 0-9");
    ClassWriter cw = new ClassWriter(COMPUTE_FRAMES);
    FieldVisitor fv;
    MethodDebugVisitor mv;
    AnnotationVisitor av0;
    final List<MappingEntry> entrys = new ArrayList<>();
    final Map<String, org.redkale.util.Attribute> restAttributes = new LinkedHashMap<>();
    final Map<String, Object> classMap = new LinkedHashMap<>();
    final Map<java.lang.reflect.Type, String> typeRefs = new LinkedHashMap<>();
    final List<java.lang.reflect.Type[]> paramTypes = new ArrayList<>();
    final List<java.lang.reflect.Type> retvalTypes = new ArrayList<>();
    final Map<String, java.lang.reflect.Type> bodyTypes = new HashMap<>();
    final List<Object[]> restConverts = new ArrayList<>();
    final Map<String, Method> mappingurlToMethod = new HashMap<>();
    cw.visit(V11, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, newDynName, null, supDynName, null);
    {
        // RestDynSourceType
        av0 = cw.visitAnnotation(Type.getDescriptor(RestDynSourceType.class), true);
        av0.visit("value", Type.getType(Type.getDescriptor(serviceType)));
        av0.visitEnd();
    }
    boolean dynsimple = true;
    // 获取所有可以转换成HttpMapping的方法
    int methodidex = 0;
    final MessageMultiConsumer mmc = serviceType.getAnnotation(MessageMultiConsumer.class);
    if (mmc != null && (mmc.module() == null || mmc.module().isEmpty())) {
        throw new RuntimeException("@" + MessageMultiConsumer.class.getSimpleName() + ".module can not empty in " + serviceType.getName());
    }
    if (mmc != null && !checkName2(mmc.module())) {
        throw new RuntimeException(serviceType.getName() + " have illegal " + MessageMultiConsumer.class.getSimpleName() + ".module, only 0-9 a-z A-Z _ - . cannot begin 0-9");
    }
    if (mmc != null) {
        MethodDebugVisitor.visitAnnotation(cw.visitAnnotation(Type.getDescriptor(mmc.annotationType()), true), mmc);
    }
    final Method[] allMethods = serviceType.getMethods();
    Arrays.sort(allMethods, (m1, m2) -> {
        // 必须排序,否则paramTypes顺序容易乱
        int s = m1.getName().compareTo(m2.getName());
        if (s != 0)
            return s;
        s = Arrays.toString(m1.getParameterTypes()).compareTo(Arrays.toString(m2.getParameterTypes()));
        return s;
    });
    for (final Method method : allMethods) {
        if (Modifier.isStatic(method.getModifiers()))
            continue;
        if (method.isSynthetic())
            continue;
        if (EXCLUDERMETHODS.contains(method.getName()))
            continue;
        if (method.getParameterCount() == 1 && method.getParameterTypes()[0] == AnyValue.class) {
            if ("init".equals(method.getName()))
                continue;
            if ("stop".equals(method.getName()))
                continue;
            if ("destroy".equals(method.getName()))
                continue;
        }
        if (controller == null)
            continue;
        RestMapping[] mappings = method.getAnnotationsByType(RestMapping.class);
        if (!controller.automapping() && mappings.length < 1)
            continue;
        boolean ignore = false;
        for (RestMapping mapping : mappings) {
            if (mapping.ignore()) {
                ignore = true;
                break;
            }
        }
        if (ignore)
            continue;
        Class[] extypes = method.getExceptionTypes();
        if (extypes.length > 0) {
            for (Class exp : extypes) {
                if (!RuntimeException.class.isAssignableFrom(exp) && !IOException.class.isAssignableFrom(exp)) {
                    throw new RuntimeException("@" + RestMapping.class.getSimpleName() + " only for method(" + method + ") with throws IOException");
                }
            }
        }
        if (mmc != null && method.getReturnType() != void.class) {
            throw new RuntimeException("@" + RestMapping.class.getSimpleName() + " only for method(" + method + ") with return void by @" + MessageMultiConsumer.class.getSimpleName() + " Service");
        }
        paramTypes.add(TypeToken.getGenericType(method.getGenericParameterTypes(), serviceType));
        retvalTypes.add(formatRestReturnType(method, serviceType));
        if (mappings.length == 0) {
            // 没有Mapping,设置一个默认值
            MappingEntry entry = new MappingEntry(serrpconly, methodidex, null, bigmodulename, method);
            if (entrys.contains(entry))
                throw new RuntimeException(serviceType.getName() + " on " + method.getName() + " 's mapping(" + entry.name + ") is repeat");
            entrys.add(entry);
        } else {
            for (RestMapping mapping : mappings) {
                MappingEntry entry = new MappingEntry(serrpconly, methodidex, mapping, defmodulename, method);
                if (entrys.contains(entry))
                    throw new RuntimeException(serviceType.getName() + " on " + method.getName() + " 's mapping(" + entry.name + ") is repeat");
                entrys.add(entry);
            }
        }
        methodidex++;
    }
    // 没有可HttpMapping的方法
    if (entrys.isEmpty())
        return null;
    Collections.sort(entrys);
    RestClassLoader newLoader = new RestClassLoader(loader);
    final int moduleid = controller == null ? 0 : controller.moduleid();
    {
        // 注入 @WebServlet 注解
        String urlpath = "";
        boolean repair = controller == null ? true : controller.repair();
        String comment = controller == null ? "" : controller.comment();
        av0 = cw.visitAnnotation(webServletDesc, true);
        {
            AnnotationVisitor av1 = av0.visitArray("value");
            boolean pound = false;
            for (MappingEntry entry : entrys) {
                if (entry.existsPound) {
                    pound = true;
                    break;
                }
            }
            if (defmodulename.isEmpty() || (!pound && entrys.size() <= 2)) {
                for (MappingEntry entry : entrys) {
                    String suburl = (catalog.isEmpty() ? "/" : ("/" + catalog + "/")) + (defmodulename.isEmpty() ? "" : (defmodulename + "/")) + entry.name;
                    if ("//".equals(suburl)) {
                        suburl = "/";
                    } else if (suburl.length() > 2 && suburl.endsWith("/")) {
                        suburl += "*";
                    }
                    urlpath += "," + suburl;
                    av1.visit(null, suburl);
                }
                if (urlpath.length() > 0)
                    urlpath = urlpath.substring(1);
            } else {
                urlpath = (catalog.isEmpty() ? "/" : ("/" + catalog + "/")) + defmodulename + "/*";
                av1.visit(null, urlpath);
            }
            av1.visitEnd();
        }
        av0.visit("name", defmodulename);
        av0.visit("moduleid", moduleid);
        av0.visit("repair", repair);
        av0.visit("comment", comment);
        av0.visitEnd();
        classMap.put("type", serviceType.getName());
        classMap.put("url", urlpath);
        classMap.put("moduleid", moduleid);
        classMap.put("repair", repair);
    // classMap.put("comment", comment); //不显示太多信息
    }
    {
        // 内部类
        cw.visitInnerClass(actionEntryName, httpServletName, HttpServlet.ActionEntry.class.getSimpleName(), ACC_PROTECTED + ACC_FINAL + ACC_STATIC);
        for (final MappingEntry entry : entrys) {
            cw.visitInnerClass(newDynName + "$" + entry.newActionClassName, newDynName, entry.newActionClassName, ACC_PRIVATE + ACC_STATIC);
        }
    }
    {
        // 注入 @Resource  private XXXService _service;
        fv = cw.visitField(ACC_PRIVATE, REST_SERVICE_FIELD_NAME, serviceDesc, null, null);
        av0 = fv.visitAnnotation(resDesc, true);
        av0.visit("name", "");
        av0.visitEnd();
        fv.visitEnd();
    }
    {
        // 注入 @Resource(name = "APP_HOME")  private File _redkale_home;
        fv = cw.visitField(ACC_PRIVATE, "_redkale_home", Type.getDescriptor(File.class), null, null);
        av0 = fv.visitAnnotation(resDesc, true);
        av0.visit("name", "APP_HOME");
        av0.visitEnd();
        fv.visitEnd();
    }
    {
        // _servicemap字段 Map<String, XXXService>
        fv = cw.visitField(ACC_PRIVATE, REST_SERVICEMAP_FIELD_NAME, "Ljava/util/Map;", "Ljava/util/Map<Ljava/lang/String;" + serviceDesc + ">;", null);
        fv.visitEnd();
    }
    {
        // _redkale_tostringsupplier字段 Supplier<String>
        fv = cw.visitField(ACC_PRIVATE, REST_TOSTRINGOBJ_FIELD_NAME, "Ljava/util/function/Supplier;", "Ljava/util/function/Supplier<Ljava/lang/String;>;", null);
        fv.visitEnd();
    }
    {
        // 构造函数
        mv = new MethodDebugVisitor(cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null));
        // mv.setDebug(true);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitMethodInsn(INVOKESPECIAL, supDynName, "<init>", "()V", false);
        mv.visitInsn(RETURN);
        mv.visitMaxs(1, 1);
        mv.visitEnd();
    }
    // 将每个Service可转换的方法生成HttpServlet对应的HttpMapping方法
    boolean namePresent = false;
    try {
        Method m0 = null;
        for (final MappingEntry entry : entrys) {
            if (entry.mappingMethod.getParameterCount() > 0) {
                m0 = entry.mappingMethod;
                break;
            }
        }
        namePresent = m0 == null ? true : m0.getParameters()[0].isNamePresent();
    } catch (Exception e) {
    }
    final Map<String, List<String>> asmParamMap = namePresent ? null : MethodParamClassVisitor.getMethodParamNames(new HashMap<>(), serviceType);
    Map<String, byte[]> innerClassBytesMap = new LinkedHashMap<>();
    for (final MappingEntry entry : entrys) {
        RestUploadFile mupload = null;
        Class muploadType = null;
        final Method method = entry.mappingMethod;
        final Class returnType = method.getReturnType();
        final java.lang.reflect.Type retvalType = formatRestReturnType(method, serviceType);
        final String methodDesc = Type.getMethodDescriptor(method);
        final Parameter[] params = method.getParameters();
        final RestConvert[] rcs = method.getAnnotationsByType(RestConvert.class);
        final RestConvertCoder[] rcc = method.getAnnotationsByType(RestConvertCoder.class);
        if ((rcs != null && rcs.length > 0) || (rcc != null && rcc.length > 0)) {
            restConverts.add(new Object[] { rcs, rcc });
        }
        mv = new MethodDebugVisitor(cw.visitMethod(ACC_PUBLIC, entry.newMethodName, "(" + reqDesc + respDesc + ")V", null, new String[] { "java/io/IOException" }));
        // mv.setDebug(true);
        mv.debugLine();
        mv.visitVarInsn(ALOAD, 0);
        mv.visitFieldInsn(GETFIELD, newDynName, REST_SERVICEMAP_FIELD_NAME, "Ljava/util/Map;");
        Label lmapif = new Label();
        mv.visitJumpInsn(IFNONNULL, lmapif);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitFieldInsn(GETFIELD, newDynName, REST_SERVICE_FIELD_NAME, serviceDesc);
        Label lserif = new Label();
        mv.visitJumpInsn(GOTO, lserif);
        mv.visitLabel(lmapif);
        mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitFieldInsn(GETFIELD, newDynName, REST_SERVICEMAP_FIELD_NAME, "Ljava/util/Map;");
        mv.visitVarInsn(ALOAD, 1);
        mv.visitLdcInsn(REST_HEADER_RESOURCE_NAME);
        mv.visitLdcInsn("");
        mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getHeader", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", false);
        mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Map", "get", "(Ljava/lang/Object;)Ljava/lang/Object;", true);
        mv.visitTypeInsn(CHECKCAST, serviceTypeInternalName);
        mv.visitLabel(lserif);
        mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] { serviceTypeInternalName });
        mv.visitVarInsn(ASTORE, 3);
        final int maxStack = 3 + params.length;
        List<int[]> varInsns = new ArrayList<>();
        int maxLocals = 4;
        List<String> asmParamNames = asmParamMap == null ? null : asmParamMap.get(method.getName() + ":" + Type.getMethodDescriptor(method));
        // 删掉空元素
        if (asmParamNames != null)
            while (asmParamNames.remove(" ")) ;
        List<Object[]> paramlist = new ArrayList<>();
        // 解析方法中的每个参数
        for (int i = 0; i < params.length; i++) {
            final Parameter param = params[i];
            final Class ptype = param.getType();
            String n = null;
            String comment = "";
            boolean required = true;
            int radix = 10;
            RestHeader annhead = param.getAnnotation(RestHeader.class);
            if (annhead != null) {
                if (ptype != String.class && ptype != InetSocketAddress.class)
                    throw new RuntimeException("@RestHeader must on String or InetSocketAddress Parameter in " + method);
                n = annhead.name();
                radix = annhead.radix();
                comment = annhead.comment();
                if (n.isEmpty())
                    throw new RuntimeException("@RestHeader.value is illegal in " + method);
            }
            RestCookie anncookie = param.getAnnotation(RestCookie.class);
            if (anncookie != null) {
                if (annhead != null)
                    throw new RuntimeException("@RestCookie and @RestHeader cannot on the same Parameter in " + method);
                if (ptype != String.class)
                    throw new RuntimeException("@RestCookie must on String Parameter in " + method);
                n = anncookie.name();
                radix = anncookie.radix();
                comment = anncookie.comment();
                if (n.isEmpty())
                    throw new RuntimeException("@RestCookie.value is illegal in " + method);
            }
            RestSessionid annsid = param.getAnnotation(RestSessionid.class);
            if (annsid != null) {
                if (annhead != null)
                    throw new RuntimeException("@RestSessionid and @RestHeader cannot on the same Parameter in " + method);
                if (anncookie != null)
                    throw new RuntimeException("@RestSessionid and @RestCookie cannot on the same Parameter in " + method);
                if (ptype != String.class)
                    throw new RuntimeException("@RestSessionid must on String Parameter in " + method);
            }
            RestAddress annaddr = param.getAnnotation(RestAddress.class);
            if (annaddr != null) {
                if (annhead != null)
                    throw new RuntimeException("@RestAddress and @RestHeader cannot on the same Parameter in " + method);
                if (anncookie != null)
                    throw new RuntimeException("@RestAddress and @RestCookie cannot on the same Parameter in " + method);
                if (annsid != null)
                    throw new RuntimeException("@RestAddress and @RestSessionid cannot on the same Parameter in " + method);
                if (ptype != String.class)
                    throw new RuntimeException("@RestAddress must on String Parameter in " + method);
                comment = annaddr.comment();
            }
            RestBody annbody = param.getAnnotation(RestBody.class);
            if (annbody != null) {
                if (annhead != null)
                    throw new RuntimeException("@RestBody and @RestHeader cannot on the same Parameter in " + method);
                if (anncookie != null)
                    throw new RuntimeException("@RestBody and @RestCookie cannot on the same Parameter in " + method);
                if (annsid != null)
                    throw new RuntimeException("@RestBody and @RestSessionid cannot on the same Parameter in " + method);
                if (annaddr != null)
                    throw new RuntimeException("@RestBody and @RestAddress cannot on the same Parameter in " + method);
                if (ptype.isPrimitive())
                    throw new RuntimeException("@RestBody cannot on primitive type Parameter in " + method);
                comment = annbody.comment();
            }
            RestUploadFile annfile = param.getAnnotation(RestUploadFile.class);
            if (annfile != null) {
                if (mupload != null)
                    throw new RuntimeException("@RestUploadFile repeat in " + method);
                mupload = annfile;
                muploadType = ptype;
                if (annhead != null)
                    throw new RuntimeException("@RestUploadFile and @RestHeader cannot on the same Parameter in " + method);
                if (anncookie != null)
                    throw new RuntimeException("@RestUploadFile and @RestCookie cannot on the same Parameter in " + method);
                if (annsid != null)
                    throw new RuntimeException("@RestUploadFile and @RestSessionid cannot on the same Parameter in " + method);
                if (annaddr != null)
                    throw new RuntimeException("@RestUploadFile and @RestAddress cannot on the same Parameter in " + method);
                if (annbody != null)
                    throw new RuntimeException("@RestUploadFile and @RestBody cannot on the same Parameter in " + method);
                if (ptype != byte[].class && ptype != File.class && ptype != File[].class)
                    throw new RuntimeException("@RestUploadFile must on byte[] or File or File[] Parameter in " + method);
                comment = annfile.comment();
            }
            RestURI annuri = param.getAnnotation(RestURI.class);
            if (annuri != null) {
                if (annhead != null)
                    throw new RuntimeException("@RestURI and @RestHeader cannot on the same Parameter in " + method);
                if (anncookie != null)
                    throw new RuntimeException("@RestURI and @RestCookie cannot on the same Parameter in " + method);
                if (annsid != null)
                    throw new RuntimeException("@RestURI and @RestSessionid cannot on the same Parameter in " + method);
                if (annaddr != null)
                    throw new RuntimeException("@RestURI and @RestAddress cannot on the same Parameter in " + method);
                if (annbody != null)
                    throw new RuntimeException("@RestURI and @RestBody cannot on the same Parameter in " + method);
                if (annfile != null)
                    throw new RuntimeException("@RestURI and @RestUploadFile cannot on the same Parameter in " + method);
                if (ptype != String.class)
                    throw new RuntimeException("@RestURI must on String Parameter in " + method);
                comment = annuri.comment();
            }
            RestUserid userid = param.getAnnotation(RestUserid.class);
            if (userid != null) {
                if (annhead != null)
                    throw new RuntimeException("@RestUserid and @RestHeader cannot on the same Parameter in " + method);
                if (anncookie != null)
                    throw new RuntimeException("@RestUserid and @RestCookie cannot on the same Parameter in " + method);
                if (annsid != null)
                    throw new RuntimeException("@RestUserid and @RestSessionid cannot on the same Parameter in " + method);
                if (annaddr != null)
                    throw new RuntimeException("@RestUserid and @RestAddress cannot on the same Parameter in " + method);
                if (annbody != null)
                    throw new RuntimeException("@RestUserid and @RestBody cannot on the same Parameter in " + method);
                if (annfile != null)
                    throw new RuntimeException("@RestUserid and @RestUploadFile cannot on the same Parameter in " + method);
                if (!ptype.isPrimitive() && !java.io.Serializable.class.isAssignableFrom(ptype))
                    throw new RuntimeException("@RestUserid must on java.io.Serializable Parameter in " + method);
                comment = "";
            }
            RestHeaders annheaders = param.getAnnotation(RestHeaders.class);
            if (annheaders != null) {
                if (annhead != null)
                    throw new RuntimeException("@RestHeaders and @RestHeader cannot on the same Parameter in " + method);
                if (anncookie != null)
                    throw new RuntimeException("@RestHeaders and @RestCookie cannot on the same Parameter in " + method);
                if (annsid != null)
                    throw new RuntimeException("@RestHeaders and @RestSessionid cannot on the same Parameter in " + method);
                if (annaddr != null)
                    throw new RuntimeException("@RestHeaders and @RestAddress cannot on the same Parameter in " + method);
                if (annbody != null)
                    throw new RuntimeException("@RestHeaders and @RestBody cannot on the same Parameter in " + method);
                if (annfile != null)
                    throw new RuntimeException("@RestHeaders and @RestUploadFile cannot on the same Parameter in " + method);
                if (userid != null)
                    throw new RuntimeException("@RestHeaders and @RestUserid cannot on the same Parameter in " + method);
                if (!TYPE_MAP_STRING_STRING.equals(param.getParameterizedType()))
                    throw new RuntimeException("@RestHeaders must on Map<String, String> Parameter in " + method);
                comment = "";
            }
            RestParams annparams = param.getAnnotation(RestParams.class);
            if (annparams != null) {
                if (annhead != null)
                    throw new RuntimeException("@RestParams and @RestHeader cannot on the same Parameter in " + method);
                if (anncookie != null)
                    throw new RuntimeException("@RestParams and @RestCookie cannot on the same Parameter in " + method);
                if (annsid != null)
                    throw new RuntimeException("@RestParams and @RestSessionid cannot on the same Parameter in " + method);
                if (annaddr != null)
                    throw new RuntimeException("@RestParams and @RestAddress cannot on the same Parameter in " + method);
                if (annbody != null)
                    throw new RuntimeException("@RestParams and @RestBody cannot on the same Parameter in " + method);
                if (annfile != null)
                    throw new RuntimeException("@RestParams and @RestUploadFile cannot on the same Parameter in " + method);
                if (userid != null)
                    throw new RuntimeException("@RestParams and @RestUserid cannot on the same Parameter in " + method);
                if (annheaders != null)
                    throw new RuntimeException("@RestParams and @RestHeaders cannot on the same Parameter in " + method);
                if (!TYPE_MAP_STRING_STRING.equals(param.getParameterizedType()))
                    throw new RuntimeException("@RestParams must on Map<String, String> Parameter in " + method);
                comment = "";
            }
            RestParam annpara = param.getAnnotation(RestParam.class);
            if (annpara != null)
                radix = annpara.radix();
            if (annpara != null)
                comment = annpara.comment();
            if (annpara != null)
                required = annpara.required();
            if (n == null)
                n = (annpara == null || annpara.name().isEmpty()) ? null : annpara.name();
            // 用户类型特殊处理
            if (n == null && ptype == userType)
                n = "&";
            if (n == null && asmParamNames != null && asmParamNames.size() > i)
                n = asmParamNames.get(i);
            if (n == null) {
                if (param.isNamePresent()) {
                    n = param.getName();
                } else if (ptype == Flipper.class) {
                    n = "flipper";
                } else {
                    throw new RuntimeException("Parameter " + param.getName() + " not found name by @RestParam  in " + method);
                }
            }
            if (annhead == null && anncookie == null && annsid == null && annaddr == null && annbody == null && annfile == null && !ptype.isPrimitive() && ptype != String.class && ptype != Flipper.class && !CompletionHandler.class.isAssignableFrom(ptype) && !ptype.getName().startsWith("java") && n.charAt(0) != '#' && !"&".equals(n)) {
                // 判断Json对象是否包含@RestUploadFile
                Class loop = ptype;
                do {
                    // 接口时getSuperclass可能会得到null
                    if (loop == null || loop.isInterface())
                        break;
                    for (Field field : loop.getDeclaredFields()) {
                        if (Modifier.isStatic(field.getModifiers()))
                            continue;
                        if (Modifier.isFinal(field.getModifiers()))
                            continue;
                        RestUploadFile ruf = field.getAnnotation(RestUploadFile.class);
                        if (ruf == null)
                            continue;
                        if (mupload != null)
                            throw new RuntimeException("@RestUploadFile repeat in " + method + " or field " + field);
                        mupload = ruf;
                        muploadType = field.getType();
                    }
                } while ((loop = loop.getSuperclass()) != Object.class);
            }
            java.lang.reflect.Type paramtype = TypeToken.getGenericType(param.getParameterizedType(), serviceType);
            paramlist.add(new Object[] { param, n, ptype, radix, comment, required, annpara, annsid, annaddr, annhead, anncookie, annbody, annfile, annuri, userid, annheaders, annparams, paramtype });
        }
        Map<String, Object> mappingMap = new LinkedHashMap<>();
        {
            // 设置 Annotation
            // 设置 HttpMapping
            boolean reqpath = false;
            for (Object[] ps : paramlist) {
                if ("#".equals((String) ps[1])) {
                    reqpath = true;
                    break;
                }
            }
            if (method.getAnnotation(Deprecated.class) != null) {
                av0 = mv.visitAnnotation(Type.getDescriptor(Deprecated.class), true);
                av0.visitEnd();
            }
            av0 = mv.visitAnnotation(mappingDesc, true);
            String url = (catalog.isEmpty() ? "/" : ("/" + catalog + "/")) + (defmodulename.isEmpty() ? "" : (defmodulename + "/")) + entry.name + (reqpath ? "/" : "");
            if ("//".equals(url))
                url = "/";
            av0.visit("url", url);
            av0.visit("name", (defmodulename.isEmpty() ? "" : (defmodulename + "_")) + entry.name);
            av0.visit("example", entry.example);
            av0.visit("rpconly", entry.rpconly);
            av0.visit("auth", entry.auth);
            av0.visit("cacheseconds", entry.cacheseconds);
            av0.visit("actionid", entry.actionid);
            av0.visit("comment", entry.comment);
            AnnotationVisitor av1 = av0.visitArray("methods");
            for (String m : entry.methods) {
                av1.visit(null, m);
            }
            av1.visitEnd();
            java.lang.reflect.Type grt = TypeToken.getGenericType(method.getGenericReturnType(), serviceType);
            Class rtc = returnType;
            if (rtc == void.class) {
                rtc = RetResult.class;
                grt = TYPE_RETRESULT_STRING;
            } else if (CompletionStage.class.isAssignableFrom(returnType)) {
                ParameterizedType ptgrt = (ParameterizedType) grt;
                grt = ptgrt.getActualTypeArguments()[0];
                rtc = TypeToken.typeToClass(grt);
                // 应该不会发生吧?
                if (rtc == null)
                    rtc = Object.class;
            }
            av0.visit("result", Type.getType(Type.getDescriptor(rtc)));
            if (grt != rtc) {
                String refid = typeRefs.get(grt);
                if (refid == null) {
                    refid = "_typeref_" + typeRefs.size();
                    typeRefs.put(grt, refid);
                }
                av0.visit("resultref", refid);
            }
            av0.visitEnd();
            mappingMap.put("url", url);
            mappingMap.put("rpconly", entry.rpconly);
            mappingMap.put("auth", entry.auth);
            mappingMap.put("cacheseconds", entry.cacheseconds);
            mappingMap.put("actionid", entry.actionid);
            mappingMap.put("comment", entry.comment);
            mappingMap.put("methods", entry.methods);
            mappingMap.put("result", grt == returnType ? returnType.getName() : String.valueOf(grt));
            entry.mappingurl = url;
        }
        {
            // 设置 Annotation
            av0 = mv.visitAnnotation(httpParamsDesc, true);
            AnnotationVisitor av1 = av0.visitArray("value");
            // 设置 HttpParam
            for (Object[] ps : paramlist) {
                // {param, n, ptype, radix, comment, required, annpara, annsid, annaddr, annhead, anncookie, annbody, annfile, annuri, annuserid, annheaders, annparams, paramtype}
                String n = ps[1].toString();
                // 是否取userid
                final boolean isuserid = ((RestUserid) ps[14]) != null;
                // @RestUserid 不需要生成 @HttpParam
                if (n.indexOf('&') >= 0 || isuserid)
                    continue;
                // @RestAddress 不需要生成 @HttpParam
                if (((RestAddress) ps[8]) != null)
                    continue;
                // 是否取getHeader 而不是 getParameter
                final boolean ishead = ((RestHeader) ps[9]) != null;
                // 是否取getCookie
                final boolean iscookie = ((RestCookie) ps[10]) != null;
                // 是否取getBody
                final boolean isbody = ((RestBody) ps[11]) != null;
                AnnotationVisitor av2 = av1.visitAnnotation(null, httpParamDesc);
                av2.visit("name", (String) ps[1]);
                if (((Parameter) ps[0]).getAnnotation(Deprecated.class) != null) {
                    av2.visit("deprecated", true);
                }
                av2.visit("type", Type.getType(Type.getDescriptor((Class) ps[2])));
                java.lang.reflect.Type pgtype = TypeToken.getGenericType(((Parameter) ps[0]).getParameterizedType(), serviceType);
                if (pgtype != (Class) ps[2]) {
                    String refid = typeRefs.get(pgtype);
                    if (refid == null) {
                        refid = "_typeref_" + typeRefs.size();
                        typeRefs.put(pgtype, refid);
                    }
                    av2.visit("typeref", refid);
                }
                av2.visit("radix", (Integer) ps[3]);
                if (ishead) {
                    av2.visitEnum("style", sourcetypeDesc, HttpParam.HttpParameterStyle.HEADER.name());
                    av2.visit("example", ((RestHeader) ps[9]).example());
                } else if (iscookie) {
                    av2.visitEnum("style", sourcetypeDesc, HttpParam.HttpParameterStyle.COOKIE.name());
                    av2.visit("example", ((RestCookie) ps[10]).example());
                } else if (isbody) {
                    av2.visitEnum("style", sourcetypeDesc, HttpParam.HttpParameterStyle.BODY.name());
                    av2.visit("example", ((RestBody) ps[11]).example());
                } else if (ps[6] != null) {
                    av2.visitEnum("style", sourcetypeDesc, HttpParam.HttpParameterStyle.QUERY.name());
                    av2.visit("example", ((RestParam) ps[6]).example());
                }
                av2.visit("comment", (String) ps[4]);
                av2.visit("required", (Boolean) ps[5]);
                av2.visitEnd();
            }
            av1.visitEnd();
            av0.visitEnd();
        }
        int uploadLocal = 0;
        if (mupload != null) {
            // 存在文件上传
            if (muploadType == byte[].class) {
                mv.visitVarInsn(ALOAD, 1);
                mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getMultiContext", "()" + multiContextDesc, false);
                mv.visitLdcInsn(mupload.maxLength());
                mv.visitLdcInsn(mupload.fileNameReg());
                mv.visitLdcInsn(mupload.contentTypeReg());
                mv.visitMethodInsn(INVOKEVIRTUAL, multiContextName, "partsFirstBytes", "(JLjava/lang/String;Ljava/lang/String;)[B", false);
                mv.visitVarInsn(ASTORE, maxLocals);
                uploadLocal = maxLocals;
            } else if (muploadType == File.class) {
                mv.visitVarInsn(ALOAD, 1);
                mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getMultiContext", "()" + multiContextDesc, false);
                mv.visitVarInsn(ALOAD, 0);
                mv.visitFieldInsn(GETFIELD, newDynName, "_redkale_home", "Ljava/io/File;");
                mv.visitLdcInsn(mupload.maxLength());
                mv.visitLdcInsn(mupload.fileNameReg());
                mv.visitLdcInsn(mupload.contentTypeReg());
                mv.visitMethodInsn(INVOKEVIRTUAL, multiContextName, "partsFirstFile", "(Ljava/io/File;JLjava/lang/String;Ljava/lang/String;)Ljava/io/File;", false);
                mv.visitVarInsn(ASTORE, maxLocals);
                uploadLocal = maxLocals;
            } else if (muploadType == File[].class) {
                // File[]
                mv.visitVarInsn(ALOAD, 1);
                mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getMultiContext", "()" + multiContextDesc, false);
                mv.visitVarInsn(ALOAD, 0);
                mv.visitFieldInsn(GETFIELD, newDynName, "_redkale_home", "Ljava/io/File;");
                mv.visitLdcInsn(mupload.maxLength());
                mv.visitLdcInsn(mupload.fileNameReg());
                mv.visitLdcInsn(mupload.contentTypeReg());
                mv.visitMethodInsn(INVOKEVIRTUAL, multiContextName, "partsFiles", "(Ljava/io/File;JLjava/lang/String;Ljava/lang/String;)[Ljava/io/File;", false);
                mv.visitVarInsn(ASTORE, maxLocals);
                uploadLocal = maxLocals;
            }
            maxLocals++;
        }
        List<Map<String, Object>> paramMaps = new ArrayList<>();
        // 获取每个参数的值
        boolean hasAsyncHandler = false;
        for (Object[] ps : paramlist) {
            Map<String, Object> paramMap = new LinkedHashMap<>();
            // 参数类型
            final Parameter param = (Parameter) ps[0];
            // 参数名
            String pname = (String) ps[1];
            // 参数类型
            Class ptype = (Class) ps[2];
            int radix = (Integer) ps[3];
            String comment = (String) ps[4];
            boolean required = (Boolean) ps[5];
            RestParam annpara = (RestParam) ps[6];
            RestSessionid annsid = (RestSessionid) ps[7];
            RestAddress annaddr = (RestAddress) ps[8];
            RestHeader annhead = (RestHeader) ps[9];
            RestCookie anncookie = (RestCookie) ps[10];
            RestBody annbody = (RestBody) ps[11];
            RestUploadFile annfile = (RestUploadFile) ps[12];
            RestURI annuri = (RestURI) ps[13];
            RestUserid userid = (RestUserid) ps[14];
            RestHeaders annheaders = (RestHeaders) ps[15];
            RestParams annparams = (RestParams) ps[16];
            java.lang.reflect.Type pgentype = (java.lang.reflect.Type) ps[17];
            if (dynsimple && (annsid != null || annaddr != null || annhead != null || anncookie != null || annfile != null || annheaders != null))
                dynsimple = false;
            // 是否取getHeader 而不是 getParameter
            final boolean ishead = annhead != null;
            // 是否取getCookie
            final boolean iscookie = anncookie != null;
            paramMap.put("name", pname);
            paramMap.put("type", ptype.getName());
            if (CompletionHandler.class.isAssignableFrom(ptype)) {
                // HttpResponse.createAsyncHandler() or HttpResponse.createAsyncHandler(Class)
                if (ptype == CompletionHandler.class) {
                    mv.visitVarInsn(ALOAD, 2);
                    mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "createAsyncHandler", "()Ljava/nio/channels/CompletionHandler;", false);
                    mv.visitVarInsn(ASTORE, maxLocals);
                    varInsns.add(new int[] { ALOAD, maxLocals });
                } else {
                    mv.visitVarInsn(ALOAD, 3);
                    mv.visitVarInsn(ALOAD, 2);
                    mv.visitLdcInsn(Type.getType(Type.getDescriptor(ptype)));
                    mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "createAsyncHandler", "(Ljava/lang/Class;)Ljava/nio/channels/CompletionHandler;", false);
                    mv.visitTypeInsn(CHECKCAST, ptype.getName().replace('.', '/'));
                    mv.visitVarInsn(ASTORE, maxLocals);
                    varInsns.add(new int[] { ALOAD, maxLocals });
                }
                hasAsyncHandler = true;
            } else if (annsid != null) {
                // HttpRequest.getSessionid(true|false)
                mv.visitVarInsn(ALOAD, 1);
                mv.visitInsn(annsid.create() ? ICONST_1 : ICONST_0);
                mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getSessionid", "(Z)Ljava/lang/String;", false);
                mv.visitVarInsn(ASTORE, maxLocals);
                varInsns.add(new int[] { ALOAD, maxLocals });
            } else if (annaddr != null) {
                // HttpRequest.getRemoteAddr
                mv.visitVarInsn(ALOAD, 1);
                mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getRemoteAddr", "()Ljava/lang/String;", false);
                mv.visitVarInsn(ASTORE, maxLocals);
                varInsns.add(new int[] { ALOAD, maxLocals });
            } else if (annheaders != null) {
                // HttpRequest.getHeaders
                mv.visitVarInsn(ALOAD, 1);
                mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getHeaders", "()Ljava/util/Map;", false);
                mv.visitVarInsn(ASTORE, maxLocals);
                varInsns.add(new int[] { ALOAD, maxLocals });
            } else if (annparams != null) {
                // HttpRequest.getParameters
                mv.visitVarInsn(ALOAD, 1);
                mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getParameters", "()Ljava/util/Map;", false);
                mv.visitVarInsn(ASTORE, maxLocals);
                varInsns.add(new int[] { ALOAD, maxLocals });
            } else if (annbody != null) {
                // HttpRequest.getBodyUTF8 / HttpRequest.getBody
                if (ptype == String.class) {
                    mv.visitVarInsn(ALOAD, 1);
                    mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getBodyUTF8", "()Ljava/lang/String;", false);
                    mv.visitVarInsn(ASTORE, maxLocals);
                    varInsns.add(new int[] { ALOAD, maxLocals });
                } else if (ptype == byte[].class) {
                    mv.visitVarInsn(ALOAD, 1);
                    mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getBody", "()[B", false);
                    mv.visitVarInsn(ASTORE, maxLocals);
                    varInsns.add(new int[] { ALOAD, maxLocals });
                } else {
                    // JavaBean 转 Json
                    String typefieldname = "_redkale_body_jsontype_" + bodyTypes.size();
                    bodyTypes.put(typefieldname, pgentype);
                    mv.visitVarInsn(ALOAD, 1);
                    mv.visitVarInsn(ALOAD, 0);
                    mv.visitFieldInsn(GETFIELD, newDynName, typefieldname, "Ljava/lang/reflect/Type;");
                    mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getBodyJson", "(Ljava/lang/reflect/Type;)Ljava/lang/Object;", false);
                    mv.visitTypeInsn(CHECKCAST, Type.getInternalName(ptype));
                    mv.visitVarInsn(ASTORE, maxLocals);
                    varInsns.add(new int[] { ALOAD, maxLocals });
                }
            } else if (annfile != null) {
                // MultiContext.partsFirstBytes / HttpRequest.partsFirstFile / HttpRequest.partsFiles
                mv.visitVarInsn(ALOAD, 4);
                mv.visitVarInsn(ASTORE, maxLocals);
                varInsns.add(new int[] { ALOAD, maxLocals });
            } else if (annuri != null) {
                // HttpRequest.getRequestURI
                mv.visitVarInsn(ALOAD, 1);
                mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getRequestURI", "()Ljava/lang/String;", false);
                mv.visitVarInsn(ASTORE, maxLocals);
                varInsns.add(new int[] { ALOAD, maxLocals });
            } else if (userid != null) {
                // HttpRequest.currentUserid
                mv.visitVarInsn(ALOAD, 1);
                if (ptype == int.class) {
                    mv.visitFieldInsn(GETSTATIC, "java/lang/Integer", "TYPE", "Ljava/lang/Class;");
                } else if (ptype == long.class) {
                    mv.visitFieldInsn(GETSTATIC, "java/lang/Long", "TYPE", "Ljava/lang/Class;");
                } else {
                    mv.visitLdcInsn(Type.getType(Type.getInternalName(ptype)));
                }
                mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "currentUserid", "(Ljava/lang/Class;)Ljava/io/Serializable;", false);
                if (ptype == int.class) {
                    mv.visitTypeInsn(CHECKCAST, "java/lang/Integer");
                    mv.visitInsn(ICONST_0);
                    mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false);
                    mv.visitMethodInsn(INVOKESTATIC, restInternalName, "orElse", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", false);
                    mv.visitTypeInsn(CHECKCAST, "java/lang/Integer");
                    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false);
                    mv.visitVarInsn(ISTORE, maxLocals);
                    varInsns.add(new int[] { ILOAD, maxLocals });
                } else if (ptype == long.class) {
                    mv.visitTypeInsn(CHECKCAST, "java/lang/Long");
                    mv.visitInsn(LCONST_0);
                    mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", false);
                    mv.visitMethodInsn(INVOKESTATIC, restInternalName, "orElse", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", false);
                    mv.visitTypeInsn(CHECKCAST, "java/lang/Long");
                    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J", false);
                    mv.visitVarInsn(LSTORE, maxLocals);
                    varInsns.add(new int[] { LLOAD, maxLocals });
                    maxLocals++;
                } else {
                    mv.visitTypeInsn(CHECKCAST, Type.getInternalName(ptype));
                    mv.visitVarInsn(ASTORE, maxLocals);
                    varInsns.add(new int[] { ALOAD, maxLocals });
                }
            } else if ("#".equals(pname)) {
                // 从request.getRequstURI 中取参数
                if (ptype == boolean.class) {
                    mv.visitVarInsn(ALOAD, 1);
                    mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getRequstURILastPath", "()Ljava/lang/String;", false);
                    mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "parseBoolean", "(Ljava/lang/String;)Z", false);
                    mv.visitVarInsn(ISTORE, maxLocals);
                    varInsns.add(new int[] { ILOAD, maxLocals });
                } else if (ptype == byte.class) {
                    mv.visitVarInsn(ALOAD, 1);
                    mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getRequstURILastPath", "()Ljava/lang/String;", false);
                    mv.visitIntInsn(BIPUSH, radix);
                    mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "parseByte", "(Ljava/lang/String;I)B", false);
                    mv.visitVarInsn(ISTORE, maxLocals);
                    varInsns.add(new int[] { ILOAD, maxLocals });
                } else if (ptype == short.class) {
                    mv.visitVarInsn(ALOAD, 1);
                    mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getRequstURILastPath", "()Ljava/lang/String;", false);
                    mv.visitIntInsn(BIPUSH, radix);
                    mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "parseShort", "(Ljava/lang/String;I)S", false);
                    mv.visitVarInsn(ISTORE, maxLocals);
                    varInsns.add(new int[] { ILOAD, maxLocals });
                } else if (ptype == char.class) {
                    mv.visitVarInsn(ALOAD, 1);
                    mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getRequstURILastPath", "()Ljava/lang/String;", false);
                    mv.visitInsn(ICONST_0);
                    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "charAt", "(I)C", false);
                    mv.visitVarInsn(ISTORE, maxLocals);
                    varInsns.add(new int[] { ILOAD, maxLocals });
                } else if (ptype == int.class) {
                    mv.visitVarInsn(ALOAD, 1);
                    mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getRequstURILastPath", "()Ljava/lang/String;", false);
                    mv.visitIntInsn(BIPUSH, radix);
                    mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "parseInt", "(Ljava/lang/String;I)I", false);
                    mv.visitVarInsn(ISTORE, maxLocals);
                    varInsns.add(new int[] { ILOAD, maxLocals });
                } else if (ptype == float.class) {
                    mv.visitVarInsn(ALOAD, 1);
                    mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getRequstURILastPath", "()Ljava/lang/String;", false);
                    mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "parseFloat", "(Ljava/lang/String;)F", false);
                    mv.visitVarInsn(FSTORE, maxLocals);
                    varInsns.add(new int[] { FLOAD, maxLocals });
                } else if (ptype == long.class) {
                    mv.visitVarInsn(ALOAD, 1);
                    mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getRequstURILastPath", "()Ljava/lang/String;", false);
                    mv.visitIntInsn(BIPUSH, radix);
                    mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "parseLong", "(Ljava/lang/String;I)J", false);
                    mv.visitVarInsn(LSTORE, maxLocals);
                    varInsns.add(new int[] { LLOAD, maxLocals });
                    maxLocals++;
                } else if (ptype == double.class) {
                    mv.visitVarInsn(ALOAD, 1);
                    mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getRequstURILastPath", "()Ljava/lang/String;", false);
                    mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "parseDouble", "(Ljava/lang/String;)D", false);
                    mv.visitVarInsn(DSTORE, maxLocals);
                    varInsns.add(new int[] { DLOAD, maxLocals });
                    maxLocals++;
                } else if (ptype == String.class) {
                    mv.visitVarInsn(ALOAD, 1);
                    mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getRequstURILastPath", "()Ljava/lang/String;", false);
                    mv.visitVarInsn(ASTORE, maxLocals);
                    varInsns.add(new int[] { ALOAD, maxLocals });
                } else {
                    throw new RuntimeException(method + " only " + RestParam.class.getSimpleName() + "(#) to Type(primitive class or String)");
                }
            } else if (pname.charAt(0) == '#') {
                // 从request.getRequstURIPath 中去参数
                if (ptype == boolean.class) {
                    mv.visitVarInsn(ALOAD, 1);
                    mv.visitLdcInsn(pname.substring(1));
                    mv.visitLdcInsn("false");
                    mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getRequstURIPath", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", false);
                    mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "parseBoolean", "(Ljava/lang/String;)Z", false);
                    mv.visitVarInsn(ISTORE, maxLocals);
                    varInsns.add(new int[] { ILOAD, maxLocals });
                } else if (ptype == byte.class) {
                    mv.visitVarInsn(ALOAD, 1);
                    mv.visitLdcInsn(pname.substring(1));
                    mv.visitLdcInsn("0");
                    mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getRequstURIPath", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", false);
                    mv.visitIntInsn(BIPUSH, radix);
                    mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "parseByte", "(Ljava/lang/String;I)B", false);
                    mv.visitVarInsn(ISTORE, maxLocals);
                    varInsns.add(new int[] { ILOAD, maxLocals });
                } else if (ptype == short.class) {
                    mv.visitVarInsn(ALOAD, 1);
                    mv.visitLdcInsn(pname.substring(1));
                    mv.visitLdcInsn("0");
                    mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getRequstURIPath", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", false);
                    mv.visitIntInsn(BIPUSH, radix);
                    mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "parseShort", "(Ljava/lang/String;I)S", false);
                    mv.visitVarInsn(ISTORE, maxLocals);
                    varInsns.add(new int[] { ILOAD, maxLocals });
                } else if (ptype == char.class) {
                    mv.visitVarInsn(ALOAD, 1);
                    mv.visitLdcInsn(pname.substring(1));
                    mv.visitLdcInsn("0");
                    mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getRequstURIPath", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", false);
                    mv.visitInsn(ICONST_0);
                    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "charAt", "(I)C", false);
                    mv.visitVarInsn(ISTORE, maxLocals);
                    varInsns.add(new int[] { ILOAD, maxLocals });
                } else if (ptype == int.class) {
                    mv.visitVarInsn(ALOAD, 1);
                    mv.visitLdcInsn(pname.substring(1));
                    mv.visitLdcInsn("0");
                    mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getRequstURIPath", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", false);
                    mv.visitIntInsn(BIPUSH, radix);
                    mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "parseInt", "(Ljava/lang/String;I)I", false);
                    mv.visitVarInsn(ISTORE, maxLocals);
                    varInsns.add(new int[] { ILOAD, maxLocals });
                } else if (ptype == float.class) {
                    mv.visitVarInsn(ALOAD, 1);
                    mv.visitLdcInsn(pname.substring(1));
                    mv.visitLdcInsn("0");
                    mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getRequstURIPath", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", false);
                    mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "parseFloat", "(Ljava/lang/String;)F", false);
                    mv.visitVarInsn(FSTORE, maxLocals);
                    varInsns.add(new int[] { FLOAD, maxLocals });
                } else if (ptype == long.class) {
                    mv.visitVarInsn(ALOAD, 1);
                    mv.visitLdcInsn(pname.substring(1));
                    mv.visitLdcInsn("0");
                    mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getRequstURIPath", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", false);
                    mv.visitIntInsn(BIPUSH, radix);
                    mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "parseLong", "(Ljava/lang/String;I)J", false);
                    mv.visitVarInsn(LSTORE, maxLocals);
                    varInsns.add(new int[] { LLOAD, maxLocals });
                    maxLocals++;
                } else if (ptype == double.class) {
                    mv.visitVarInsn(ALOAD, 1);
                    mv.visitLdcInsn(pname.substring(1));
                    mv.visitLdcInsn("0");
                    mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getRequstURIPath", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", false);
                    mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "parseDouble", "(Ljava/lang/String;)D", false);
                    mv.visitVarInsn(DSTORE, maxLocals);
                    varInsns.add(new int[] { DLOAD, maxLocals });
                    maxLocals++;
                } else if (ptype == String.class) {
                    mv.visitVarInsn(ALOAD, 1);
                    mv.visitLdcInsn(pname.substring(1));
                    mv.visitLdcInsn("");
                    mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getRequstURIPath", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", false);
                    mv.visitVarInsn(ASTORE, maxLocals);
                    varInsns.add(new int[] { ALOAD, maxLocals });
                } else {
                    throw new RuntimeException(method + " only " + RestParam.class.getSimpleName() + "(#) to Type(primitive class or String)");
                }
            } else if ("&".equals(pname) && ptype == userType) {
                // 当前用户对象的类名
                mv.visitVarInsn(ALOAD, 1);
                mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "currentUser", "()Ljava/lang/Object;", false);
                mv.visitTypeInsn(CHECKCAST, Type.getInternalName(ptype));
                mv.visitVarInsn(ASTORE, maxLocals);
                varInsns.add(new int[] { ALOAD, maxLocals });
            } else if (ptype == boolean.class) {
                mv.visitVarInsn(ALOAD, 1);
                mv.visitLdcInsn(pname);
                mv.visitInsn(ICONST_0);
                mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, ishead ? "getBooleanHeader" : "getBooleanParameter", "(Ljava/lang/String;Z)Z", false);
                mv.visitVarInsn(ISTORE, maxLocals);
                varInsns.add(new int[] { ILOAD, maxLocals });
            } else if (ptype == byte.class) {
                mv.visitVarInsn(ALOAD, 1);
                mv.visitLdcInsn(pname);
                mv.visitLdcInsn("0");
                mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, ishead ? "getHeader" : "getParameter", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", false);
                mv.visitIntInsn(BIPUSH, radix);
                mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "parseByte", "(Ljava/lang/String;I)B", false);
                mv.visitVarInsn(ISTORE, maxLocals);
                varInsns.add(new int[] { ILOAD, maxLocals });
            } else if (ptype == short.class) {
                mv.visitVarInsn(ALOAD, 1);
                mv.visitIntInsn(BIPUSH, radix);
                mv.visitLdcInsn(pname);
                mv.visitInsn(ICONST_0);
                mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, ishead ? "getShortHeader" : "getShortParameter", "(ILjava/lang/String;S)S", false);
                mv.visitVarInsn(ISTORE, maxLocals);
                varInsns.add(new int[] { ILOAD, maxLocals });
            } else if (ptype == char.class) {
                mv.visitVarInsn(ALOAD, 1);
                mv.visitLdcInsn(pname);
                mv.visitLdcInsn("0");
                mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, ishead ? "getHeader" : "getParameter", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", false);
                mv.visitInsn(ICONST_0);
                mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "charAt", "(I)C", false);
                mv.visitVarInsn(ISTORE, maxLocals);
                varInsns.add(new int[] { ILOAD, maxLocals });
            } else if (ptype == int.class) {
                mv.visitVarInsn(ALOAD, 1);
                mv.visitIntInsn(BIPUSH, radix);
                mv.visitLdcInsn(pname);
                mv.visitInsn(ICONST_0);
                mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, ishead ? "getIntHeader" : "getIntParameter", "(ILjava/lang/String;I)I", false);
                mv.visitVarInsn(ISTORE, maxLocals);
                varInsns.add(new int[] { ILOAD, maxLocals });
            } else if (ptype == float.class) {
                mv.visitVarInsn(ALOAD, 1);
                mv.visitLdcInsn(pname);
                mv.visitInsn(FCONST_0);
                mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, ishead ? "getFloatHeader" : "getFloatParameter", "(Ljava/lang/String;F)F", false);
                mv.visitVarInsn(FSTORE, maxLocals);
                varInsns.add(new int[] { FLOAD, maxLocals });
            } else if (ptype == long.class) {
                mv.visitVarInsn(ALOAD, 1);
                mv.visitIntInsn(BIPUSH, radix);
                mv.visitLdcInsn(pname);
                mv.visitInsn(LCONST_0);
                mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, ishead ? "getLongHeader" : "getLongParameter", "(ILjava/lang/String;J)J", false);
                mv.visitVarInsn(LSTORE, maxLocals);
                varInsns.add(new int[] { LLOAD, maxLocals });
                maxLocals++;
            } else if (ptype == double.class) {
                mv.visitVarInsn(ALOAD, 1);
                mv.visitLdcInsn(pname);
                mv.visitInsn(DCONST_0);
                mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, ishead ? "getDoubleHeader" : "getDoubleParameter", "(Ljava/lang/String;D)D", false);
                mv.visitVarInsn(DSTORE, maxLocals);
                varInsns.add(new int[] { DLOAD, maxLocals });
                maxLocals++;
            } else if (ptype == String.class) {
                mv.visitVarInsn(ALOAD, 1);
                mv.visitLdcInsn(pname);
                mv.visitLdcInsn("");
                mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, iscookie ? "getCookie" : (ishead ? "getHeader" : "getParameter"), "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", false);
                mv.visitVarInsn(ASTORE, maxLocals);
                varInsns.add(new int[] { ALOAD, maxLocals });
            } else if (ptype == ChannelContext.class) {
                mv.visitVarInsn(ALOAD, 1);
                mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getChannelContext", "()" + channelDesc, false);
                mv.visitVarInsn(ASTORE, maxLocals);
                varInsns.add(new int[] { ALOAD, maxLocals });
            } else if (ptype == Flipper.class) {
                mv.visitVarInsn(ALOAD, 1);
                mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getFlipper", "()" + flipperDesc, false);
                mv.visitVarInsn(ASTORE, maxLocals);
                varInsns.add(new int[] { ALOAD, maxLocals });
            } else {
                // 其他Json对象
                mv.visitVarInsn(ALOAD, 1);
                if (param.getType() == param.getParameterizedType()) {
                    mv.visitLdcInsn(Type.getType(Type.getDescriptor(ptype)));
                } else {
                    mv.visitVarInsn(ALOAD, 0);
                    mv.visitFieldInsn(GETFIELD, newDynName, REST_PARAMTYPES_FIELD_NAME, "[[Ljava/lang/reflect/Type;");
                    // 方法下标
                    MethodDebugVisitor.pushInt(mv, entry.methodidx);
                    mv.visitInsn(AALOAD);
                    int paramidx = -1;
                    for (int i = 0; i < params.length; i++) {
                        if (params[i] == param) {
                            paramidx = i;
                            break;
                        }
                    }
                    // 参数下标
                    MethodDebugVisitor.pushInt(mv, paramidx);
                    mv.visitInsn(AALOAD);
                }
                mv.visitLdcInsn(pname);
                mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, ishead ? "getJsonHeader" : "getJsonParameter", "(Ljava/lang/reflect/Type;Ljava/lang/String;)Ljava/lang/Object;", false);
                mv.visitTypeInsn(CHECKCAST, ptype.getName().replace('.', '/'));
                mv.visitVarInsn(ASTORE, maxLocals);
                varInsns.add(new int[] { ALOAD, maxLocals });
                JsonFactory.root().loadDecoder(param.getParameterizedType());
                // 构建 RestHeader、RestCookie、RestAddress 等赋值操作
                Class loop = ptype;
                Set<String> fields = new HashSet<>();
                Map<String, Object[]> attrParaNames = new LinkedHashMap<>();
                do {
                    // 接口时getSuperclass可能会得到null
                    if (loop == null || loop.isInterface())
                        break;
                    for (Field field : loop.getDeclaredFields()) {
                        if (Modifier.isStatic(field.getModifiers()))
                            continue;
                        if (Modifier.isFinal(field.getModifiers()))
                            continue;
                        if (fields.contains(field.getName()))
                            continue;
                        RestHeader rh = field.getAnnotation(RestHeader.class);
                        RestCookie rc = field.getAnnotation(RestCookie.class);
                        RestSessionid rs = field.getAnnotation(RestSessionid.class);
                        RestAddress ra = field.getAnnotation(RestAddress.class);
                        RestBody rb = field.getAnnotation(RestBody.class);
                        RestUploadFile ru = field.getAnnotation(RestUploadFile.class);
                        RestURI ri = field.getAnnotation(RestURI.class);
                        if (rh == null && rc == null && ra == null && rb == null && rs == null && ru == null && ri == null)
                            continue;
                        if (rh != null && field.getType() != String.class && field.getType() != InetSocketAddress.class)
                            throw new RuntimeException("@RestHeader must on String Field in " + field);
                        if (rc != null && field.getType() != String.class)
                            throw new RuntimeException("@RestCookie must on String Field in " + field);
                        if (rs != null && field.getType() != String.class)
                            throw new RuntimeException("@RestSessionid must on String Field in " + field);
                        if (ra != null && field.getType() != String.class)
                            throw new RuntimeException("@RestAddress must on String Field in " + field);
                        if (rb != null && field.getType().isPrimitive())
                            throw new RuntimeException("@RestBody must on cannot on primitive type Field in " + field);
                        if (ru != null && field.getType() != byte[].class && field.getType() != File.class && field.getType() != File[].class) {
                            throw new RuntimeException("@RestUploadFile must on byte[] or File or File[] Field in " + field);
                        }
                        if (ri != null && field.getType() != String.class)
                            throw new RuntimeException("@RestURI must on String Field in " + field);
                        org.redkale.util.Attribute attr = org.redkale.util.Attribute.create(loop, field);
                        String attrFieldName;
                        String restname = "";
                        if (rh != null) {
                            attrFieldName = "_redkale_attr_header_" + (field.getType() != String.class ? "json_" : "") + restAttributes.size();
                            restname = rh.name();
                        } else if (rc != null) {
                            attrFieldName = "_redkale_attr_cookie_" + restAttributes.size();
                            restname = rc.name();
                        } else if (rs != null) {
                            attrFieldName = "_redkale_attr_sessionid_" + restAttributes.size();
                            // 用于下面区分create值
                            restname = rs.create() ? "1" : "";
                        } else if (ra != null) {
                            attrFieldName = "_redkale_attr_address_" + restAttributes.size();
                        // restname = "";
                        } else if (rb != null && field.getType() == String.class) {
                            attrFieldName = "_redkale_attr_bodystring_" + restAttributes.size();
                        // restname = "";
                        } else if (rb != null && field.getType() == byte[].class) {
                            attrFieldName = "_redkale_attr_bodybytes_" + restAttributes.size();
                        // restname = "";
                        } else if (rb != null && field.getType() != String.class && field.getType() != byte[].class) {
                            attrFieldName = "_redkale_attr_bodyjson_" + restAttributes.size();
                        // restname = "";
                        } else if (ru != null && field.getType() == byte[].class) {
                            attrFieldName = "_redkale_attr_uploadbytes_" + restAttributes.size();
                        // restname = "";
                        } else if (ru != null && field.getType() == File.class) {
                            attrFieldName = "_redkale_attr_uploadfile_" + restAttributes.size();
                        // restname = "";
                        } else if (ru != null && field.getType() == File[].class) {
                            attrFieldName = "_redkale_attr_uploadfiles_" + restAttributes.size();
                        // restname = "";
                        } else if (ri != null && field.getType() == String.class) {
                            attrFieldName = "_redkale_attr_uri_" + restAttributes.size();
                        // restname = "";
                        } else {
                            continue;
                        }
                        restAttributes.put(attrFieldName, attr);
                        attrParaNames.put(attrFieldName, new Object[] { restname, field.getType(), field.getGenericType(), ru });
                        fields.add(field.getName());
                    }
                } while ((loop = loop.getSuperclass()) != Object.class);
                if (!attrParaNames.isEmpty()) {
                    // 参数存在 RestHeader、RestCookie、RestSessionid、RestAddress、RestBody字段
                    // 加载JsonBean
                    mv.visitVarInsn(ALOAD, maxLocals);
                    Label lif = new Label();
                    // if(bean != null) {
                    mv.visitJumpInsn(IFNULL, lif);
                    for (Map.Entry<String, Object[]> en : attrParaNames.entrySet()) {
                        RestUploadFile ru = (RestUploadFile) en.getValue()[3];
                        mv.visitVarInsn(ALOAD, 0);
                        mv.visitFieldInsn(GETFIELD, newDynName, en.getKey(), attrDesc);
                        mv.visitVarInsn(ALOAD, maxLocals);
                        mv.visitVarInsn(ALOAD, en.getKey().contains("_upload") ? uploadLocal : 1);
                        if (en.getKey().contains("_header_")) {
                            String headerkey = en.getValue()[0].toString();
                            if ("Host".equalsIgnoreCase(headerkey)) {
                                mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getHost", "()Ljava/lang/String;", false);
                            } else if ("Content-Type".equalsIgnoreCase(headerkey)) {
                                mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getContentType", "()Ljava/lang/String;", false);
                            } else if ("Connection".equalsIgnoreCase(headerkey)) {
                                mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getConnection", "()Ljava/lang/String;", false);
                            } else if ("Method".equalsIgnoreCase(headerkey)) {
                                mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getMethod", "()Ljava/lang/String;", false);
                            } else if (en.getKey().contains("_header_json_")) {
                                String typefieldname = "_redkale_body_jsontype_" + bodyTypes.size();
                                bodyTypes.put(typefieldname, (java.lang.reflect.Type) en.getValue()[2]);
                                mv.visitVarInsn(ALOAD, 0);
                                mv.visitFieldInsn(GETFIELD, newDynName, typefieldname, "Ljava/lang/reflect/Type;");
                                mv.visitLdcInsn(headerkey);
                                mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getJsonHeader", "(Ljava/lang/reflect/Type;Ljava/lang/String;)Ljava/lang/Object;", false);
                                mv.visitTypeInsn(CHECKCAST, Type.getInternalName((Class) en.getValue()[1]));
                                JsonFactory.root().loadDecoder((java.lang.reflect.Type) en.getValue()[2]);
                            } else {
                                mv.visitLdcInsn(headerkey);
                                mv.visitLdcInsn("");
                                mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getHeader", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", false);
                            }
                        } else if (en.getKey().contains("_cookie_")) {
                            mv.visitLdcInsn(en.getValue()[0].toString());
                            mv.visitLdcInsn("");
                            mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getCookie", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", false);
                        } else if (en.getKey().contains("_sessionid_")) {
                            mv.visitInsn(en.getValue()[0].toString().isEmpty() ? ICONST_0 : ICONST_1);
                            mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getSessionid", "(Z)Ljava/lang/String;", false);
                        } else if (en.getKey().contains("_address_")) {
                            mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getRemoteAddr", "()Ljava/lang/String;", false);
                        } else if (en.getKey().contains("_uri_")) {
                            mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getRequestURI", "()Ljava/lang/String;", false);
                        } else if (en.getKey().contains("_bodystring_")) {
                            mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getBodyUTF8", "()Ljava/lang/String;", false);
                        } else if (en.getKey().contains("_bodybytes_")) {
                            mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getBody", "()[B", false);
                        } else if (en.getKey().contains("_bodyjson_")) {
                            // JavaBean 转 Json
                            String typefieldname = "_redkale_body_jsontype_" + bodyTypes.size();
                            bodyTypes.put(typefieldname, (java.lang.reflect.Type) en.getValue()[2]);
                            mv.visitVarInsn(ALOAD, 0);
                            mv.visitFieldInsn(GETFIELD, newDynName, typefieldname, "Ljava/lang/reflect/Type;");
                            mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getBodyJson", "(Ljava/lang/reflect/Type;)Ljava/lang/Object;", false);
                            mv.visitTypeInsn(CHECKCAST, Type.getInternalName((Class) en.getValue()[1]));
                            JsonFactory.root().loadDecoder((java.lang.reflect.Type) en.getValue()[2]);
                        } else if (en.getKey().contains("_uploadbytes_")) {
                        // 只需mv.visitVarInsn(ALOAD, 4), 无需处理
                        } else if (en.getKey().contains("_uploadfile_")) {
                        // 只需mv.visitVarInsn(ALOAD, 4), 无需处理
                        } else if (en.getKey().contains("_uploadfiles_")) {
                        // 只需mv.visitVarInsn(ALOAD, 4), 无需处理
                        }
                        mv.visitMethodInsn(INVOKEINTERFACE, attrInternalName, "set", "(Ljava/lang/Object;Ljava/lang/Object;)V", true);
                    }
                    // end if }
                    mv.visitLabel(lif);
                    mv.visitFrame(Opcodes.F_APPEND, 1, new Object[] { ptype.getName().replace('.', '/') }, 0, null);
                }
            }
            maxLocals++;
            paramMaps.add(paramMap);
        }
        // end params for each
        // mv.visitVarInsn(ALOAD, 0); //调用this
        // mv.visitFieldInsn(GETFIELD, newDynName, REST_SERVICE_FIELD_NAME, serviceDesc);
        mv.visitVarInsn(ALOAD, 3);
        for (int[] ins : varInsns) {
            mv.visitVarInsn(ins[0], ins[1]);
        }
        mv.visitMethodInsn(INVOKEVIRTUAL, serviceTypeInternalName, method.getName(), methodDesc, false);
        if (hasAsyncHandler) {
            mv.visitInsn(RETURN);
        } else if (returnType == void.class) {
            mv.visitVarInsn(ALOAD, 2);
            mv.visitVarInsn(ALOAD, 0);
            mv.visitFieldInsn(GETFIELD, newDynName, REST_RETURNTYPES_FIELD_NAME, "[Ljava/lang/reflect/Type;");
            // 方法下标
            MethodDebugVisitor.pushInt(mv, entry.methodidx);
            mv.visitInsn(AALOAD);
            mv.visitMethodInsn(INVOKESTATIC, retInternalName, "success", "()" + retDesc, false);
            mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finishJson", "(" + typeDesc + "Ljava/lang/Object;)V", false);
            mv.visitInsn(RETURN);
        } else if (returnType == boolean.class) {
            mv.visitVarInsn(ISTORE, maxLocals);
            // response
            mv.visitVarInsn(ALOAD, 2);
            mv.visitVarInsn(ILOAD, maxLocals);
            mv.visitMethodInsn(INVOKESTATIC, "java/lang/String", "valueOf", "(Z)Ljava/lang/String;", false);
            mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finish", "(Ljava/lang/String;)V", false);
            mv.visitInsn(RETURN);
            maxLocals++;
        } else if (returnType == byte.class) {
            mv.visitVarInsn(ISTORE, maxLocals);
            // response
            mv.visitVarInsn(ALOAD, 2);
            mv.visitVarInsn(ILOAD, maxLocals);
            mv.visitMethodInsn(INVOKESTATIC, "java/lang/String", "valueOf", "(I)Ljava/lang/String;", false);
            mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finish", "(Ljava/lang/String;)V", false);
            mv.visitInsn(RETURN);
            maxLocals++;
        } else if (returnType == short.class) {
            mv.visitVarInsn(ISTORE, maxLocals);
            // response
            mv.visitVarInsn(ALOAD, 2);
            mv.visitVarInsn(ILOAD, maxLocals);
            mv.visitMethodInsn(INVOKESTATIC, "java/lang/String", "valueOf", "(I)Ljava/lang/String;", false);
            mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finish", "(Ljava/lang/String;)V", false);
            mv.visitInsn(RETURN);
            maxLocals++;
        } else if (returnType == char.class) {
            mv.visitVarInsn(ISTORE, maxLocals);
            // response
            mv.visitVarInsn(ALOAD, 2);
            mv.visitVarInsn(ILOAD, maxLocals);
            mv.visitMethodInsn(INVOKESTATIC, "java/lang/String", "valueOf", "(C)Ljava/lang/String;", false);
            mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finish", "(Ljava/lang/String;)V", false);
            mv.visitInsn(RETURN);
            maxLocals++;
        } else if (returnType == int.class) {
            mv.visitVarInsn(ISTORE, maxLocals);
            // response
            mv.visitVarInsn(ALOAD, 2);
            mv.visitVarInsn(ILOAD, maxLocals);
            mv.visitMethodInsn(INVOKESTATIC, "java/lang/String", "valueOf", "(I)Ljava/lang/String;", false);
            mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finish", "(Ljava/lang/String;)V", false);
            mv.visitInsn(RETURN);
            maxLocals++;
        } else if (returnType == float.class) {
            mv.visitVarInsn(FSTORE, maxLocals);
            // response
            mv.visitVarInsn(ALOAD, 2);
            mv.visitVarInsn(FLOAD, maxLocals);
            mv.visitMethodInsn(INVOKESTATIC, "java/lang/String", "valueOf", "(F)Ljava/lang/String;", false);
            mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finish", "(Ljava/lang/String;)V", false);
            mv.visitInsn(RETURN);
            maxLocals++;
        } else if (returnType == long.class) {
            mv.visitVarInsn(LSTORE, maxLocals);
            // response
            mv.visitVarInsn(ALOAD, 2);
            mv.visitVarInsn(LLOAD, maxLocals);
            mv.visitMethodInsn(INVOKESTATIC, "java/lang/String", "valueOf", "(J)Ljava/lang/String;", false);
            mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finish", "(Ljava/lang/String;)V", false);
            mv.visitInsn(RETURN);
            maxLocals += 2;
        } else if (returnType == double.class) {
            mv.visitVarInsn(DSTORE, maxLocals);
            // response
            mv.visitVarInsn(ALOAD, 2);
            mv.visitVarInsn(DLOAD, maxLocals);
            mv.visitMethodInsn(INVOKESTATIC, "java/lang/String", "valueOf", "(D)Ljava/lang/String;", false);
            mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finish", "(Ljava/lang/String;)V", false);
            mv.visitInsn(RETURN);
            maxLocals += 2;
        } else if (returnType == byte[].class) {
            mv.visitVarInsn(ASTORE, maxLocals);
            // response
            mv.visitVarInsn(ALOAD, 2);
            mv.visitVarInsn(ALOAD, maxLocals);
            mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finish", "([B)V", false);
            mv.visitInsn(RETURN);
            maxLocals++;
        } else if (returnType == String.class) {
            mv.visitVarInsn(ASTORE, maxLocals);
            // response
            mv.visitVarInsn(ALOAD, 2);
            mv.visitVarInsn(ALOAD, maxLocals);
            mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finish", "(Ljava/lang/String;)V", false);
            mv.visitInsn(RETURN);
            maxLocals++;
        } else if (returnType == File.class) {
            mv.visitVarInsn(ASTORE, maxLocals);
            // response
            mv.visitVarInsn(ALOAD, 2);
            mv.visitVarInsn(ALOAD, maxLocals);
            mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finish", "(Ljava/io/File;)V", false);
            mv.visitInsn(RETURN);
            maxLocals++;
        } else if (Number.class.isAssignableFrom(returnType) || CharSequence.class.isAssignableFrom(returnType)) {
            // returnType == String.class 必须放在前面
            mv.visitVarInsn(ASTORE, maxLocals);
            // response
            mv.visitVarInsn(ALOAD, 2);
            mv.visitVarInsn(ALOAD, maxLocals);
            mv.visitMethodInsn(INVOKESTATIC, "java/lang/String", "valueOf", "(Ljava/lang/Object;)Ljava/lang/String;", false);
            mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finish", "(Ljava/lang/String;)V", false);
            mv.visitInsn(RETURN);
            maxLocals++;
        } else if (RetResult.class.isAssignableFrom(returnType)) {
            mv.visitVarInsn(ASTORE, maxLocals);
            // response
            mv.visitVarInsn(ALOAD, 2);
            if (rcs != null && rcs.length > 0) {
                mv.visitVarInsn(ALOAD, 0);
                mv.visitFieldInsn(GETFIELD, newDynName, REST_CONVERT_FIELD_PREFIX + restConverts.size(), convertDesc);
                mv.visitVarInsn(ALOAD, 0);
                mv.visitFieldInsn(GETFIELD, newDynName, REST_RETURNTYPES_FIELD_NAME, "[Ljava/lang/reflect/Type;");
                // 方法下标
                MethodDebugVisitor.pushInt(mv, entry.methodidx);
                mv.visitInsn(AALOAD);
                mv.visitVarInsn(ALOAD, maxLocals);
                mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finish", "(" + convertDesc + typeDesc + retDesc + ")V", false);
            } else {
                mv.visitVarInsn(ALOAD, 0);
                mv.visitFieldInsn(GETFIELD, newDynName, REST_RETURNTYPES_FIELD_NAME, "[Ljava/lang/reflect/Type;");
                // 方法下标
                MethodDebugVisitor.pushInt(mv, entry.methodidx);
                mv.visitInsn(AALOAD);
                mv.visitVarInsn(ALOAD, maxLocals);
                mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finish", "(" + typeDesc + retDesc + ")V", false);
            }
            mv.visitInsn(RETURN);
            maxLocals++;
        } else if (HttpResult.class.isAssignableFrom(returnType)) {
            mv.visitVarInsn(ASTORE, maxLocals);
            // response
            mv.visitVarInsn(ALOAD, 2);
            if (rcs != null && rcs.length > 0) {
                mv.visitVarInsn(ALOAD, 0);
                mv.visitFieldInsn(GETFIELD, newDynName, REST_CONVERT_FIELD_PREFIX + restConverts.size(), convertDesc);
                mv.visitVarInsn(ALOAD, 0);
                mv.visitFieldInsn(GETFIELD, newDynName, REST_RETURNTYPES_FIELD_NAME, "[Ljava/lang/reflect/Type;");
                // 方法下标
                MethodDebugVisitor.pushInt(mv, entry.methodidx);
                mv.visitInsn(AALOAD);
                mv.visitVarInsn(ALOAD, maxLocals);
                mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finish", "(" + convertDesc + typeDesc + httpResultDesc + ")V", false);
            } else {
                mv.visitVarInsn(ALOAD, 0);
                mv.visitFieldInsn(GETFIELD, newDynName, REST_RETURNTYPES_FIELD_NAME, "[Ljava/lang/reflect/Type;");
                // 方法下标
                MethodDebugVisitor.pushInt(mv, entry.methodidx);
                mv.visitInsn(AALOAD);
                mv.visitVarInsn(ALOAD, maxLocals);
                mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finish", "(" + typeDesc + httpResultDesc + ")V", false);
            }
            mv.visitInsn(RETURN);
            maxLocals++;
        } else if (HttpScope.class.isAssignableFrom(returnType)) {
            mv.visitVarInsn(ASTORE, maxLocals);
            // response
            mv.visitVarInsn(ALOAD, 2);
            if (rcs != null && rcs.length > 0) {
                mv.visitVarInsn(ALOAD, 0);
                mv.visitFieldInsn(GETFIELD, newDynName, REST_CONVERT_FIELD_PREFIX + restConverts.size(), convertDesc);
                mv.visitVarInsn(ALOAD, maxLocals);
                mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finish", "(" + convertDesc + httpScopeDesc + ")V", false);
            } else {
                mv.visitVarInsn(ALOAD, maxLocals);
                mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finish", "(" + httpScopeDesc + ")V", false);
            }
            mv.visitInsn(RETURN);
            maxLocals++;
        } else if (CompletionStage.class.isAssignableFrom(returnType)) {
            mv.visitVarInsn(ASTORE, maxLocals);
            // response
            mv.visitVarInsn(ALOAD, 2);
            if (rcs != null && rcs.length > 0) {
                mv.visitVarInsn(ALOAD, 0);
                mv.visitFieldInsn(GETFIELD, newDynName, REST_CONVERT_FIELD_PREFIX + restConverts.size(), convertDesc);
                mv.visitVarInsn(ALOAD, 0);
                mv.visitFieldInsn(GETFIELD, newDynName, REST_RETURNTYPES_FIELD_NAME, "[Ljava/lang/reflect/Type;");
                // 方法下标
                MethodDebugVisitor.pushInt(mv, entry.methodidx);
                mv.visitInsn(AALOAD);
                mv.visitVarInsn(ALOAD, maxLocals);
                mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finish", "(" + convertDesc + typeDesc + stageDesc + ")V", false);
            } else {
                mv.visitVarInsn(ALOAD, 0);
                mv.visitFieldInsn(GETFIELD, newDynName, REST_RETURNTYPES_FIELD_NAME, "[Ljava/lang/reflect/Type;");
                // 方法下标
                MethodDebugVisitor.pushInt(mv, entry.methodidx);
                mv.visitInsn(AALOAD);
                mv.visitVarInsn(ALOAD, maxLocals);
                mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finish", "(" + typeDesc + stageDesc + ")V", false);
            }
            mv.visitInsn(RETURN);
            maxLocals++;
        } else if (Flows.maybePublisherClass(returnType)) {
            // Flow.Publisher
            mv.visitVarInsn(ASTORE, maxLocals);
            // response
            mv.visitVarInsn(ALOAD, 2);
            if (rcs != null && rcs.length > 0) {
                mv.visitVarInsn(ALOAD, 0);
                mv.visitFieldInsn(GETFIELD, newDynName, REST_CONVERT_FIELD_PREFIX + restConverts.size(), convertDesc);
                mv.visitVarInsn(ALOAD, 0);
                mv.visitFieldInsn(GETFIELD, newDynName, REST_RETURNTYPES_FIELD_NAME, "[Ljava/lang/reflect/Type;");
                // 方法下标
                MethodDebugVisitor.pushInt(mv, entry.methodidx);
                mv.visitInsn(AALOAD);
                mv.visitVarInsn(ALOAD, maxLocals);
                mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finishPublisher", "(" + convertDesc + typeDesc + "Ljava/lang/Object;)V", false);
            } else {
                mv.visitVarInsn(ALOAD, 0);
                mv.visitFieldInsn(GETFIELD, newDynName, REST_RETURNTYPES_FIELD_NAME, "[Ljava/lang/reflect/Type;");
                // 方法下标
                MethodDebugVisitor.pushInt(mv, entry.methodidx);
                mv.visitInsn(AALOAD);
                mv.visitVarInsn(ALOAD, maxLocals);
                mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finishPublisher", "(" + typeDesc + "Ljava/lang/Object;)V", false);
            }
            mv.visitInsn(RETURN);
            maxLocals++;
        } else if (returnType == retvalType) {
            // 普通JavaBean或JavaBean[]
            mv.visitVarInsn(ASTORE, maxLocals);
            // response
            mv.visitVarInsn(ALOAD, 2);
            if (rcs != null && rcs.length > 0) {
                mv.visitVarInsn(ALOAD, 0);
                mv.visitFieldInsn(GETFIELD, newDynName, REST_CONVERT_FIELD_PREFIX + restConverts.size(), convertDesc);
                mv.visitVarInsn(ALOAD, 0);
                mv.visitFieldInsn(GETFIELD, newDynName, REST_RETURNTYPES_FIELD_NAME, "[Ljava/lang/reflect/Type;");
                // 方法下标
                MethodDebugVisitor.pushInt(mv, entry.methodidx);
                mv.visitInsn(AALOAD);
                mv.visitVarInsn(ALOAD, maxLocals);
                mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finishJson", "(" + Type.getDescriptor(JsonConvert.class) + typeDesc + "Ljava/lang/Object;)V", false);
            } else {
                mv.visitVarInsn(ALOAD, 0);
                mv.visitFieldInsn(GETFIELD, newDynName, REST_RETURNTYPES_FIELD_NAME, "[Ljava/lang/reflect/Type;");
                // 方法下标
                MethodDebugVisitor.pushInt(mv, entry.methodidx);
                mv.visitInsn(AALOAD);
                mv.visitVarInsn(ALOAD, maxLocals);
                mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finishJson", "(" + typeDesc + "Ljava/lang/Object;)V", false);
            }
            mv.visitInsn(RETURN);
            maxLocals++;
        } else {
            mv.visitVarInsn(ASTORE, maxLocals);
            // response
            mv.visitVarInsn(ALOAD, 2);
            if (rcs != null && rcs.length > 0) {
                mv.visitVarInsn(ALOAD, 0);
                mv.visitFieldInsn(GETFIELD, newDynName, REST_CONVERT_FIELD_PREFIX + restConverts.size(), convertDesc);
                mv.visitVarInsn(ALOAD, 0);
                mv.visitFieldInsn(GETFIELD, newDynName, REST_RETURNTYPES_FIELD_NAME, "[Ljava/lang/reflect/Type;");
                // 方法下标
                MethodDebugVisitor.pushInt(mv, entry.methodidx);
                mv.visitInsn(AALOAD);
                mv.visitVarInsn(ALOAD, maxLocals);
                mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finish", "(" + convertDesc + typeDesc + "Ljava/lang/Object;)V", false);
            } else {
                mv.visitVarInsn(ALOAD, 0);
                mv.visitFieldInsn(GETFIELD, newDynName, REST_RETURNTYPES_FIELD_NAME, "[Ljava/lang/reflect/Type;");
                // 方法下标
                MethodDebugVisitor.pushInt(mv, entry.methodidx);
                mv.visitInsn(AALOAD);
                mv.visitVarInsn(ALOAD, maxLocals);
                mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finish", "(" + typeDesc + "Ljava/lang/Object;)V", false);
            }
            mv.visitInsn(RETURN);
            maxLocals++;
        }
        mv.visitMaxs(maxStack, maxLocals);
        mappingMap.put("params", paramMaps);
        {
            // _Dync_XXX__HttpServlet.class
            ClassWriter cw2 = new ClassWriter(COMPUTE_FRAMES);
            cw2.visit(V11, ACC_SUPER, newDynName + "$" + entry.newActionClassName, null, httpServletName, null);
            cw2.visitInnerClass(newDynName + "$" + entry.newActionClassName, newDynName, entry.newActionClassName, ACC_PRIVATE + ACC_STATIC);
            {
                fv = cw2.visitField(0, "servlet", "L" + newDynName + ";", null, null);
                fv.visitEnd();
            }
            {
                mv = new MethodDebugVisitor(cw2.visitMethod(0, "<init>", "(L" + newDynName + ";)V", null, null));
                mv.visitVarInsn(ALOAD, 0);
                mv.visitMethodInsn(INVOKESPECIAL, httpServletName, "<init>", "()V", false);
                mv.visitVarInsn(ALOAD, 0);
                mv.visitVarInsn(ALOAD, 1);
                mv.visitFieldInsn(PUTFIELD, newDynName + "$" + entry.newActionClassName, "servlet", "L" + newDynName + ";");
                mv.visitInsn(RETURN);
                mv.visitMaxs(2, 2);
                mv.visitEnd();
            }
            // if (false) {
            // mv = new MethodDebugVisitor(cw2.visitMethod(ACC_SYNTHETIC, "<init>", "(L" + newDynName + ";L" + newDynName + "$" + entry.newActionClassName + ";)V", null, null));
            // mv.visitVarInsn(ALOAD, 0);
            // mv.visitVarInsn(ALOAD, 1);
            // mv.visitMethodInsn(INVOKESPECIAL, newDynName + "$" + entry.newActionClassName, "<init>", "L" + newDynName + ";", false);
            // mv.visitInsn(RETURN);
            // mv.visitMaxs(2, 3);
            // mv.visitEnd();
            // }
            {
                mv = new MethodDebugVisitor(cw2.visitMethod(ACC_PUBLIC, "execute", "(" + reqDesc + respDesc + ")V", null, new String[] { "java/io/IOException" }));
                mv.visitVarInsn(ALOAD, 0);
                mv.visitFieldInsn(GETFIELD, newDynName + "$" + entry.newActionClassName, "servlet", "L" + newDynName + ";");
                mv.visitVarInsn(ALOAD, 1);
                mv.visitVarInsn(ALOAD, 2);
                mv.visitMethodInsn(INVOKEVIRTUAL, newDynName, entry.newMethodName, "(" + reqDesc + respDesc + ")V", false);
                mv.visitInsn(RETURN);
                mv.visitMaxs(3, 3);
                mv.visitEnd();
            }
            cw2.visitEnd();
            byte[] bytes = cw2.toByteArray();
            newLoader.addClass((newDynName + "$" + entry.newActionClassName).replace('/', '.'), bytes);
            innerClassBytesMap.put((newDynName + "$" + entry.newActionClassName).replace('/', '.'), bytes);
        }
    }
    // end  for each
    // HashMap<String, ActionEntry> _createRestActionEntry() {
    // HashMap<String, ActionEntry> map = new HashMap<>();
    // map.put("asyncfind3", new ActionEntry(100000,200000,"asyncfind3", new String[]{},null,false,false,0, new _Dync_asyncfind3_HttpServlet()));
    // map.put("asyncfind2", new ActionEntry(1,2,"asyncfind2", new String[]{"GET", "POST"},null,false,true,0, new _Dync_asyncfind2_HttpServlet()));
    // return map;
    // }
    {
        // _createRestActionEntry 方法
        mv = new MethodDebugVisitor(cw.visitMethod(0, "_createRestActionEntry", "()Ljava/util/HashMap;", "()Ljava/util/HashMap<Ljava/lang/String;L" + actionEntryName + ";>;", null));
        // mv.setDebug(true);
        mv.visitTypeInsn(NEW, "java/util/HashMap");
        mv.visitInsn(DUP);
        mv.visitMethodInsn(INVOKESPECIAL, "java/util/HashMap", "<init>", "()V", false);
        mv.visitVarInsn(ASTORE, 1);
        for (final MappingEntry entry : entrys) {
            mappingurlToMethod.put(entry.mappingurl, entry.mappingMethod);
            mv.visitVarInsn(ALOAD, 1);
            // name
            mv.visitLdcInsn(entry.mappingurl);
            // new ActionEntry
            mv.visitTypeInsn(NEW, actionEntryName);
            mv.visitInsn(DUP);
            // moduleid
            MethodDebugVisitor.pushInt(mv, moduleid);
            // actionid
            MethodDebugVisitor.pushInt(mv, entry.actionid);
            // name
            mv.visitLdcInsn(entry.mappingurl);
            // methods
            MethodDebugVisitor.pushInt(mv, entry.methods.length);
            mv.visitTypeInsn(ANEWARRAY, "java/lang/String");
            for (int i = 0; i < entry.methods.length; i++) {
                mv.visitInsn(DUP);
                MethodDebugVisitor.pushInt(mv, i);
                mv.visitLdcInsn(entry.methods[i]);
                mv.visitInsn(AASTORE);
            }
            // method
            mv.visitInsn(ACONST_NULL);
            // rpconly
            mv.visitInsn(entry.rpconly ? ICONST_1 : ICONST_0);
            // auth
            mv.visitInsn(entry.auth ? ICONST_1 : ICONST_0);
            // cacheseconds
            MethodDebugVisitor.pushInt(mv, entry.cacheseconds);
            mv.visitTypeInsn(NEW, newDynName + "$" + entry.newActionClassName);
            mv.visitInsn(DUP);
            mv.visitVarInsn(ALOAD, 0);
            mv.visitMethodInsn(INVOKESPECIAL, newDynName + "$" + entry.newActionClassName, "<init>", "(L" + newDynName + ";)V", false);
            mv.visitMethodInsn(INVOKESPECIAL, actionEntryName, "<init>", "(IILjava/lang/String;[Ljava/lang/String;Ljava/lang/reflect/Method;ZZILorg/redkale/net/http/HttpServlet;)V", false);
            mv.visitMethodInsn(INVOKEVIRTUAL, "java/util/HashMap", "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", false);
            mv.visitInsn(POP);
        }
        mv.visitVarInsn(ALOAD, 1);
        mv.visitInsn(ARETURN);
        mv.visitMaxs(2, 2);
        mv.visitEnd();
    }
    for (Map.Entry<String, java.lang.reflect.Type> en : bodyTypes.entrySet()) {
        fv = cw.visitField(ACC_PRIVATE, en.getKey(), "Ljava/lang/reflect/Type;", null, null);
        av0 = fv.visitAnnotation(Type.getDescriptor(Comment.class), true);
        av0.visit("value", en.getValue().toString());
        av0.visitEnd();
        fv.visitEnd();
    }
    for (Map.Entry<java.lang.reflect.Type, String> en : typeRefs.entrySet()) {
        fv = cw.visitField(ACC_PRIVATE, en.getValue(), "Ljava/lang/reflect/Type;", null, null);
        av0 = fv.visitAnnotation(Type.getDescriptor(Comment.class), true);
        av0.visit("value", en.getKey().toString());
        av0.visitEnd();
        fv.visitEnd();
    }
    for (Map.Entry<String, org.redkale.util.Attribute> en : restAttributes.entrySet()) {
        fv = cw.visitField(ACC_PRIVATE, en.getKey(), attrDesc, null, null);
        av0 = fv.visitAnnotation(Type.getDescriptor(Comment.class), true);
        av0.visit("value", en.getValue().toString());
        av0.visitEnd();
        fv.visitEnd();
    }
    for (int i = 1; i <= restConverts.size(); i++) {
        fv = cw.visitField(ACC_PRIVATE, REST_CONVERT_FIELD_PREFIX + i, convertDesc, null, null);
        fv.visitEnd();
    }
    {
        // _paramtypes字段 java.lang.reflect.Type[][]
        fv = cw.visitField(ACC_PRIVATE, REST_PARAMTYPES_FIELD_NAME, "[[Ljava/lang/reflect/Type;", null, null);
        av0 = fv.visitAnnotation(Type.getDescriptor(Comment.class), true);
        StringBuilder sb = new StringBuilder().append('[');
        for (java.lang.reflect.Type[] rs : paramTypes) {
            sb.append(Arrays.toString(rs)).append(',');
        }
        av0.visit("value", sb.append(']').toString());
        av0.visitEnd();
        fv.visitEnd();
    }
    {
        // _returntypes字段 java.lang.reflect.Type[]
        fv = cw.visitField(ACC_PRIVATE, REST_RETURNTYPES_FIELD_NAME, "[Ljava/lang/reflect/Type;", null, null);
        av0 = fv.visitAnnotation(Type.getDescriptor(Comment.class), true);
        av0.visit("value", retvalTypes.toString());
        av0.visitEnd();
        fv.visitEnd();
    }
    // classMap.put("mappings", mappingMaps); //不显示太多信息
    {
        // toString函数
        mv = new MethodDebugVisitor(cw.visitMethod(ACC_PUBLIC, "toString", "()Ljava/lang/String;", null, null));
        // mv.setDebug(true);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitFieldInsn(GETFIELD, newDynName, REST_TOSTRINGOBJ_FIELD_NAME, "Ljava/util/function/Supplier;");
        mv.visitMethodInsn(INVOKEINTERFACE, "java/util/function/Supplier", "get", "()Ljava/lang/Object;", true);
        mv.visitTypeInsn(CHECKCAST, "java/lang/String");
        mv.visitInsn(ARETURN);
        mv.visitMaxs(1, 1);
        mv.visitEnd();
    }
    {
        // RestDyn
        av0 = cw.visitAnnotation(Type.getDescriptor(RestDyn.class), true);
        av0.visit("simple", (Boolean) dynsimple);
        av0.visitEnd();
    }
    cw.visitEnd();
    byte[] bytes = cw.toByteArray();
    newLoader.addClass(newDynName.replace('/', '.'), bytes);
    try {
        Class<?> newClazz = newLoader.findClass(newDynName.replace('/', '.'));
        innerClassBytesMap.forEach((n, bs) -> {
            try {
                RedkaleClassLoader.putDynClass(n, bs, newLoader.findClass(n));
                RedkaleClassLoader.putReflectionClass(n);
            } catch (ClassNotFoundException e) {
                throw new RuntimeException(e);
            }
        });
        RedkaleClassLoader.putDynClass(newDynName.replace('/', '.'), bytes, newClazz);
        RedkaleClassLoader.putReflectionDeclaredConstructors(newClazz, newDynName.replace('/', '.'));
        for (java.lang.reflect.Type t : retvalTypes) {
            JsonFactory.root().loadEncoder(t);
        }
        T obj = ((Class<T>) newClazz).getDeclaredConstructor().newInstance();
        {
            Field serviceField = newClazz.getDeclaredField(REST_SERVICE_FIELD_NAME);
            RedkaleClassLoader.putReflectionField(newDynName.replace('/', '.'), serviceField);
            Field servicemapField = newClazz.getDeclaredField(REST_SERVICEMAP_FIELD_NAME);
            RedkaleClassLoader.putReflectionField(newDynName.replace('/', '.'), servicemapField);
        }
        for (Map.Entry<java.lang.reflect.Type, String> en : typeRefs.entrySet()) {
            Field refField = newClazz.getDeclaredField(en.getValue());
            refField.setAccessible(true);
            refField.set(obj, en.getKey());
            RedkaleClassLoader.putReflectionField(newDynName.replace('/', '.'), refField);
        }
        for (Map.Entry<String, org.redkale.util.Attribute> en : restAttributes.entrySet()) {
            Field attrField = newClazz.getDeclaredField(en.getKey());
            attrField.setAccessible(true);
            attrField.set(obj, en.getValue());
            RedkaleClassLoader.putReflectionField(newDynName.replace('/', '.'), attrField);
        }
        for (Map.Entry<String, java.lang.reflect.Type> en : bodyTypes.entrySet()) {
            Field genField = newClazz.getDeclaredField(en.getKey());
            genField.setAccessible(true);
            genField.set(obj, en.getValue());
            RedkaleClassLoader.putReflectionField(newDynName.replace('/', '.'), genField);
        }
        for (int i = 0; i < restConverts.size(); i++) {
            Field genField = newClazz.getDeclaredField(REST_CONVERT_FIELD_PREFIX + (i + 1));
            genField.setAccessible(true);
            Object[] rc = restConverts.get(i);
            genField.set(obj, createJsonConvert((RestConvert[]) rc[0], (RestConvertCoder[]) rc[1]));
            RedkaleClassLoader.putReflectionField(newDynName.replace('/', '.'), genField);
        }
        Field typesfield = newClazz.getDeclaredField(REST_PARAMTYPES_FIELD_NAME);
        typesfield.setAccessible(true);
        java.lang.reflect.Type[][] paramtypeArray = new java.lang.reflect.Type[paramTypes.size()][];
        paramtypeArray = paramTypes.toArray(paramtypeArray);
        typesfield.set(obj, paramtypeArray);
        RedkaleClassLoader.putReflectionField(newDynName.replace('/', '.'), typesfield);
        Field retfield = newClazz.getDeclaredField(REST_RETURNTYPES_FIELD_NAME);
        retfield.setAccessible(true);
        java.lang.reflect.Type[] rettypeArray = new java.lang.reflect.Type[retvalTypes.size()];
        rettypeArray = retvalTypes.toArray(rettypeArray);
        retfield.set(obj, rettypeArray);
        RedkaleClassLoader.putReflectionField(newDynName.replace('/', '.'), retfield);
        Field tostringfield = newClazz.getDeclaredField(REST_TOSTRINGOBJ_FIELD_NAME);
        tostringfield.setAccessible(true);
        java.util.function.Supplier<String> sSupplier = () -> JsonConvert.root().convertTo(classMap);
        tostringfield.set(obj, sSupplier);
        RedkaleClassLoader.putReflectionField(newDynName.replace('/', '.'), tostringfield);
        Method restactMethod = newClazz.getDeclaredMethod("_createRestActionEntry");
        restactMethod.setAccessible(true);
        RedkaleClassLoader.putReflectionMethod(newDynName.replace('/', '.'), restactMethod);
        Field tmpentrysfield = HttpServlet.class.getDeclaredField("_actionmap");
        tmpentrysfield.setAccessible(true);
        HashMap<String, HttpServlet.ActionEntry> innerEntryMap = (HashMap) restactMethod.invoke(obj);
        for (Map.Entry<String, HttpServlet.ActionEntry> en : innerEntryMap.entrySet()) {
            Method m = mappingurlToMethod.get(en.getKey());
            if (m != null)
                en.getValue().annotations = HttpServlet.ActionEntry.annotations(m);
        }
        tmpentrysfield.set(obj, innerEntryMap);
        RedkaleClassLoader.putReflectionField(HttpServlet.class.getName(), tmpentrysfield);
        return obj;
    } catch (Throwable e) {
        throw new RuntimeException(e);
    }
}
Also used : java.lang.reflect(java.lang.reflect) org.redkale.convert(org.redkale.convert) org.redkale.asm(org.redkale.asm) java.util(java.util) Flipper(org.redkale.source.Flipper) java.util.concurrent(java.util.concurrent) org.redkale.net(org.redkale.net) java.lang.annotation(java.lang.annotation) CompletionHandler(java.nio.channels.CompletionHandler) Resource(javax.annotation.Resource) COMPUTE_FRAMES(org.redkale.asm.ClassWriter.COMPUTE_FRAMES) Opcodes(org.redkale.asm.Opcodes) Type(org.redkale.asm.Type) ElementType(java.lang.annotation.ElementType) RUNTIME(java.lang.annotation.RetentionPolicy.RUNTIME) InetSocketAddress(java.net.InetSocketAddress) org.redkale.convert.json(org.redkale.convert.json) org.redkale.util(org.redkale.util) java.io(java.io) Sncp(org.redkale.net.sncp.Sncp) MethodDebugVisitor(org.redkale.asm.MethodDebugVisitor) org.redkale.service(org.redkale.service) org.redkale.mq(org.redkale.mq) InetSocketAddress(java.net.InetSocketAddress) java.lang.reflect(java.lang.reflect) java.io(java.io) java.util(java.util) org.redkale.util(org.redkale.util) Flipper(org.redkale.source.Flipper) Type(org.redkale.asm.Type) ElementType(java.lang.annotation.ElementType) CompletionHandler(java.nio.channels.CompletionHandler) MethodDebugVisitor(org.redkale.asm.MethodDebugVisitor)

Aggregations

ElementType (java.lang.annotation.ElementType)3 Resource (javax.annotation.Resource)3 MethodDebugVisitor (org.redkale.asm.MethodDebugVisitor)3 Type (org.redkale.asm.Type)3 java.io (java.io)1 java.lang.annotation (java.lang.annotation)1 RUNTIME (java.lang.annotation.RetentionPolicy.RUNTIME)1 java.lang.reflect (java.lang.reflect)1 InetSocketAddress (java.net.InetSocketAddress)1 CompletionHandler (java.nio.channels.CompletionHandler)1 java.util (java.util)1 java.util.concurrent (java.util.concurrent)1 org.redkale.asm (org.redkale.asm)1 COMPUTE_FRAMES (org.redkale.asm.ClassWriter.COMPUTE_FRAMES)1 Opcodes (org.redkale.asm.Opcodes)1 org.redkale.convert (org.redkale.convert)1 org.redkale.convert.json (org.redkale.convert.json)1 org.redkale.mq (org.redkale.mq)1 org.redkale.net (org.redkale.net)1 Sncp (org.redkale.net.sncp.Sncp)1