NationalSecurityAgency/ghidra · error · IOException
GhidraRandomAccessFile is closed
Error message
GhidraRandomAccessFile is closed
What it means
GRandomAccessFile maintains an 'open' flag set false by close(). Every mutating/reading operation routes through checkOpen(), which throws this IOException if the instance has already been closed. It is the standard use-after-close guard for a buffered RandomAccessFile wrapper.
Source
Thrown at GPL/DMG/src/dmg/java/mobiledevices/dmg/ghidra/GRandomAccessFile.java:31
* This implementation relies on java.net.RandomAccessFile,
* but adds buffering to limit the amount.
*/
public class GRandomAccessFile {
private static final byte[] EMPTY = new byte[0];
private static final int BUFFER_SIZE = 0x100000;
private RandomAccessFile randomAccessFile;
private byte[] buffer = EMPTY;
private long bufferOffset = 0;
private long bufferFileStartIndex = 0;
private byte[] lastbuffer = EMPTY;
private long lastbufferOffset = 0;
private long lastbufferFileStartIndex = 0;
private boolean open = false;
private void checkOpen() throws IOException {
if (!open) {
throw new IOException("GhidraRandomAccessFile is closed");
}
}
/**
* Creates a random access file stream to read from, and optionally to
* write to, the file specified by the {@link File} argument. A new {@link
* FileDescriptor} object is created to represent this file connection.
*
* <p>
* This implementation relies on java.net.RandomAccessFile,
* but adds buffering to limit the amount.
* <p>
*
* <a name="mode"><p> The <tt>mode</tt> argument specifies the access mode
* in which the file is to be opened. The permitted values and their
* meanings are:
*
* <blockquote><table summary="Access mode permitted values and meanings">View on GitHub (pinned to d5f144c24d)
Solutions
- Audit the lifecycle: ensure no reads/seeks happen after the close() that owns this GRandomAccessFile.
- Move the close() to the true end of use, or stop retaining references past close.
- Use try-with-resources scoped tightly around the read loop so close runs only after all access completes.
- Null out references after close to surface accidental reuse as an NPE earlier in the chain.
Example fix
// before
graf.close();
// ... later, in error path:
graf.seek(pos);
// after - ensure no access after close, scope the resource
try (GRandomAccessFile graf = new GRandomAccessFile(file, mode)) {
graf.seek(pos);
// ... all reads here
} Defensive patterns
Strategy: try-catch
Validate before calling
// No pre-call validation possible; track ownership centrally.
// Optional: wrap access in a guard that checks an application-level 'closed' flag
if (graf == null) throw new IllegalStateException("GRandomAccessFile reference is null (already released)");
graf.seek(pos); Type guard
// Not a type guard per se, but a lifecycle wrapper:
class SafeRandomAccessFile {
private final GRandomAccessFile inner;
private volatile boolean closed = false;
synchronized void close() throws IOException { closed = true; inner.close(); }
void seek(long pos) throws IOException {
if (closed) throw new IOException("already closed");
inner.seek(pos);
}
} Try / catch
try {
graf.seek(pos);
} catch (IOException e) {
if (e.getMessage() != null && e.getMessage().contains("is closed")) {
// Use-after-close: do not retry; re-open or fail upward with context
throw new IOException("Attempted to use GRandomAccessFile after close", e);
}
throw e;
} Prevention
- Scope resource lifetime with try-with-resources around the entire access window.
- Do not retain or share the underlying handle beyond its owner's lifetime.
- Null out references after close to surface accidental reuse earlier.
- Audit finally/error paths that close early then continue processing.
When it happens
Trigger: Calling any operation (read, seek, write, length, etc.) on a GRandomAccessFile after close() was invoked. Commonly happens when the owning reader/provider is closed but a reference to the underlying file is still held and used, or in error-handling paths that close early then continue.
Common situations: Closing a DmgFileReader/ByteProvider in a finally block but then retrying an operation; nested resource management where the outer close invalidates an inner handle still in use; a try-with-resources that scoped too widely; double-close across multiple owners of the same handle.
Related errors
- Unable to read {} bytes
- pos cannot be less than zero
- Bad nodeSize: {}
- Invalid number of elements specified: {}
- No system partitions found. Perhaps the decryption failed?
AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14).
Data as JSON: /api/errors/a08202c4ff9c9d90.
Report an issue: GitHub.