【问题标题】:AspectJ compiler bug leads to StackOverflowErrorAspectJ 编译器错误导致 StackOverflowError
【发布时间】:2017-10-31 07:47:27
【问题描述】:

我今天遇到了 AspectJ 编译器的 * 错误,我想我应该在 * 上分享它:-) 为了重现错误,我做了一个玩具示例

public abstract class Node<T,Q extends Node<T,Q>> implements WithParent<Q>{
    private T content;
    //getter and setter for content
}
public aspect WithParentAspect {
    private T WithParent<T>.parent;
    public T WithParent<T>.getParent() {
        return this.parent;
    }
    public void WithParent<T>.setParent(T parent) {
        this.parent=parent;
    }
}
public interface WithParent<T> { }
public class StringContentNode extends Node<String, StringContentNode>{
    public static void main (String [] args) {
        StringContentNode root = new StringContentNode();
        StringContentNode leaf = new StringContentNode();

        root.setContent("root");
        leaf.setContent("leaf");
        leaf.setParent(root);
        System.out.println(leaf);                   
        System.out.println(leaf.getParent());
    }
}

尝试编译此代码会导致以下错误:

java.lang.*Error
at org.aspectj.weaver.World$TypeMap.put(World.java:1198)
at org.aspectj.weaver.World.resolve(World.java:398)
at org.aspectj.weaver.World.resolve(World.java:277)
at org.aspectj.weaver.World.resolve(World.java:229)
at org.aspectj.weaver.UnresolvedType.resolve(UnresolvedType.java:615)
at org.aspectj.weaver.ReferenceType.isAssignableFrom(ReferenceType.java:621)
at org.aspectj.weaver.ReferenceType.isAssignableFrom(Ref ...
bleFrom(ReferenceType.java:459)
at org.aspectj.weaver.TypeVariable.isASubtypeOf(TypeVariable.java:201)  

但是,如果我将 Node 类中的泛型修改为

public abstract class Node<T,Q extends Node<T,?>> implements WithParent<Q>{
...

(注意 ? 而不是 Q),该程序可以运行,并打印出您所期望的:

Node (content=leaf, parent=Node (content=root, parent=null))
Node (content=root, parent=null)

即使 Eclipse 抱怨

未为 StringContentNode 类型定义方法 setParent(StringContentNode)

如果我现在将 WithParent 接口留空,或者

StringContentNode 类型必须实现继承的抽象方法 WithParent.getParent()

如果我在界面中定义了 getter 和 setter。
我应该发出错误信号吗?有没有更简洁的方法来实现相同的功能,而不会产生任何奇怪的编译问题? 谢谢!

【问题讨论】:

  • 从我的角度来看,当编译器抛出异常时,我认为它是一个错误,无论您尝试使用多么复杂的构造。所以我认为这绝对值得报道。
  • 我报告了这个错误,bugs.eclipse.org/bugs/show_bug.cgi?id=526707 请问您是否能够复制该错误?谢谢...
  • @EmanueleFusco 我相信这是因为这个“问题”实际上并不是一个问题。每天都会报告无数的错误,但没有人真正为每一个错误在 * 上创建一个问题。
  • @Caregh 好吧,例如告诉我您可以复制错误,这样我就可以确定我提交的错误报告在处理时实际上会显示存在错误。我也很想知道其他人是否以不同的方式使用 AspectJ 来实现代表,正如我在问题和赏金中所问的那样......无论如何,如果我冒犯了某人,我很抱歉。干杯...
  • @kriegaex 这是一个非常合理的用例,我们实际上给它起了一个名字,它叫做 recursiveself-referencing自绑定泛型,一个突出的例子是JDK中Enum类的声明:abstract class Enum&lt;E extends Enum&lt;E&gt;&gt; ...

标签: java stack-overflow aspectj compiler-bug


【解决方案1】:

似乎没有人会提出一种解决方法,允许通过 AspectJ 继续实现递归泛型接口,尽管存在错误。 找到这样的解决方案会很有趣,但我想它不太可能存在。

如果可以的话,请对错误报告https://bugs.eclipse.org/bugs/show_bug.cgi?id=526707 投票。

干杯。


更新:根据 Tim Wright 的说法,该错误已在 aspectjrt 的 1.9.5 版中修复

【讨论】: