diff --git a/java/java-impl/src/com/intellij/psi/impl/compiled/ClsFileImpl.java b/java/java-impl/src/com/intellij/psi/impl/compiled/ClsFileImpl.java index f081f8ecb5e7..d4a528438846 100644 --- a/java/java-impl/src/com/intellij/psi/impl/compiled/ClsFileImpl.java +++ b/java/java-impl/src/com/intellij/psi/impl/compiled/ClsFileImpl.java @@ -33,6 +33,7 @@ import com.intellij.util.ArrayUtil; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.lang.ref.SoftReference; import java.util.List; @@ -355,33 +356,48 @@ public class ClsFileImpl extends ClsRepositoryPsiElement @NotNull public StubTree getStubTree() { - SoftReference stub = myStub; - StubTree stubHolder = stub == null ? null : stub.get(); + ApplicationManager.getApplication().assertReadAccessAllowed(); + + final StubTree derefd = derefStub(); + if (derefd != null) return derefd; + + StubTree stubHolder = StubTree.readOrBuild(getProject(), getVirtualFile()); if (stubHolder == null) { - synchronized (lock) { - stub = myStub; - stubHolder = stub == null ? null : stub.get(); - if (stubHolder != null) { - return stubHolder; - } - stubHolder = StubTree.readOrBuild(getProject(), getVirtualFile()); - if (stubHolder == null) { - // Must be corrupted classfile - LOG.info("Class file is corrupted: " + getVirtualFile().getPresentableUrl()); + // Must be corrupted classfile + LOG.info("Class file is corrupted: " + getVirtualFile().getPresentableUrl()); - stubHolder = new StubTree(new PsiJavaFileStubImpl("corrupted.classfiles", true)); - } - - myStub = new SoftReference(stubHolder); - ((PsiFileStubImpl)stubHolder.getRoot()).setPsi(this); - - synchronized (MIRROR_LOCK) { - myMirrorFileElement = null; - } - myPackageStatement = new ClsPackageStatementImpl(this); + StubTree emptyTree = new StubTree(new PsiJavaFileStubImpl("corrupted.classfiles", true)); + setStubTree(emptyTree); + return emptyTree; + } + + synchronized (lock) { + final StubTree derefdOnLock = derefStub(); + if (derefdOnLock != null) return derefdOnLock; + + setStubTree(stubHolder); + return stubHolder; + } + } + + private void setStubTree(StubTree tree) { + synchronized (lock) { + myStub = new SoftReference(tree); + ((PsiFileStubImpl)tree.getRoot()).setPsi(this); + + synchronized (MIRROR_LOCK) { + myMirrorFileElement = null; } + myPackageStatement = new ClsPackageStatementImpl(this); + + } + } + + @Nullable + private StubTree derefStub() { + synchronized (lock) { + return myStub != null ? myStub.get() : null; } - return stubHolder; } public ASTNode findTreeForStub(final StubTree tree, final StubElement stub) {