I run into a StackOverflow error of the AspectJ compiler today and I thought I should share it on StackOverflow :-) To reproduce the error I made a toy example
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());
}
}
Trying to compile this code results in the following error:
java.lang.StackOverflowError
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)
However, if I modify the Generics in the Node class to
public abstract class Node<T,Q extends Node<T,?>> implements WithParent<Q>{
...
(notice the ? instead of Q), the program works, and prints what you would expect:
Node (content=leaf, parent=Node (content=root, parent=null))
Node (content=root, parent=null)
even though Eclipse complains that
The method setParent(StringContentNode) is undefined for the type StringContentNode
if I leave the WithParent Interface empty as is now, or that
The type StringContentNode must implement the inherited abstract method WithParent.getParent()
If I define the getter and the setter in the interface.
Should I signal the bug? Is there a cleaner way to achieve the same functionality, without incurring in any weird compilation issue?
Thanks!
StackOverflowError is a runtime error which points to serious problems that cannot be caught by an application. The java. lang. StackOverflowError indicates that the application stack is exhausted and is usually caused by deep or infinite recursion.
To handle StackoverFlowError, you should carefully inspect the stack trace to detect any repeating call patterns in your code. These indicate recursive calls to your code or function. Some traits of recursion: Large thread stacks that appear to repeat.
A stack overflow is a type of buffer overflow error that occurs when a computer program tries to use more memory space in the call stack than has been allocated to that stack.
It seems no one will propose a workaround that allows to keep implementing recursive generics interfaces through AspectJ in spite of the bug. It would have been interesting to find such a solution but I guess it is not likely to exist.
Please cast your votes on the bug report https://bugs.eclipse.org/bugs/show_bug.cgi?id=526707 if you can.
Cheers.
update: according to Tim Wright the bug is fixed in version 1.9.5 of aspectjrt
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With