Community
Participate
Working Groups
I20060504-0920 I just started up the build, imported all required plugins as binary and let autobuild rebuild the workspace. Got the NPE below in the log, with a very long problem message, starting with this: ([..] are my omissions): Exception occurred during problem detection:----------------------------------- SOURCE BEGIN ------------------------------------- /******************************************************************************* * Copyright (c) 2000, 2006 IBM Corporation and others. * All rights reserved. This program and the accompanying materials [..] package org.eclipse.jdt.ui; [..] public final class JavaUI { [.. full CU source ..] java.lang.NullPointerException at org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader.getSourceName(ClassFileReader.java:567) at org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding.<init>(BinaryTypeBinding.java:162) at org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment.createBinaryTypeFrom(LookupEnvironment.java:561) at org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment.createBinaryTypeFrom(LookupEnvironment.java:558) at org.eclipse.jdt.internal.compiler.Compiler.accept(Compiler.java:272) at org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment.askForType(LookupEnvironment.java:102) at org.eclipse.jdt.internal.compiler.lookup.UnresolvedReferenceBinding.resolve(UnresolvedReferenceBinding.java:43) at org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding.resolveUnresolvedType(BinaryTypeBinding.java:138) at org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding.superclass(BinaryTypeBinding.java:907) at org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding.implementsInterface(ReferenceBinding.java:808) at org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding.isCompatibleWith0(ReferenceBinding.java:937) at org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding.isCompatibleWith(ReferenceBinding.java:890) at org.eclipse.jdt.internal.compiler.ast.Assignment.resolveType(Assignment.java:196) at org.eclipse.jdt.internal.compiler.ast.Expression.resolve(Expression.java:880) at org.eclipse.jdt.internal.compiler.ast.Block.resolve(Block.java:101) at org.eclipse.jdt.internal.compiler.ast.IfStatement.resolve(IfStatement.java:236) at org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration.resolveStatements(AbstractMethodDeclaration.java:432) at org.eclipse.jdt.internal.compiler.ast.MethodDeclaration.resolveStatements(MethodDeclaration.java:179) at org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration.resolve(AbstractMethodDeclaration.java:403) at org.eclipse.jdt.internal.compiler.ast.TypeDeclaration.resolve(TypeDeclaration.java:1054) at org.eclipse.jdt.internal.compiler.ast.TypeDeclaration.resolve(TypeDeclaration.java:1101) at org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration.resolve(CompilationUnitDeclaration.java:353) at org.eclipse.jdt.internal.compiler.Compiler.resolve(Compiler.java:650) at org.eclipse.jdt.internal.compiler.Compiler.resolve(Compiler.java:689) at org.eclipse.jdt.internal.core.CompilationUnitProblemFinder.process(CompilationUnitProblemFinder.java:176) at org.eclipse.jdt.internal.core.CompilationUnitProblemFinder.process(CompilationUnitProblemFinder.java:248) at org.eclipse.jdt.internal.core.ReconcileWorkingCopyOperation.makeConsistent(ReconcileWorkingCopyOperation.java:152) at org.eclipse.jdt.internal.core.ReconcileWorkingCopyOperation.executeOperation(ReconcileWorkingCopyOperation.java:71) at org.eclipse.jdt.internal.core.JavaModelOperation.run(JavaModelOperation.java:720) at org.eclipse.jdt.internal.core.JavaModelOperation.runOperation(JavaModelOperation.java:779) at org.eclipse.jdt.internal.core.CompilationUnit.reconcile(CompilationUnit.java:1123) at org.eclipse.jdt.internal.core.CompilationUnit.reconcile(CompilationUnit.java:1095) at org.eclipse.jdt.internal.corext.util.JavaModelUtil.reconcile(JavaModelUtil.java:702) at org.eclipse.jdt.internal.ui.actions.SelectionConverter.getElementAtOffset(SelectionConverter.java:210) at org.eclipse.jdt.internal.ui.actions.SelectionConverter.getElementAtOffset(SelectionConverter.java:144) at org.eclipse.jdt.internal.ui.actions.SelectionConverter.getElementAtOffset(SelectionConverter.java:136) at org.eclipse.jdt.internal.ui.text.JavaElementProvider.getInformation2(JavaElementProvider.java:84) at org.eclipse.jface.text.information.InformationPresenter.computeInformation(InformationPresenter.java:346) at org.eclipse.jface.text.AbstractInformationControlManager.doShowInformation(AbstractInformationControlManager.java:821) at org.eclipse.jface.text.AbstractInformationControlManager.showInformation(AbstractInformationControlManager.java:811) at org.eclipse.jdt.internal.ui.javaeditor.JavaSourceViewer.doOperation(JavaSourceViewer.java:166) at org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitEditor$AdaptedSourceViewer.doOperation(CompilationUnitEditor.java:201) at org.eclipse.ui.texteditor.TextOperationAction$1.run(TextOperationAction.java:131) at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:67) at org.eclipse.ui.texteditor.TextOperationAction.run(TextOperationAction.java:129) at org.eclipse.jface.action.Action.runWithEvent(Action.java:499) at org.eclipse.ui.commands.ActionHandler.execute(ActionHandler.java:185) at org.eclipse.ui.internal.handlers.LegacyHandlerWrapper.execute(LegacyHandlerWrapper.java:109) at org.eclipse.core.commands.Command.executeWithChecks(Command.java:461) at org.eclipse.core.commands.ParameterizedCommand.executeWithChecks(ParameterizedCommand.java:424) at org.eclipse.ui.internal.handlers.HandlerService.executeCommand(HandlerService.java:160) at org.eclipse.ui.internal.keys.WorkbenchKeyboard.executeCommand(WorkbenchKeyboard.java:466) at org.eclipse.ui.internal.keys.WorkbenchKeyboard.press(WorkbenchKeyboard.java:799) at org.eclipse.ui.internal.keys.WorkbenchKeyboard.processKeyEvent(WorkbenchKeyboard.java:846) at org.eclipse.ui.internal.keys.WorkbenchKeyboard.filterKeySequenceBindings(WorkbenchKeyboard.java:564) at org.eclipse.ui.internal.keys.WorkbenchKeyboard.access$3(WorkbenchKeyboard.java:506) at org.eclipse.ui.internal.keys.WorkbenchKeyboard$KeyDownFilter.handleEvent(WorkbenchKeyboard.java:122) at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:66) at org.eclipse.swt.widgets.Display.filterEvent(Display.java:982) at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:927) at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:952) at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:937) at org.eclipse.swt.widgets.Widget.sendKeyEvent(Widget.java:965) at org.eclipse.swt.widgets.Widget.sendKeyEvent(Widget.java:961) at org.eclipse.swt.widgets.Widget.wmChar(Widget.java:1275) at org.eclipse.swt.widgets.Control.WM_CHAR(Control.java:3346) at org.eclipse.swt.widgets.Control.windowProc(Control.java:3246) at org.eclipse.swt.widgets.Display.windowProc(Display.java:4025) at org.eclipse.swt.internal.win32.OS.DispatchMessageW(Native Method) at org.eclipse.swt.internal.win32.OS.DispatchMessage(OS.java:1923) at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:2966) at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:1914) at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:1878) at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:419) at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:143) at org.eclipse.ui.internal.ide.IDEApplication.run(IDEApplication.java:95) at org.eclipse.core.internal.runtime.PlatformActivator$1.run(PlatformActivator.java:78) at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:92) at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:68) at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:400) at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:177) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:585) at org.eclipse.core.launcher.Main.invokeFramework(Main.java:336) at org.eclipse.core.launcher.Main.basicRun(Main.java:280) at org.eclipse.core.launcher.Main.run(Main.java:977) at org.eclipse.core.launcher.Main.main(Main.java:952)
I will investigate.
Closing as WORKSFORME. Since it is not possible to reproduce it and looking at the source code, we don't see how this is possible.
*** Bug 166076 has been marked as a duplicate of this bug. ***
Reopening since we need to understand how this can happened.
(In reply to bug 166076 comment #3) Must be a concurrency issue then. The method is not synchronized and can be called from multiple threads (e.g. compiler and type hierarchy resolver). It is possible that one thread sets this.sourceName temporarily to null just before the arraycopy takes place.
The creation of binding should be synchronized. I don't see why the class file reader would need to be synchronized. Kent, is this doable?
How is the instance of the ClassFileReader available to multiple threads? BinaryTypeBindings create & initialize themselves from the ClassFileReader then throw it away. Is this the source we're talking about on line 567? this.sourceName = new char[name.length - start]; >>System.arraycopy(name, start, this.sourceName, 0, this.sourceName.length); Looks like a bogus VM/jit bug to me. What VM are you guys using?
(In reply to comment #7) > How is the instance of the ClassFileReader available to multiple threads? > > BinaryTypeBindings create & initialize themselves from the ClassFileReader then > throw it away. Are you sure about that? I find it hard to verify that there is no aliasing. i.e. HierarchyResolver.remember stores the object in an array. The object is retrieved in LookupEnvironment.askForType(PackageBinding, char[]) from NameEvironmentAnswer#getBinaryType() which looks shared to me. > > Is this the source we're talking about on line 567? > > this.sourceName = new char[name.length - start]; > >>System.arraycopy(name, start, this.sourceName, 0, this.sourceName.length); > > Looks like a bogus VM/jit bug to me. > > What VM are you guys using? java version "1.5.0_08" Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_08-b03) Java HotSpot(TM) Client VM (build 1.5.0_08-b03, mixed mode)
(In reply to comment #7) > How is the instance of the ClassFileReader available to multiple threads? Easy to see in the debugger: - debug a cleaned runtime workspace - create an empty Java project - open editor for Integer - set a breakpoint in ClassFileReader on line 554 and restart the runtime => debugger hangs in two threads - resume the thread that is building a type hierarchy => now, you have two threads working on the same ClassFileReader, and the NPE can be provoked by "stepwise refinement" > Is this the source we're talking about on line 567? Yes
Here are the stack traces from Markus' steps : The LookupEnvironment & BinaryTypeBinding instances are not the same, but the ClassFileReader instances are. Thread [Worker-1] (Suspended (breakpoint at line 554 in ClassFileReader)) ClassFileReader.getSourceName() line: 554 BinaryTypeBinding.<init>(PackageBinding, IBinaryType, LookupEnvironment) line: 150 LookupEnvironment.createBinaryTypeFrom(IBinaryType, PackageBinding, boolean, AccessRestriction) line: 560 LookupEnvironment.createBinaryTypeFrom(IBinaryType, PackageBinding, AccessRestriction) line: 557 CompilationUnitResolver(Compiler).accept(IBinaryType, PackageBinding, AccessRestriction) line: 272 LookupEnvironment.askForType(PackageBinding, char[]) line: 127 PackageBinding.getTypeOrPackage(char[]) line: 178 ClassScope(Scope).getTypeOrPackage(char[], int) line: 2317 ClassScope(Scope).getType(char[]) line: 2057 SingleTypeReference.getTypeBinding(Scope) line: 44 SingleTypeReference(TypeReference).resolveType(ClassScope) line: 159 SingleTypeReference(TypeReference).resolveSuperType(ClassScope) line: 110 ClassScope.findSupertype(TypeReference) line: 1106 ClassScope.connectSuperclass() line: 826 ClassScope.connectTypeHierarchy() line: 951 CompilationUnitScope.connectTypeHierarchy() line: 290 LookupEnvironment.completeTypeBindings() line: 197 CompilationUnitResolver(Compiler).beginToCompile(ICompilationUnit[]) line: 387 CompilationUnitResolver.resolve(CompilationUnitDeclaration, ICompilationUnit, NodeSearcher, boolean, boolean, boolean) line: 836 CompilationUnitResolver.resolve(ICompilationUnit, IJavaProject, NodeSearcher, Map, WorkingCopyOwner, boolean, ...) line: 510 ASTParser.internalCreateAST(IProgressMonitor) line: 835 ASTParser.createAST(IProgressMonitor) line: 628 ASTProvider$1.run() line: 605 SafeRunner.run(ISafeRunnable) line: 37 ASTProvider.createAST(IJavaElement, IProgressMonitor) line: 600 ASTProvider.getAST(IJavaElement, ASTProvider$WAIT_FLAG, IProgressMonitor) line: 514 JavaEditor$8.run(IProgressMonitor) line: 3250 Worker.run() line: 58 Thread [Worker-3] (Suspended (breakpoint at line 554 in ClassFileReader)) ClassFileReader.getSourceName() line: 554 BinaryTypeBinding.<init>(PackageBinding, IBinaryType, LookupEnvironment) line: 150 LookupEnvironment.createBinaryTypeFrom(IBinaryType, PackageBinding, boolean, AccessRestriction) line: 560 LookupEnvironment.createBinaryTypeFrom(IBinaryType, PackageBinding, AccessRestriction) line: 557 HierarchyResolver.accept(IBinaryType, PackageBinding, AccessRestriction) line: 99 LookupEnvironment.askForType(char[][]) line: 101 UnresolvedReferenceBinding.resolve(LookupEnvironment, boolean) line: 43 BinaryTypeBinding.resolveType(ReferenceBinding, LookupEnvironment, boolean) line: 97 BinaryTypeBinding.superclass() line: 909 HierarchyResolver.resolve(IGenericType) line: 528 IndexBasedHierarchyBuilder(HierarchyBuilder).buildSupertypes() line: 115 IndexBasedHierarchyBuilder.build(boolean) line: 134 TypeHierarchy.compute() line: 300 TypeHierarchy.refresh(IProgressMonitor) line: 1237 CreateTypeHierarchyOperation.executeOperation() line: 90 CreateTypeHierarchyOperation(JavaModelOperation).run(IProgressMonitor) line: 720 CreateTypeHierarchyOperation(JavaModelOperation).runOperation(IProgressMonitor) line: 779 BinaryType.newSupertypeHierarchy(WorkingCopyOwner, IProgressMonitor) line: 793 BinaryType.newSupertypeHierarchy(IProgressMonitor) line: 745 SuperTypeHierarchyCache.getTypeHierarchy(IType, IProgressMonitor) line: 120 SuperTypeHierarchyCache.getTypeHierarchy(IType) line: 80 SuperTypeHierarchyCache.getMethodOverrideTester(IType) line: 89 OverrideIndicatorLabelDecorator.getOverrideIndicators(IMethod) line: 162 OverrideIndicatorLabelDecorator.computeAdornmentFlags(Object) line: 129 OverrideIndicatorLabelDecorator.decorate(Object, IDecoration) line: 261 LightweightDecoratorDefinition.decorate(Object, IDecoration) line: 259 LightweightDecoratorManager$LightweightRunnable.run() line: 71 SafeRunner.run(ISafeRunnable) line: 37 Platform.run(ISafeRunnable) line: 850 LightweightDecoratorManager.decorate(Object, DecorationBuilder, LightweightDecoratorDefinition) line: 336 LightweightDecoratorManager.getDecorations(Object, DecorationBuilder) line: 322 DecorationScheduler$1.ensureResultCached(Object, boolean, IDecorationContext) line: 357 DecorationScheduler$1.run(IProgressMonitor) line: 322 Worker.run() line: 58
We 3 choices to fix this problem: 1. Jerome -> change your cache to hold onto the class file bytes instead of the ClassFileReader instances. ClassFileReader was never designed to be thread safe. 2. Or set each accessor that uses lazy initialization to be a synchronized method. 3. Or fix the problem for #getSourceName() by changing it to [and any other accessors]: public char[] getSourceName() { if (this.sourceName != null) return this.sourceName; char[] name = getInnerSourceName(); // member or local scenario if (name == null) { name = getName(); // extract from full name int start; if (isAnonymous()) { start = CharOperation.indexOf('$', name, CharOperation.lastIndexOf('/', name) + 1) + 1; } else { start = CharOperation.lastIndexOf('/', name) + 1; } if (start > 0) { name = new char[name.length - start]; System.arraycopy(name, start, name, 0, name.length); } this.sourceName = name; } return this.sourceName; } My preference is #1
The other potential fix is to pre-initialize all lazy fields when fullyInitialize is set to true (which it is in this case). This would mean the cached ClassFileReader instance would basically be a read-only object. Any other choices? Any opinions on which one we should do?
As discussed in JDT Core call, we should do option #3, which makes it thread safe and avoids deadlocks.
Changed getSourceName() as described in comment #11. To reproduce, follow the steps in comment #9.
Released for 3.3 M4 in HEAD stream
Verified for 3.3M4 with I20061212-0010.
Created attachment 114678 [details] Backport of the fix to 3.2.2