使用Javassist
,我试图将一行代码插入到方法体中。这是对intellij-IDE
中标签文本颜色的简单修改。我在尝试这样做时得到以下错误:
- 原因:java.lang.LinkageError:loader com.intellij.util.lang. UrlClassLoader@d2cc05a尝试为com. intellij. ui. components. labels. LinkLabel重复类定义。(com.intellij.ui.components.labels.LinkLabel在加载器com.intellij.util.lang. UrlClassLoader@d2cc05a的未命名模块中,父加载器'platform')*
这意味着我试图修改的类已经被Java类加载器加载了(至少我喜欢这样认为)。下面给出了代码的示例:
private static void test() {
try {
ClassPool cp = ClassPool.getDefault();
CtClass cc = cp.get("com.intellij.ui.components.labels.LinkLabel");
CtMethod cm = cc.getDeclaredMethod("getTextColor");
cm.insertBefore("System.out.println(\"helloworld\");");
cc.toClass(); // <--- the problem
} catch (final Throwable e) {
e.printStackTrace();
}
}
字符串
作为参考,下面是访问的类:intellij link
Rafael Winterhalter在几年前评论了一个类似的问题(链接)。不幸的是,我对Javassist
的了解限制了我找到合适的解决方案。
有什么办法解决这个问题吗?
**更新:**一个最小的,可重复的例子可以在这里找到:github link的
1条答案
按热度按时间iswrvxsc1#
我知道这是一个老问题了,但是当你在google上搜索“重复的类定义javassist”时,它是最常见的结果,所以我不妨分享一下可能的解决方案。
您遇到的问题是因为类已经加载到类池中。在将类加载到类池之前,必须修改/重新定义类。
在您的特定问题中,您试图重新定义
com.intellij.ui.components.labels.LinkLabel
。这个类有一个名为ourVisitedLinks
的静态字段。这个静态字段将强制在第一次提到LinkLabel
类时加载LinkLabel
类。当调用
cc.toClass()
时,实际上是引用LinkLabel
类,并将该类加载到类池中,因为静态字段ourVisitedLinks
已初始化。因此,LinkLabel
类在加载类的修改版本之前被隐式加载到类池中。我承认我并不理解javassist中发生的一切。我只知道
cc.toClass()
会因为静态字段被初始化而抢先将类加载到类池中。您将不得不改为调用
cc.toClass(SomeNeighbor.class)
。SomeNeighbor.class
是我为示例创建的一个虚构类。它只需要是一个类,是在同一个包中的类,你试图重新定义。LinkLabel
类有以下neighbors,它们共享同一个包com.intellij.ui.components.labels
:您可以选择这5个类中的任何一个作为邻居,只要该类没有
LinkLabel
的任何直接或传递静态依赖项。这是问题中示例的更正代码。在问题中分享的github链接不幸的是不再可访问,所以我不能提供一个完美的可执行示例。
字符串