class GrpcUtil {
    @SuppressWarnings("rawtypes")
    private static HashMap<String, HashMap<String, MethodDescriptor>> serviceMap = new HashMap<String, HashMap<String, MethodDescriptor>>();
    public static final String JSON_CODEC = "grpc-pb-json";
    @SuppressWarnings({"unchecked", "rawtypes"})
    public static ServerServiceDefinition getServiceDefByAnnotation(Class<?> clazz) throws Exception {
        ServiceDescriptor serviceDesc = getServiceDesc(getGrpcClassName(clazz));
        io.grpc.ServerServiceDefinition.Builder builder = io.grpc.ServerServiceDefinition.builder(serviceDesc);
        for (MethodDescriptor<?, ?> methodDesc : serviceDesc.getMethods()) {
            builder.addMethod(methodDesc, new MotanServerCallHandler());
        }
        return builder.build();
    }

    private static String getGrpcClassName(Class<?> clazz) {<FILL_FUNCTION_BODY>}

    public static ServiceDescriptor getServiceDesc(String clazzName) throws Exception {
        Class<?> clazz = Class.forName(clazzName);
        return (ServiceDescriptor) clazz.getMethod("getServiceDescriptor", null).invoke(null, null);
    }

    @SuppressWarnings("rawtypes")
    public static HashMap<String, MethodDescriptor> getMethodDescriptorByAnnotation(Class<?> clazz, String serialization) throws Exception {
        String clazzName = getGrpcClassName(clazz);
        HashMap<String, MethodDescriptor> result = serviceMap.get(clazzName);
        if (result == null) {
            synchronized (serviceMap) {
                if (!serviceMap.containsKey(clazzName)) {
                    ServiceDescriptor serviceDesc = getServiceDesc(getGrpcClassName(clazz));
                    HashMap<String, MethodDescriptor> methodMap = new HashMap<String, MethodDescriptor>();
                    for (MethodDescriptor<?, ?> methodDesc : serviceDesc.getMethods()) {
                        Method interfaceMethod = getMethod(methodDesc.getFullMethodName(), clazz);
                        if(JSON_CODEC.equals(serialization)){
                            methodDesc = convertJsonDescriptor(methodDesc, interfaceMethod.getParameterTypes()[0], interfaceMethod.getReturnType());
                        }
                        methodMap.put(interfaceMethod.getName(), methodDesc);
                    }
                    serviceMap.put(clazzName, methodMap);
                }
                result = serviceMap.get(clazzName);
            }
        }
        return result;
    }

    public static Method getMethod(String name, Class<?> interfaceClazz) {
        int index = name.lastIndexOf("/");
        if (index > -1) {
            name = name.substring(name.lastIndexOf("/") + 1);
        }

        Method[] methods = interfaceClazz.getMethods();
        for (Method m : methods) {
            if (m.getName().equalsIgnoreCase(name)) {
                return m;
            }
        }
        throw new MotanFrameworkException("not find grpc method");
    }

    public static MethodDescriptor convertJsonDescriptor(MethodDescriptor oldDesc, Class req, Class res){
        MethodDescriptor.Marshaller reqMarshaller = getJsonMarshaller(req);
        MethodDescriptor.Marshaller resMarshaller = getJsonMarshaller(res);
        if(reqMarshaller != null && resMarshaller != null){
            return MethodDescriptor.create(oldDesc.getType(), oldDesc.getFullMethodName(), reqMarshaller, resMarshaller);
        }
        return null;
    }

    public static MethodDescriptor.Marshaller getJsonMarshaller(Class clazz) {
        try {
            if (MessageLite.class.isAssignableFrom(clazz)) {
                Method method = clazz.getDeclaredMethod("getDefaultInstance", null);
                Message message = (Message) method.invoke(null, null);
                return jsonMarshaller(message);
            }
        } catch (Exception ignore) {
        }
        return null;
    }

    public static <T extends Message> MethodDescriptor.Marshaller<T> jsonMarshaller(final T defaultInstance) {
        final JsonFormat.Printer printer = JsonFormat.printer().preservingProtoFieldNames();
        final JsonFormat.Parser parser = JsonFormat.parser();
        final Charset charset = Charset.forName("UTF-8");

        return new MethodDescriptor.Marshaller<T>() {
            @Override
            public InputStream stream(T value) {
                try {
                    return new ByteArrayInputStream(printer.print(value).getBytes(charset));
                } catch (InvalidProtocolBufferException e) {
                    throw Status.INTERNAL
                            .withCause(e)
                            .withDescription("Unable to print json proto")
                            .asRuntimeException();
                }
            }

            @SuppressWarnings("unchecked")
            @Override
            public T parse(InputStream stream) {
                Message.Builder builder = defaultInstance.newBuilderForType();
                Reader reader = new InputStreamReader(stream, charset);
                T proto;
                try {
                    parser.merge(reader, builder);
                    proto = (T) builder.build();
                    reader.close();
                } catch (InvalidProtocolBufferException e) {
                    throw Status.INTERNAL.withDescription("Invalid protobuf byte sequence")
                            .withCause(e).asRuntimeException();
                } catch (IOException e) {
                    // Same for now, might be unavailable
                    throw Status.INTERNAL.withDescription("Invalid protobuf byte sequence")
                            .withCause(e).asRuntimeException();
                }
                return proto;
            }
        };
    }


}

        GrpcConfig config = clazz.getAnnotation(GrpcConfig.class);
        if (config == null || StringUtils.isBlank(config.grpc())) {
            throw new MotanFrameworkException("can not find grpc config in class " + clazz.getName());
        }
        return config.grpc();
    
<no_super_class>