private static Class<?> getCurrentThriftMessageClass() {
        final Class<?> clazz = thriftMessageClassFinder.get();

        if (clazz == null) {
            throw new RuntimeException("Must call (indirectly) from a TBase/TApplicationException object.");
        }

        return clazz;
    }
I need to know what type thrift message we are processing,
in order to look up fields by their field name. For example,
i I parse a line "count : 7", I need to know we are in a
StatsThriftMessage, or similar, to know that count should be
of type int32, and have a thrift id 1.

<p>In order to figure this out, I assume that this method was
called (indirectly) by the read() method in a class T which
is a TBase subclass. It is called that way by thrift generated
code. So, I iterate backwards up the call stack, stopping
at the first method call which belongs to a TBase object.
I return the Class for that object.

<p>One could argue this is someone fragile and error prone.
The alternative is to modify the thrift compiler to generate
code which passes class information into this (and other)
TProtocol objects, and that seems like a lot more work. Given
the low level interface of TProtocol (e.g. methods like readInt(),
rather than readThriftMessage()), it seems likely that a TBase
subclass, which has the knowledge of what fields exist, as well as
their types & relationships, will have to be the caller of
the TProtocol methods.

<p>Note: this approach does not handle TUnion, because TUnion has its own implementation of
read/write and any TUnion thrift structure does not override its read and write method.
Thus this algorithm fail to get current specific TUnion thrift structure by reading the stack.
To fix this, we can track call stack of nested thrift objects on our own by overriding
TProtocol.writeStructBegin(), rather than relying on the stack trace.
thrift/thrift0.13/src/main/java/com/linecorp/armeria/common/thrift/text/StructContext.java