Community
Participate
Working Groups
While editing Java code, I encountered a StackOverflowError in Eclipse 3.3M7 at line 446 of Bindings.java in the method Bindings.findOverriddenMethodInHierarchy(), which is called downstream from Scope.getJavaLangObject() as shown in the stacktrace below. I'm running Eclipse 3.3M7 under Windows XP. Looking at the source code, Binding.findOverriddenMethodInHierachy() searches for an overridden method on an IBindingType recursively traversing upwards through the type's inheritence hierarchy. ie. If it doesn't find an overridden method on an ITypeBinding, it calls ITypeBinding.getSuperclass(), and if that is not null, recursively calls findOverriddenMethodInHierachy() passing that super class, until either a method is found or no super class is found. This method is only safe if the ITypeBinding hierarchy is guaranteed to never become circular. If the hierarchy somehow becomes circular, a StackOverflowError occurs. Somehow or another, the type hierarchy modelled by ITypeBinding must have become circular, and thus traversing upwards through getSuperclass() becomes circular resulting in the StackOverflowError. I have no idea how I caused this to happen. I was editing a Java class at the time, and changing one of its method's signatures. I was typing by hand - ie. just editing code - not using a refactoring tool. The class wasn't new, nor was I changing its inheritance hierarchy. However, from the log its impossible to know whether the StackOverflowError came about due to the compiler compiling the class I was editing, or whether it was doing some other background task. Note the error message its says "Override indicator installation job" - perhaps this is a clue. The class I happened to be editing at the time was a subclass DefaultTableCellRenderer - and the method I was changing on my class was its implementation of getTableCellRendererComponent - which just so happens to be an overridden method.... but I have no idea whether this is relevant. That's about all I know - I don't know the specific steps of how to reproduce the bug, or whether it was related to what I was doing at the time. !ENTRY org.eclipse.core.jobs 4 2 2007-05-10 07:38:17.558 !MESSAGE An internal error occurred during: "Override indicator installation job". !STACK 0 java.lang.StackOverflowError at org.eclipse.jdt.internal.compiler.util.HashtableOfPackage.get(HashtableOfPackage.java:51) at org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment.getPackage0(LookupEnvironment.java:939) at org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment.getType(LookupEnvironment.java:994) at org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment.getResolvedType(LookupEnvironment.java:946) at org.eclipse.jdt.internal.compiler.lookup.Scope.getJavaLangObject(Scope.java:2008) at org.eclipse.jdt.core.dom.DefaultBindingResolver.resolveWellKnownType(DefaultBindingResolver.java:1635) at org.eclipse.jdt.core.dom.RecoveredTypeBinding.getSuperclass(RecoveredTypeBinding.java:244) at org.eclipse.jdt.internal.corext.dom.Bindings.findOverriddenMethodInHierarchy(Bindings.java:444) at org.eclipse.jdt.internal.corext.dom.Bindings.findOverriddenMethodInHierarchy(Bindings.java:446) at org.eclipse.jdt.internal.corext.dom.Bindings.findOverriddenMethodInHierarchy(Bindings.java:446) at org.eclipse.jdt.internal.corext.dom.Bindings.findOverriddenMethodInHierarchy(Bindings.java:446) at org.eclipse.jdt.internal.corext.dom.Bindings.findOverriddenMethodInHierarchy(Bindings.java:446) at org.eclipse.jdt.internal.corext.dom.Bindings.findOverriddenMethodInHierarchy(Bindings.java:446) at org.eclipse.jdt.internal.corext.dom.Bindings.findOverriddenMethodInHierarchy(Bindings.java:446) at org.eclipse.jdt.internal.corext.dom.Bindings.findOverriddenMethodInHierarchy(Bindings.java:446) at org.eclipse.jdt.internal.corext.dom.Bindings.findOverriddenMethodInHierarchy(Bindings.java:446) at org.eclipse.jdt.internal.corext.dom.Bindings.findOverriddenMethodInHierarchy(Bindings.java:446) at org.eclipse.jdt.internal.corext.dom.Bindings.findOverriddenMethodInHierarchy(Bindings.java:446) at org.eclipse.jdt.internal.corext.dom.Bindings.findOverriddenMethodInHierarchy(Bindings.java:446) at org.eclipse.jdt.internal.corext.dom.Bindings.findOverriddenMethodInHierarchy(Bindings.java:446) at org.eclipse.jdt.internal.corext.dom.Bindings.findOverriddenMethodInHierarchy(Bindings.java:446) at org.eclipse.jdt.internal.corext.dom.Bindings.findOverriddenMethodInHierarchy(Bindings.java:446) at org.eclipse.jdt.internal.corext.dom.Bindings.findOverriddenMethodInHierarchy(Bindings.java:446) at org.eclipse.jdt.internal.corext.dom.Bindings.findOverriddenMethodInHierarchy(Bindings.java:446) at org.eclipse.jdt.internal.corext.dom.Bindings.findOverriddenMethodInHierarchy(Bindings.java:446) at org.eclipse.jdt.internal.corext.dom.Bindings.findOverriddenMethodInHierarchy(Bindings.java:446) <repeated about 1000 times until stack overflows>
The problem seems to occur before the RecoveredTypeBinding is reached. For this binding, we set the superclass to java.lang.Object so this should be fine. The only problem I can see is if we set Object to be the superclass of Object as a recovered binding. But this would not produce the stack trace we are seeing here. Martin, any clue?
If you get it again, please try to remember what you did.
I don't know what it could be...
We definitely need a reproducable test case for this one.
I just realized the analysis I made in the original bug report I filed was flawed. Stack traces of course, are logged from the from the top of the stack down.... In otherwords the top line as it appears in log of a stack trace is the deepest method called, while the next line is the caller of that function etc. Since the first line reported in the log for the stack trace is HashtableOfPackage.java:51 - presumably that is the line of code being executed when the stack overflow occured. The problem with this revised reasoning, is that it implies that somehow the JVM spun in an recursive loop for around 1000 iterations at Bindings.java:446, until it miraculously broke free of this loop, only to then run out of stack space a mere 8 stack frames deeper.... NOTE: While for the sake of brievity I didn't attach the full log - there is absolutely nothing else logged other than approx 1000 lines to calls to Bindings.java:446 - there's no hint as to the root caller of Bindings.findOverriddenMethodInHierarchy Since none of this makes sense, I assume that a side effect is of a StackOverflowError is that the stack trace that is logged is misleading in some respect.... Anyway, while I doubt this revised reasoning is helpful, I thought I should mention it, incase my initial flawed report was steering analysis of the problem down a wrong path. If it happens to me again, I'll update this issue with more information.
Thanks for the additional info. But it doesn't change much since we need to understand the 1000's call to getSuperclass(). For now there is no much I can do for RC1. But if we get a reproducable test case, we might be able to fix it post RC1.
Closing as WORKSFORME. I could never get a reproducable test case. Please reopen if you get it again.
Verified for 3.4M1 using build I20070806-1800.
Steps to reproduce in I20071106-0816: - paste to Package Explorer: package p; public class A { void m() { } } //-- package p; public class C extends A { void m() {} } - remove the 'JRE System Library' from the build path - go to Java Browsing perspective - open p.A (by using the browsing views) - open p.C (by using the browsing views) - open p.A (by using the browsing views) => boom The type binding for p.A from the ASTProvider has an invalid superclass: SUPERCLASS: Object NAME: 'Object' KEY: 'Recovered#referenceBindingLjava/lang/Object;0<>' IS RECOVERED: true QUALIFIED NAME: 'Object' KIND: isClass GENERICS: (non-generic, non-parameterized) CREATE ARRAY TYPE (+1): Object[] ORIGIN: isTopLevel IS FROM SOURCE: false PACKAGE: p DECLARING CLASS: null DECLARING METHOD: null MODIFIERS: (empty string) BINARY NAME: null TYPE DECLARATION: Object ERASURE: Object SUPERCLASS: Object // this is the same invalid 'Object' binding again INTERFACES (0) DECLARED TYPES (0) DECLARED FIELDS (0) DECLARED METHODS (0) IS SYNTHETIC: false IS DEPRECATED: false ANNOTATIONS (0) > CompilationUnit: p.Object (does not exist)
*** Bug 208997 has been marked as a duplicate of this bug. ***
I can now reproduce the problem with 3.4M3 and scenario described at comment 9.
*** Bug 209031 has been marked as a duplicate of this bug. ***
Created attachment 82336 [details] Proposed patch Olivier, can you review this patch? Thanks
Jérôme, this should be backported for 3.3.2.
The recovered 'Object' type binding is still a bit strange, since it has name "Object" and a package binding with name "p" but a qualifiedName "Object". Expected: either qualifiedName "p.Object", or better yet "java.lang.Object" and a package binding for "java.lang" (since ITypeBinding.getSuperclass() suggests to test for "java.lang.Object").
In this specific case, we could indeed do better. We retrieve a missing binary type binding that contains the right package binding and the right fully qualified name. So we should improve: -getPackage() to return the package binding corresponding to the package binding inside the missing binary type binding. This will involve updating the doc for ITypeBinding#getPackage(). - getQualifiedName() to return a consistent name wrt the package name - getName() same for the single name Of course getSuperclass() should also be fixed, but for this, we have a fix already.
I opened bug 209510 for problem noticed by Markus at comment 15...
Created attachment 82427 [details] Better proposed patch This patch uses new implemented RecoveredTypeBinding.equals(Object) method instead of identity test. Added new test using code illustrating this peculiar need. Also move the test cases for this bug in a new test suite as this kind of tests do not require the Converter* projects to be copied... Olivier, please review it again, thanks
equals(Object) is too complicated to fix this issue. Combined with bug 209150, we can have a simpler solution to test equality: getQualifiedName().equals("java.lang.Object") I'll be back soon with a new patch...
Created attachment 82455 [details] New proposed patch
+1. Should be backported to 3.3.2.
The patch has issues with array types. I need to rewrite it a little bit...
Created attachment 82466 [details] Last (?) proposed patch ITypeBinding.getPackage() API specifies that it returns null for array type. This patch do the right thing now. It also fixes problem with missing [] in array types qualified name (I've added a new test for this). Also (Markus) updated the javadoc comment for getPackage() method...
Created attachment 82472 [details] Last proposed patch fixed by Olivier Olivier modified my previous patch after his review. getReferenceBinding() method of RecoveredTypeBinding now returns the reference of the most inner type if any. This allow to simplify the getQualifiedName() method and make it safer. Thanks Olivier
Released for 3.4M4 in HEAD stream.
+1 for backporting to 3.3.2
Created attachment 82754 [details] Proposed patch for 3.3.2
Released for 3.3.2 in R3_3_maintenance stream.
Since there is no workaround and a StackOverFlowError is always bad, this fix needs to be included in 3.3.2. Philippe please approve.
+1 for 3.3.2
*** Bug 210052 has been marked as a duplicate of this bug. ***
Verified for 3.4 M4 using build I20071211-0010
*** Bug 237022 has been marked as a duplicate of this bug. ***