我试图检查(在字节码级别,ASM)实现某些特定接口(在本例中为java.sql.Connection)的类,并发现在某些情况下,库具有另一个接口,该接口扩展了我的接口集。 ..然后它们的类实现THAT接口。(在这种情况下,新的扩展接口com.mysql.jdbc.Connection扩展了java.sql.Connection,然后扩展了它们的实现,例如ConnectionImpl实现了com.mysql.jdbc.Connection。)因此,我错过了将ConnectionImpl标识为目标类的想法。
因此,结果是我在加载类时需要将com.mysql.jdbc.Connection标识为“有趣的”接口。但是我看不到如何通过接口而不是普通类来标识类。ClassReader中是否有某些东西可以给我这种信息?
根据标题,如果你想检查一个类是否是一个接口:
ClassNode node = // However you wish to load the class
if ((node.access & Opcodes.ACC_INTERFACE) != 0){
// is interface
} else {
// is not an interface
}
Run Code Online (Sandbox Code Playgroud)
在您的帖子中,您声明您希望找到java.sql.Connection.
您遇到的问题是这样的:
java.sql.Connection -> com.mysql.jdbc.Connection -> ConnectionImpl
ConnectionImpl不直接实现java.sql.Connection,因此不会将其检测为子/实现。对于这样的问题,您必须做的是遍历类层次结构。如果我处于您的情况,我会加载 ClassNodes 映射<String, ClassNode>,其中字符串是 ClassNode 的名称。然后我将使用递归方法来检查给定的类是否是预期的类型。因此,如果您在其中发送 ClassNode,它将使用该节点的父节点调用自身,然后调用接口。最终,如果最初给定的节点是正确的类型,最终java.sql.Connection将通过并找到接口。此外,如果您想跳过冗余,您可以将每个 ClassNode 的结果存储在映射中,这样您就不必一遍又一遍地检查整个层次结构。
编辑:像这样
public static boolean isMatch(ClassNode cn, Map<String,ClassNode> nodes, String target){
if (cn.name.equals(target)) return true;
else{
if (nodes.containsKey(cn.superName) && isMatch(nodes.get(cn.superName),nodes,target)) return true;
for (String interf : cn.interfaces){
if (nodes.containsKey(interf) && isMatch(nodes.get(interf),nodes,target)) return true;
}
}
return false;
}
Run Code Online (Sandbox Code Playgroud)