I'm using JDiagram JAR like below
Diagram myDigram = new Diagram();
myDigram.routeAllLinks();
This code works fine when run with JRE 7 however when it is run with JRE 8, following error is being thrown:
java.lang.StackOverflowError
at java.util.Collections.sort(Unknown Source)
at com.mindfusion.common.ExtendedArrayList.sort(Unknown Source)
at java.util.Collections.sort(Unknown Source)
at com.mindfusion.common.ExtendedArrayList.sort(Unknown Source)
at java.util.Collections.sort(Unknown Source)
at com.mindfusion.common.ExtendedArrayList.sort(Unknown Source)
I followed the stack trace to JDiagram decompiled code. Observed that routeAllLinks() calls RouteLinks() on another object (say router) and at one more level deep ExtendedArrayList.sort() which is appeared in error stack trace is called. The "ExtendedArrayList" in JDiagram extends ArrayList and contains a method named "sort()" which has following definition.
public void sort(Comparator<? super T> paramComparator)
{
Collections.sort(this, paramComparator);
}
On Google I found out that JRE 8 has introduced List.sort() and delegates the Collections.sort() calls to collection's (ExtendedArrayList in my case) sort method. And so library ExtendedArrayList.sort() became an override. And it creates an infinite recursion which results in stackoverflow. I could reproduce this issue even with small piece of code as well now.
Also
- Our original class which creates JDiagram object, is being loaded at runtime by some other component in our product. We have very little control over the loading of our program.
- We have found out that latest version of JDiagram has fixed this issue by replacing sort() with sortJ7() method. However, we cannot upgrade the library at this moment. JDiagram is a licensed API.
- ExtendedArrayList is being instantiated by JDiagram internally and so we cannot alter it from our code.
We have tried following solutions which didn't work so far
- Java Proxy: Because our code does not call ExtendedArrayList directly and also 'Diagram' does not have any interface.
- Spring AOP: We are not using spring and also our program is loaded runtime by other component.
- AspectJ: By now, this was apparently a solution. However, it also didn't work as we are not able to weave our program at runtime. Not sure if someone could make it work.
Kindly let me know if any point needs elaboration. Any help is welcome. Thanks.
UPDATE So far, javassist is the best approach however there JDiagram obfuscation is preventing the solution to work correctly. We have kind of assumed that it is impossible (have to say) to fix considering our release date on our head. We have started process to upgrade library. And meanwhile removed a small feature from our application which was being provided by routeAllLinks() method.. :-( thanks everyone for your help. I'll be continuing my research on this issue as I found it really intriguing and challenging.. I'll update the post if I could resolve it.. And I'll be giving bounty to @gontard for his javassist approach as I'm continuing my research with it. Thanks.