Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1686,4 +1686,55 @@ public void run(){
}
}

/*
* Ensures that stale buffers from deleted/recreated jars are properly detected and replaced.
* This test simulates the scenario where a jar file is deleted and recreated with the same path,
* and verifies that stale cached buffers are not reused.
* See https://github.com/eclipse-jdt/eclipse.jdt.ui/issues/736
*/
public void testStaleBufferAfterJarRecreation() throws CoreException, IOException {
IJavaProject project = null;
try {
project = createJavaProject("TestStaleBuffer", new String[0], new String[] {"JCL18_LIB"}, "", JavaCore.VERSION_1_8);

String[] pathAndContents = new String[] {
"pack/age/X.java",
"package pack.age;\n" +
"public interface X {\n" +
" String test();\n" +
"}"
};
addLibrary(project, "testlib.jar", "testlibsrc.zip", pathAndContents, JavaCore.VERSION_1_8);

IPackageFragmentRoot root = project.getPackageFragmentRoot(project.getProject().getFile("testlib.jar"));
IOrdinaryClassFile classFile1 = root.getPackageFragment("pack.age").getOrdinaryClassFile("X.class");
String source1 = classFile1.getSource();
assertNotNull("Source should be available for first jar", source1);
assertTrue("Source should contain 'test()' method", source1.contains("test()"));
assertFalse("Source should not contain 'newMethod()'", source1.contains("newMethod()"));

removeLibrary(project, "testlib.jar", "testlibsrc.zip");
String[] newPathAndContents = new String[] {
"pack/age/X.java",
"package pack.age;\n" +
"public interface X {\n" +
" String newMethod();\n" +
"}"
};
addLibrary(project, "testlib.jar", "testlibsrc.zip", newPathAndContents, JavaCore.VERSION_1_8);

root = project.getPackageFragmentRoot(project.getProject().getFile("testlib.jar"));
IOrdinaryClassFile classFile2 = root.getPackageFragment("pack.age").getOrdinaryClassFile("X.class");
String source2 = classFile2.getSource();

assertNotNull("Source should be available for recreated jar", source2);
assertTrue("Source should contain new 'newMethod()'", source2.contains("newMethod()"));
assertFalse("Source should not contain old 'test()' method", source2.contains("test()"));
} finally {
if (project != null) {
deleteProject(project);
}
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,11 @@ protected IBuffer openBuffer(IProgressMonitor pm, IElementInfo info) throws Java
// Check the cache for the top-level type first
IType outerMostEnclosingType = getOuterMostEnclosingType();
IBuffer buffer = getBufferManager().getBuffer(outerMostEnclosingType.getClassFile());
// Validate the cached buffer is still valid (not stale from a deleted/recreated jar)
if (buffer != null && !(buffer instanceof NullBuffer) && buffer.isClosed()) {
getBufferManager().removeBuffer(buffer);
buffer = null;
}
if (buffer == null) {
SourceMapper mapper = getSourceMapper();
IBinaryType typeInfo = info instanceof IBinaryType ? (IBinaryType) info : null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,11 @@ public IBuffer getBuffer() throws JavaModelException {
// ensure element is open
IElementInfo info = getElementInfo();
IBuffer buffer = getBufferManager().getBuffer(this);
if (buffer != null && !(buffer instanceof NullBuffer) && buffer.isClosed()) {
// stale buffer from deleted/recreated jar - evict and recreate
getBufferManager().removeBuffer(buffer);
buffer = null;
}
if (buffer == null) {
// try to (re)open a buffer
buffer = openBuffer(null, info);
Expand Down
Loading