Bug 575641 - Text editor fails to open for very large text files
This change adds a catch for OutOfMemoryError to setDocumentContent() in
ResourceTextFileBuffer, FileStoreTextFileBuffer and
LastSaveReferenceProvider. The OOM is wrapped in an IOException and is
rethrown as a CoreException, relying on the CoreException handling
further up in the call stack trace.
Change-Id: I1ad32be1c1733106c3516c5914ab7784fcc57972
Signed-off-by: Simeon Andreev <simeon.danailov.andreev@gmail.com>
Reviewed-on: https://git.eclipse.org/r/c/platform/eclipse.platform.text/+/184513
Tested-by: Andrey Loskutov <loskutov@gmx.de>
Tested-by: Platform Bot <platform-bot@eclipse.org>
Reviewed-by: Jörg Kubitz <jkubitz-eclipse@gmx.de>
Reviewed-by: Andrey Loskutov <loskutov@gmx.de>
diff --git a/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/FileBuffersMessages.java b/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/FileBuffersMessages.java
index d64141f..0f834ab 100644
--- a/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/FileBuffersMessages.java
+++ b/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/FileBuffersMessages.java
@@ -41,6 +41,7 @@
public static String ResourceTextFileBuffer_error_unsupported_encoding_message_arg;
public static String ResourceTextFileBuffer_error_illegal_encoding_message_arg;
public static String ResourceTextFileBuffer_task_saving;
+ public static String ResourceTextFileBuffer_oom_on_file_read;
public static String ResourceFileBuffer_task_creatingFileBuffer;
public static String JavaTextFileBuffer_error_closeStream;
public static String TextFileBufferManager_error_documentSetupFailed;
diff --git a/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/FileBuffersMessages.properties b/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/FileBuffersMessages.properties
index 1f05f68..8e17fda 100644
--- a/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/FileBuffersMessages.properties
+++ b/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/FileBuffersMessages.properties
@@ -30,6 +30,7 @@
ResourceTextFileBuffer_error_unsupported_encoding_message_arg= Character encoding "{0}" is not supported by this platform.
ResourceTextFileBuffer_error_charset_mapping_failed_message_arg=Some characters cannot be mapped using "{0}" character encoding.\nEither change the encoding or remove the characters which are not supported by the "{0}" character encoding.
ResourceTextFileBuffer_task_saving= Saving
+ResourceTextFileBuffer_oom_on_file_read=OutOfMemoryError occurred while reading file "{0}".
ResourceFileBuffer_task_creatingFileBuffer=creating file buffer
diff --git a/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/FileStoreTextFileBuffer.java b/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/FileStoreTextFileBuffer.java
index 289de5d..acc254e 100644
--- a/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/FileStoreTextFileBuffer.java
+++ b/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/FileStoreTextFileBuffer.java
@@ -33,6 +33,8 @@
import java.nio.charset.UnmappableCharacterException;
import java.nio.charset.UnsupportedCharsetException;
+import org.eclipse.osgi.util.NLS;
+
import org.eclipse.core.filesystem.EFS;
import org.eclipse.core.filesystem.IFileInfo;
import org.eclipse.core.filesystem.IFileStore;
@@ -532,9 +534,15 @@
StringBuilder buffer= new StringBuilder(BUFFER_SIZE);
char[] readBuffer= new char[READER_CHUNK_SIZE];
int n= in.read(readBuffer);
- while (n > 0) {
- buffer.append(readBuffer, 0, n);
- n= in.read(readBuffer);
+ try {
+ while (n > 0) {
+ buffer.append(readBuffer, 0, n);
+ n= in.read(readBuffer);
+ }
+ } catch (OutOfMemoryError e) {
+ // give the JVM a hint that it can free the big buffer right away
+ buffer= null;
+ throw new IOException(NLS.bind(FileBuffersMessages.ResourceTextFileBuffer_oom_on_file_read, file.toURI()), e);
}
document.set(buffer.toString());
diff --git a/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/ResourceTextFileBuffer.java b/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/ResourceTextFileBuffer.java
index 69a3e4d..8b903e4 100644
--- a/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/ResourceTextFileBuffer.java
+++ b/org.eclipse.core.filebuffers/src/org/eclipse/core/internal/filebuffers/ResourceTextFileBuffer.java
@@ -31,6 +31,8 @@
import java.nio.charset.UnmappableCharacterException;
import java.nio.charset.UnsupportedCharsetException;
+import org.eclipse.osgi.util.NLS;
+
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
@@ -514,9 +516,15 @@
StringBuilder buffer= new StringBuilder(BUFFER_SIZE);
char[] readBuffer= new char[READER_CHUNK_SIZE];
int n= in.read(readBuffer);
- while (n > 0) {
- buffer.append(readBuffer, 0, n);
- n= in.read(readBuffer);
+ try {
+ while (n > 0) {
+ buffer.append(readBuffer, 0, n);
+ n= in.read(readBuffer);
+ }
+ } catch (OutOfMemoryError e) {
+ // give the JVM a hint that it can free the big buffer right away
+ buffer= null;
+ throw new IOException(NLS.bind(FileBuffersMessages.ResourceTextFileBuffer_oom_on_file_read, file.getLocationURI()), e);
}
if (document instanceof IDocumentExtension4)
diff --git a/org.eclipse.ui.editors/src/org/eclipse/ui/internal/editors/quickdiff/LastSaveReferenceProvider.java b/org.eclipse.ui.editors/src/org/eclipse/ui/internal/editors/quickdiff/LastSaveReferenceProvider.java
index b8f9705..32e13b6 100644
--- a/org.eclipse.ui.editors/src/org/eclipse/ui/internal/editors/quickdiff/LastSaveReferenceProvider.java
+++ b/org.eclipse.ui.editors/src/org/eclipse/ui/internal/editors/quickdiff/LastSaveReferenceProvider.java
@@ -44,6 +44,7 @@
import org.eclipse.ui.IStorageEditorInput;
import org.eclipse.ui.IWorkbenchPartSite;
import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.internal.editors.text.EditorsPlugin;
import org.eclipse.ui.texteditor.IDocumentProvider;
import org.eclipse.ui.texteditor.IElementStateListener;
@@ -250,6 +251,7 @@
}
} catch (CoreException e) {
+ EditorsPlugin.log(e);
return;
}
@@ -375,18 +377,21 @@
StringBuilder buffer= new StringBuilder(DEFAULT_FILE_SIZE);
char[] readBuffer= new char[2048];
int n= in.read(readBuffer);
- while (n > 0) {
- if (monitor != null && monitor.isCanceled())
- return;
+ try {
+ while (n > 0) {
+ if (monitor != null && monitor.isCanceled())
+ return;
- buffer.append(readBuffer, 0, n);
- n= in.read(readBuffer);
+ buffer.append(readBuffer, 0, n);
+ n= in.read(readBuffer);
+ }
+ } catch (OutOfMemoryError e) {
+ throw new IOException("OutOfMemoryError occurred while reading " + storage.getFullPath(), e); //$NON-NLS-1$
}
-
document.set(buffer.toString());
} catch (IOException x) {
- throw new CoreException(new Status(IStatus.ERROR, EditorsUI.PLUGIN_ID, IStatus.OK, "Failed to access or read underlying storage", x)); //$NON-NLS-1$
+ throw new CoreException(Status.error("Failed to access or read " + storage.getFullPath(), x)); //$NON-NLS-1$
} finally {
try {
if (in != null)