使用 ASM 重命名 class 时内部 class 的 NoClassDefFoundError
NoClassDefFoundError for inner class when renaming class with ASM
我正在尝试使用 ASM 重命名 class,然后再将其写入 JAR 文件,稍后再将其加载回来。我已经按如下方式实现了我的 ASM 重映射器:
private static class MyClassRemapper extends Remapper {
private final String className;
public MyClassRemapper(Class cls) {
className = cls.getCanonicalName().replace(".", "/");
}
@Override public String map(String internalName) {
if (internalName.startsWith(className))
return internalName.replace(className, "New" + className);
return super.map(internalName);
}
}
如果我给它喂一些OuterClass
,它一切正常。但是,如果我随后将内部 class InnerClass
添加到 OuterClass
,那么在我尝试在 [= 的实例上调用方法(如果重要的话通过反射)时重新加载 JAR 之后=19=] 我收到错误:
java.lang.NoClassDefFoundError: com/.../NewOuterClass$InnerClass
at java.base/java.lang.Class.getDeclaredMethods0(Native Method)
at java.base/java.lang.Class.privateGetDeclaredMethods(Class.java:3139)
at java.base/java.lang.Class.getMethodsRecursive(Class.java:3280)
at java.base/java.lang.Class.getMethod0(Class.java:3266)
at java.base/java.lang.Class.getMethod(Class.java:2063)
at ...
从错误中可以清楚地看出,ASM 成功地重命名了一些对 InnerClass
的引用,但显然不是 class 定义本身。我已经考虑过实施 mapInnerClassName
,但我很确定我不需要这样做,因为那会改变 InnerClass
本身。
有人有什么想法吗?
编辑:如果我将map
函数更改为;
@Override public String map(String internalName) {
if (internalName == className)
return internalName.replace(className, "New" + className);
return super.map(internalName);
}
这样只有顶层 class 被重命名,然后我 运行 在尝试 运行 内部 class 构造函数时陷入不同的错误:
NoSuchMethodError: com.(...).OuterClass$InnerClass.<init>(Lcom/.../NewOuterClass)V
这表明内部 class 的方法未能正确重命名。
Holger 在他的评论中提供了解决方案。问题是我只是重新映射外部 class 的 class 文件。然而,内部 class 也有自己的 class 文件。解决方案是将 MyClassRemapper
应用到它并写出来。
我正在尝试使用 ASM 重命名 class,然后再将其写入 JAR 文件,稍后再将其加载回来。我已经按如下方式实现了我的 ASM 重映射器:
private static class MyClassRemapper extends Remapper {
private final String className;
public MyClassRemapper(Class cls) {
className = cls.getCanonicalName().replace(".", "/");
}
@Override public String map(String internalName) {
if (internalName.startsWith(className))
return internalName.replace(className, "New" + className);
return super.map(internalName);
}
}
如果我给它喂一些OuterClass
,它一切正常。但是,如果我随后将内部 class InnerClass
添加到 OuterClass
,那么在我尝试在 [= 的实例上调用方法(如果重要的话通过反射)时重新加载 JAR 之后=19=] 我收到错误:
java.lang.NoClassDefFoundError: com/.../NewOuterClass$InnerClass
at java.base/java.lang.Class.getDeclaredMethods0(Native Method)
at java.base/java.lang.Class.privateGetDeclaredMethods(Class.java:3139)
at java.base/java.lang.Class.getMethodsRecursive(Class.java:3280)
at java.base/java.lang.Class.getMethod0(Class.java:3266)
at java.base/java.lang.Class.getMethod(Class.java:2063)
at ...
从错误中可以清楚地看出,ASM 成功地重命名了一些对 InnerClass
的引用,但显然不是 class 定义本身。我已经考虑过实施 mapInnerClassName
,但我很确定我不需要这样做,因为那会改变 InnerClass
本身。
有人有什么想法吗?
编辑:如果我将map
函数更改为;
@Override public String map(String internalName) {
if (internalName == className)
return internalName.replace(className, "New" + className);
return super.map(internalName);
}
这样只有顶层 class 被重命名,然后我 运行 在尝试 运行 内部 class 构造函数时陷入不同的错误:
NoSuchMethodError: com.(...).OuterClass$InnerClass.<init>(Lcom/.../NewOuterClass)V
这表明内部 class 的方法未能正确重命名。
Holger 在他的评论中提供了解决方案。问题是我只是重新映射外部 class 的 class 文件。然而,内部 class 也有自己的 class 文件。解决方案是将 MyClassRemapper
应用到它并写出来。