Community
Participate
Working Groups
20040413 Found this exception in the console. My guess is that came from visiting the AST from multiple threads. The cursor managment doesn't seem to be thread save. java.lang.NullPointerException at java.lang.Throwable.<init>(Throwable.java) at java.lang.Throwable.<init>(Throwable.java) at java.lang.NullPointerException.<init>(NullPointerException.java:60) at org.eclipse.jdt.core.dom.ASTNode$NodeList.releaseCursor (ASTNode.java) at org.eclipse.jdt.core.dom.ASTNode.acceptChildren(ASTNode.java) at org.eclipse.jdt.core.dom.CompilationUnit.accept0 (CompilationUnit.java ) at org.eclipse.jdt.core.dom.ASTNode.accept(ASTNode.java) at org.eclipse.jdt.internal.ui.javaeditor.OverrideIndicatorManager.updat eAnnotations(OverrideIndicatorManager.java) at org.eclipse.jdt.internal.ui.javaeditor.OverrideIndicatorManager.recon ciled(OverrideIndicatorManager.java:271) at org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitEditor.reconcil ed(CompilationUnitEditor.java) at org.eclipse.jdt.internal.ui.text.java.JavaReconcilingStrategy.reconci le(JavaReconcilingStrategy.java) at org.eclipse.jdt.internal.ui.text.java.JavaReconcilingStrategy.reconci le(JavaReconcilingStrategy.java:118) at org.eclipse.jface.text.reconciler.CompositeReconcilingStrategy.reconc ile(CompositeReconcilingStrategy.java) at org.eclipse.jdt.internal.ui.text.JavaCompositeReconcilingStrategy.rec oncile(JavaCompositeReconcilingStrategy.java) at org.eclipse.jface.text.reconciler.MonoReconciler.process (MonoReconcil er.java:76) at org.eclipse.jface.text.reconciler.AbstractReconciler$BackgroundThread .run(AbstractReconciler.java)
Jim, any comment?
The problem does indeed look like its caused by multiple threads accessing the same AST. No aspect of ASTs is thread-safe (not even for just reading). ASTNode * AST nodes are <b>not</b> thread-safe; this is true even for trees that * are read-only. If synchronization is required, consider using the common AST * object that owns the node; that is, use * <code>synchronize (node.getAST()) {...}</code>.
Reopening. Investigate how to make ASTs thread safe for reading.
Ensuring that AST is safe for separate threads reading the same AST required two kinds of changes: (1) ASTNode.NodeList.newCursor() and releaseCursor(). Both of these methods are used by ASTVisitor while visiting nodes. The methods modify an internal list of known cursors. Adding internal synch on NodeList.this makes these thread-safe for readers. Minor performance impact only for ASTVisitors. (2) various getXXX() methods on node subclasses. These methods do lazy init, which actually creates new nodes and modifies the node being accessed. There are no callbacks during lazy init (there is already a mechanism that prevents callbacks from within callbacks). Adding internal sync on ASTNode.this make lazy init sequence thread-safe for readers. No issue with performance since lazy init is not on critical path (nodes created by ASTParser are explicitly init'd). Updated comment on ASTNode to say that ASTs are safe for multiple readers (but still utterly unsafe if there are any writers).
Great, thank a lot, Jim! I was thinking that some more locks ar required in the BindingResolver at places where the binding elements are created and cached.
Reopening while investigating possible need for further locks.
Indeed, two more kinds of changes were required: (3) AST.disableEvents Lazy init causes this instance variable to be modified. Adding internal sync (on AST.internalAstLock) to make event management thread-safe for readers. (4) BindingResolver Any of the methods could be called by a reader. Adding internal sync on DefaultBindingResolver to make binding lookup thread-safe for readers.
*** Bug 58428 has been marked as a duplicate of this bug. ***
Verified that code is in 200405180816