Java 5泛型將類型參數信息存儲在類文件的Signature屬性中。雖然反射API可讀取已加載類的泛型信息,但無法處理未加載的類文件。本文詳細介紹如何使用ASM字節碼框架直接解析二進制類中的泛型簽名,無需類加載即可獲取完整類型信息。
java/lang/StringL全限定名;,基本類型單字母(I=int, Z=boolean),數組[前綴(參數描述符)返回描述符擴展描述符語法,引入類型參數、通配符、邊界等:
<T:Ljava/lang/Object;U:Ljava/lang/Object;>Ljava/lang/Object;Ljava/lang/Iterable<TT;;>;Ljava/util/List<Lcom/example/FileInfo;>;T標識,結尾;,如TT;、TU;ClassVisitor的核心方法直接接收簽名字符串:
void visit(int version, int access, String name, String signature, String superName, String[] interfaces);
FieldVisitor visitField(int access, String name, String desc, String signature, Object value);
MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions);
非泛型元素簽名為null。
將簽名字符串解析為SignatureVisitor方法調用序列:
accept():解析類/方法簽名acceptType():解析字段簽名SignatureVisitor定義16個方法,對應簽名語法各產生式,如visitFormalTypeParameter、visitClassType、visitTypeVariable、visitTypeArgument等。返回新Visitor實例表示進入嵌套上下文。
Ljava/util/List<Lcom/sosnoski/generics/FileInfo;>;
解析調用序列:
visitClassType("java/util/List")
visitTypeArgument('=')
visitClassType("com/sosnoski/generics/FileInfo")
visitEnd()
visitEnd()
<T:Ljava/lang/Object;U:Ljava/lang/Object;>Ljava/lang/Object;Ljava/lang/Iterable<TT;;>;
解析展示嵌套結構:
visitFormalTypeParameter("T")
visitClassBound() → visitClassType("java/lang/Object") → visitEnd()
visitFormalTypeParameter("U")
visitClassBound() → visitClassType("java/lang/Object") → visitEnd()
visitSuperclass() → visitClassType("java/lang/Object") → visitEnd()
visitInterface() → visitClassType("java/lang/Iterable")
visitTypeArgument('=') → visitTypeVariable("T") → visitEnd()
visitEnd()
AnalyzeSignaturesVisitor繼承EmptyVisitor,重寫三個訪問方法:
public void visit(...) { if (sig!=null) new SignatureReader(sig).accept(new TraceSignatureVisitor()); }
public FieldVisitor visitField(...) { if (sig!=null) new SignatureReader(sig).acceptType(new TraceSignatureVisitor()); }
public MethodVisitor visitMethod(...) { if (sig!=null) new SignatureReader(sig).accept(new TraceSignatureVisitor()); }
TraceSignatureVisitor實現SignatureVisitor,將各調用輸出到控制台,配合縮進邏輯可視化嵌套結構。
下一期將構建完整的泛型數據結構分析引擎,實現跨類引用的類型替換與遞歸展開。