protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws Exception {
    int length = msg.readableBytes();
    byte[] array;
    int offset;
    if (msg.hasArray()) {
      array = msg.array();
      offset = msg.arrayOffset() + msg.readerIndex();
    } else {
      array = ByteBufUtil.getBytes(msg, msg.readerIndex(), length, false);
      offset = 0;
    }

    Object addObj;
    if (HAS_PARSER) {
      // addObj = parser.parseFrom(array, offset, length);
      addObj = parseFromMethod.invoke(parser, array, offset, length);
    } else {
      // addObj = builder.mergeFrom(array, offset, length).build();
      Object builderObj = mergeFromMethod.invoke(builder, array, offset, length);
      addObj = buildMethod.invoke(builderObj);
    }
    out.add(addObj);
  }
Modified based on io.netty.handler.codec.protobuf.ProtobufDecoder. The Netty's ProtobufDecode
supports unshaded protobuf messages (com.google.protobuf). Hadoop 3.3.0 and above relocates
protobuf classes to a shaded jar (hadoop-thirdparty), and so we must use reflection to detect
which one (relocated or not) to use. Do not use this to process HBase's shaded protobuf messages.
This is meant to process the protobuf messages in HDFS for the asyncfs use case.
hbase-asyncfs/src/main/java/org/apache/hadoop/hbase/io/asyncfs/ProtobufDecoder.java