docs: @SuppressWarnings("unchecked")
      protected static <T extends Service> Class<? extends T> createLocalServiceClass(ClassLoader classLoader, final String name, final Class<T> serviceImplClass) {
          if (serviceImplClass == null) return null;
          if (!Service.class.isAssignableFrom(serviceImplClass)) return serviceImplClass;
          ResourceFactory.checkResourceName(name);
          int mod = serviceImplClass.getModifiers();
          if (!java.lang.reflect.Modifier.isPublic(mod)) return serviceImplClass;
          if (java.lang.reflect.Modifier.isAbstract(mod)) return serviceImplClass;
          final List<Method> methods = SncpClient.parseMethod(serviceImplClass);
          final String supDynName = serviceImplClass.getName().replace('.', '/');
          final String clientName = SncpClient.class.getName().replace('.', '/');
          final String resDesc = Type.getDescriptor(Resource.class);
          final String clientDesc = Type.getDescriptor(SncpClient.class);
          final String anyValueDesc = Type.getDescriptor(AnyValue.class);
          final String sncpDynDesc = Type.getDescriptor(SncpDyn.class);
          ClassLoader loader = classLoader == null ? Thread.currentThread().getContextClassLoader() : classLoader;
          String newDynName = supDynName.substring(0, supDynName.lastIndexOf('/') + 1) + LOCALPREFIX + serviceImplClass.getSimpleName();
          if (!name.isEmpty()) {
              boolean normal = true;
              for (char ch : name.toCharArray()) {
                  if (!((ch >= '0' && ch <= '9') || ch == '_' || (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))) normal = false;
              }
              if (!normal) throw new RuntimeException(serviceImplClass + "'s resource name is illegal, must be 0-9 _ a-z A-Z");
              newDynName += "_" + (normal ? name : hash(name));
          }
          try {
              return (Class<T>) loader.loadClass(newDynName.replace('/', '.'));
          } catch (Throwable ex) {
          }
          //------------------------------------------------------------------------------
          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);
          {
              av0 = cw.visitAnnotation(resDesc, true);
              av0.visit("name", name);
              av0.visitEnd();
          }
          {
              av0 = cw.visitAnnotation(sncpDynDesc, true);
              av0.visit("remote", Boolean.FALSE);
              av0.visitEnd();
          }
          { //给新类加上 原有的Annotation
              for (Annotation ann : serviceImplClass.getAnnotations()) {
                  if (ann instanceof Resource || ann instanceof SncpDyn || ann instanceof ResourceType) continue;
                  visitAnnotation(cw.visitAnnotation(Type.getDescriptor(ann.annotationType()), true), ann);
              }
          }
          {
              av0 = cw.visitAnnotation(Type.getDescriptor(ResourceType.class), true);
              ResourceType rty = serviceImplClass.getAnnotation(ResourceType.class);
              av0.visit("value", Type.getType(Type.getDescriptor(rty == null ? serviceImplClass : rty.value())));
              av0.visitEnd();
          }
          {
              fv = cw.visitField(ACC_PRIVATE, FIELDPREFIX + "_conf", anyValueDesc, null, null);
              fv.visitEnd();
          }
          {
              fv = cw.visitField(ACC_PRIVATE, FIELDPREFIX + "_client", clientDesc, null, 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();
          }
          { // toString()
              mv = new MethodDebugVisitor(cw.visitMethod(ACC_PUBLIC, "toString", "()Ljava/lang/String;", null, null));
              mv.visitVarInsn(ALOAD, 0);
              mv.visitFieldInsn(GETFIELD, newDynName, FIELDPREFIX + "_client", clientDesc);
              Label l1 = new Label();
              mv.visitJumpInsn(IFNONNULL, l1);
              mv.visitVarInsn(ALOAD, 0);
              mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;", false);
              mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class", "getName", "()Ljava/lang/String;", false);
              Label l2 = new Label();
              mv.visitJumpInsn(GOTO, l2);
              mv.visitLabel(l1);
              mv.visitVarInsn(ALOAD, 0);
              mv.visitFieldInsn(GETFIELD, newDynName, FIELDPREFIX + "_client", clientDesc);
              mv.visitMethodInsn(INVOKEVIRTUAL, clientName, "toSimpleString", "()Ljava/lang/String;", false);
              mv.visitLabel(l2);
              mv.visitInsn(ARETURN);
              mv.visitMaxs(1, 1);
              mv.visitEnd();
          }
          int i = - 1;
          for (final Method method : methods) {
              final RpcMultiRun mrun = method.getAnnotation(RpcMultiRun.class);
              if (mrun == null) continue;
              final Class returnType = method.getReturnType();
              final String methodDesc = Type.getMethodDescriptor(method);
              final Class[] paramtypes = method.getParameterTypes();
              final int index = ++i;
              {   //原始方法
                  mv = new MethodDebugVisitor(cw.visitMethod(ACC_PUBLIC + (method.isVarArgs() ? ACC_VARARGS : 0), method.getName(), methodDesc, null, null));
                  //mv.setDebug(true);
                  { //给参数加上 Annotation
                      final Annotation[][] anns = method.getParameterAnnotations();
                      for (int k = 0; k < anns.length; k++) {
                          for (Annotation ann : anns[k]) {
                              if (ann instanceof SncpDyn || ann instanceof RpcMultiRun) continue; //必须过滤掉 RpcMultiRun、SncpDyn，否则生成远程模式Service时会出错
                              visitAnnotation(mv.visitParameterAnnotation(k, Type.getDescriptor(ann.annotationType()), true), ann);
                          }
                      }
                  }
                  mv.visitVarInsn(ALOAD, 0);
                  mv.visitInsn(mrun.selfrun() ? ICONST_1 : ICONST_0);
                  mv.visitInsn(mrun.samerun() ? ICONST_1 : ICONST_0);
                  mv.visitInsn(mrun.diffrun() ? ICONST_1 : ICONST_0);
                  int varindex = 0;
                  boolean handlerFuncFlag = false;
                  for (Class pt : paramtypes) {
                      if (CompletionHandler.class.isAssignableFrom(pt)) {
                          if (handlerFuncFlag) throw new RuntimeException(method + " have more than one CompletionHandler type parameter");
                          checkAsyncModifier(pt, method);
                          handlerFuncFlag = true;
                      }
                      if (pt.isPrimitive()) {
                          if (pt == long.class) {
                              mv.visitVarInsn(LLOAD, ++varindex);
                              ++varindex;
                          } else if (pt == double.class) {
                              mv.visitVarInsn(DLOAD, ++varindex);
                              ++varindex;
                          } else if (pt == float.class) {
                              mv.visitVarInsn(FLOAD, ++varindex);
                          } else {
                              mv.visitVarInsn(ILOAD, ++varindex);
                          }
                      } else {
                          mv.visitVarInsn(ALOAD, ++varindex);
                      }
                  }
                  mv.visitMethodInsn(INVOKEVIRTUAL, newDynName, FIELDPREFIX + "_" + method.getName(), "(ZZZ" + methodDesc.substring(1), false);
                  if (returnType == void.class) {
                      mv.visitInsn(RETURN);
                  } else if (returnType.isPrimitive()) {
                      if (returnType == long.class) {
                          mv.visitInsn(LRETURN);
                      } else if (returnType == float.class) {
                          mv.visitInsn(FRETURN);
                      } else if (returnType == double.class) {
                          mv.visitInsn(DRETURN);
                      } else {
                          mv.visitInsn(IRETURN);
                      }
                  } else {
                      mv.visitInsn(ARETURN);
                  }
                  mv.visitMaxs(varindex + 3, varindex + 1);
                  mv.visitEnd();
              }
              {  // _方法   _方法比无_方法多了三个参数
                  mv = new MethodDebugVisitor(cw.visitMethod(ACC_PUBLIC + (method.isVarArgs() ? ACC_VARARGS : 0), FIELDPREFIX + "_" + method.getName(), "(ZZZ" + methodDesc.substring(1), null, null));
                  //mv.setDebug(true);  
                  { //给参数加上 Annotation
                      final Annotation[][] anns = method.getParameterAnnotations();
                      boolean handlerAttachFlag = false;
                      for (int k = 0; k < anns.length; k++) {
                          for (Annotation ann : anns[k]) {
                              if (ann.annotationType() == RpcAttachment.class) {
                                  if (handlerAttachFlag) {
                                      throw new RuntimeException(method + " have more than one @RpcAttachment parameter");
                                  }
                                  handlerAttachFlag = true;
                              }
                              if (ann instanceof SncpDyn || ann instanceof RpcMultiRun) continue; //必须过滤掉 RpcMultiRun、SncpDyn，否则生成远程模式Service时会出错
                              visitAnnotation(mv.visitParameterAnnotation(k, Type.getDescriptor(ann.annotationType()), true), ann);
                          }
                      }
                  }
                  av0 = mv.visitAnnotation(sncpDynDesc, true);
                  av0.visit("remote", Boolean.FALSE);
                  av0.visit("index", index);
                  av0.visitEnd();
                  //---------------------------- 调用selfrun ---------------------------------
                  Label selfLabel = new Label();
                  if (returnType == void.class) {  // if
                      mv.visitVarInsn(ILOAD, 1);
                      mv.visitJumpInsn(IFEQ, selfLabel);
                  }
                  mv.visitVarInsn(ALOAD, 0);
                  int varindex = 3; //空3给selfrunnable、samerunnable、diffrunnable
                  for (Class pt : paramtypes) {
                      if (pt.isPrimitive()) {
                          if (pt == long.class) {
                              mv.visitVarInsn(LLOAD, ++varindex);
                              ++varindex;
                          } else if (pt == double.class) {
                              mv.visitVarInsn(DLOAD, ++varindex);
                              ++varindex;
                          } else if (pt == float.class) {
                              mv.visitVarInsn(FLOAD, ++varindex);
                          } else {
                              mv.visitVarInsn(ILOAD, ++varindex);
                          }
                      } else {
                          mv.visitVarInsn(ALOAD, ++varindex);
                      }
                  }
                  mv.visitMethodInsn(INVOKESPECIAL, supDynName, method.getName(), methodDesc, false);
                  if (returnType == void.class) {  // end if
                      mv.visitLabel(selfLabel);
                  }
                  if (returnType == void.class) {
                  } else if (returnType.isPrimitive()) {
                      if (returnType == long.class) {
                          mv.visitVarInsn(LSTORE, ++varindex);
                          //++varindex; //多加1
                      } else if (returnType == float.class) {
                          mv.visitVarInsn(FSTORE, ++varindex);
                      } else if (returnType == double.class) {
                          mv.visitVarInsn(DSTORE, ++varindex);
                          //++varindex; //多加1
                      } else {
                          mv.visitVarInsn(ISTORE, ++varindex);
                      }
                  } else {
                      mv.visitVarInsn(ASTORE, ++varindex);
                  }
                  final int rsindex = varindex;  //
  
                  //---------------------------if (_redkale_client== null)  return ----------------------------------
                  mv.visitVarInsn(ALOAD, 0);
                  mv.visitFieldInsn(GETFIELD, newDynName, FIELDPREFIX + "_client", clientDesc);
                  Label clientLabel = new Label();
                  mv.visitJumpInsn(IFNONNULL, clientLabel);
                  if (returnType == void.class) {
                      mv.visitInsn(RETURN);
                  } else if (returnType.isPrimitive()) {
                      if (returnType == long.class) {
                          mv.visitVarInsn(LLOAD, rsindex);
                          mv.visitInsn(LRETURN);
                      } else if (returnType == float.class) {
                          mv.visitVarInsn(FLOAD, rsindex);
                          mv.visitInsn(FRETURN);
                      } else if (returnType == double.class) {
                          mv.visitVarInsn(DLOAD, rsindex);
                          mv.visitInsn(DRETURN);
                      } else {
                          mv.visitVarInsn(ILOAD, rsindex);
                          mv.visitInsn(IRETURN);
                      }
                  } else {
                      mv.visitVarInsn(ALOAD, rsindex);
                      mv.visitInsn(ARETURN);
                  }
                  mv.visitLabel(clientLabel);
                  //---------------------------- 调用samerun ---------------------------------
                  mv.visitVarInsn(ILOAD, 2); //读取 samerunnable
                  Label sameLabel = new Label();
                  mv.visitJumpInsn(IFEQ, sameLabel);  //判断 samerunnable
  
                  mv.visitVarInsn(ALOAD, 0);//调用 _client
                  mv.visitFieldInsn(GETFIELD, newDynName, FIELDPREFIX + "_client", clientDesc);
                  final int preparams = 3; //调用selfrunnable之前的参数个数;  _client
  
                  pushInt(mv, index);   //第几个 SncpAction 
                  pushInt(mv, paramtypes.length + preparams);   //参数总数量
  
                  mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");
  
                  mv.visitInsn(DUP);
                  mv.visitInsn(ICONST_0);
                  mv.visitInsn(ICONST_1);   //第一个参数  selfrunnable
                  mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false);
                  mv.visitInsn(AASTORE);
  
                  mv.visitInsn(DUP);
                  mv.visitInsn(ICONST_1);
                  mv.visitInsn(ICONST_0);   //第二个参数  samerunnable
                  mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false);
                  mv.visitInsn(AASTORE);
  
                  mv.visitInsn(DUP);
                  mv.visitInsn(ICONST_2);
                  mv.visitInsn(ICONST_0);   //第三个参数  diffrunnable
                  mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false);
                  mv.visitInsn(AASTORE);
  
                  int insn = 3; //空3给selfrunnable、samerunnable、diffrunnable
                  for (int j = 0; j < paramtypes.length; j++) {
                      final Class pt = paramtypes[j];
                      mv.visitInsn(DUP);
                      insn++;
                      pushInt(mv, j + 3);
                      if (pt.isPrimitive()) {
                          if (pt == long.class) {
                              mv.visitVarInsn(LLOAD, insn++);
                          } else if (pt == float.class) {
                              mv.visitVarInsn(FLOAD, insn++);
                          } else if (pt == double.class) {
                              mv.visitVarInsn(DLOAD, insn++);
                          } else {
                              mv.visitVarInsn(ILOAD, insn);
                          }
                          Class bigclaz = java.lang.reflect.Array.get(java.lang.reflect.Array.newInstance(pt, 1), 0).getClass();
                          mv.visitMethodInsn(INVOKESTATIC, bigclaz.getName().replace('.', '/'), "valueOf", "(" + Type.getDescriptor(pt) + ")" + Type.getDescriptor(bigclaz), false);
                      } else {
                          mv.visitVarInsn(ALOAD, insn);
                      }
                      mv.visitInsn(AASTORE);
                  }
                  mv.visitMethodInsn(INVOKEVIRTUAL, clientName, mrun.async() ? "asyncRemoteSameGroup" : "remoteSameGroup", "(I[Ljava/lang/Object;)V", false);
                  mv.visitLabel(sameLabel);
                  //---------------------------- 调用diffrun ---------------------------------
                  mv.visitVarInsn(ILOAD, 3); //读取 diffrunnable
                  Label diffLabel = new Label();
                  mv.visitJumpInsn(IFEQ, diffLabel);  //判断 diffrunnable
  
                  mv.visitVarInsn(ALOAD, 0);
                  mv.visitFieldInsn(GETFIELD, newDynName, FIELDPREFIX + "_client", clientDesc);
  
                  pushInt(mv, index); //第几个 SncpAction 
                  pushInt(mv, paramtypes.length + preparams); //参数总数量
  
                  mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");
  
                  mv.visitInsn(DUP);
                  mv.visitInsn(ICONST_0);
                  mv.visitInsn(ICONST_1);   //第一个参数  samerunnable
                  mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false);
                  mv.visitInsn(AASTORE);
  
                  mv.visitInsn(DUP);
                  mv.visitInsn(ICONST_1);
                  mv.visitInsn(ICONST_1);   //第二个参数  diffrunnable
                  mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false);
                  mv.visitInsn(AASTORE);
  
                  mv.visitInsn(DUP);
                  mv.visitInsn(ICONST_2);
                  mv.visitInsn(ICONST_0);   //第二个参数  diffrunnable
                  mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false);
                  mv.visitInsn(AASTORE);
  
                  insn = 3;//空3给selfrunnable、samerunnable、diffrunnable
                  for (int j = 0; j < paramtypes.length; j++) {
                      final Class pt = paramtypes[j];
                      mv.visitInsn(DUP);
                      insn++;
                      pushInt(mv, j + 3);
                      if (pt.isPrimitive()) {
                          if (pt == long.class) {
                              mv.visitVarInsn(LLOAD, insn++);
                          } else if (pt == float.class) {
                              mv.visitVarInsn(FLOAD, insn++);
                          } else if (pt == double.class) {
                              mv.visitVarInsn(DLOAD, insn++);
                          } else {
                              mv.visitVarInsn(ILOAD, insn);
                          }
                          Class bigclaz = java.lang.reflect.Array.get(java.lang.reflect.Array.newInstance(pt, 1), 0).getClass();
                          mv.visitMethodInsn(INVOKESTATIC, bigclaz.getName().replace('.', '/'), "valueOf", "(" + Type.getDescriptor(pt) + ")" + Type.getDescriptor(bigclaz), false);
                      } else {
                          mv.visitVarInsn(ALOAD, insn);
                      }
                      mv.visitInsn(AASTORE);
                  }
                  mv.visitMethodInsn(INVOKEVIRTUAL, clientName, mrun.async() ? "asyncRemoteDiffGroup" : "remoteDiffGroup", "(I[Ljava/lang/Object;)V", false);
                  mv.visitLabel(diffLabel);
  
                  if (returnType == void.class) {
                      mv.visitInsn(RETURN);
                  } else if (returnType.isPrimitive()) {
                      if (returnType == long.class) {
                          mv.visitVarInsn(LLOAD, rsindex);
                          mv.visitInsn(LRETURN);
                      } else if (returnType == float.class) {
                          mv.visitVarInsn(FLOAD, rsindex);
                          mv.visitInsn(FRETURN);
                      } else if (returnType == double.class) {
                          mv.visitVarInsn(DLOAD, rsindex);
                          mv.visitInsn(DRETURN);
                      } else {
                          mv.visitVarInsn(ILOAD, rsindex);
                          mv.visitInsn(IRETURN);
                      }
                  } else {
                      mv.visitVarInsn(ALOAD, rsindex);
                      mv.visitInsn(ARETURN);
                  }
  
                  mv.visitMaxs(Math.max(varindex, 10), varindex + 4);
                  mv.visitEnd();
              }
          }
          cw.visitEnd();
          byte[] bytes = cw.toByteArray();
          Class<?> newClazz = new ClassLoader(loader) {
              public final Class<?> loadClass(String name, byte[] b) {
                  return defineClass(name, b, 0, b.length);
              }
          }.loadClass(newDynName.replace('/', '.'), bytes);
          return (Class<T>) newClazz;
      }