Skip to content

Commit ead6a4d

Browse files
committed
Clarify Windows memory map file locking
1 parent 28c4fb9 commit ead6a4d

2 files changed

Lines changed: 32 additions & 19 deletions

File tree

README.md

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,10 @@ this package directly.
4141

4242
To use the API, you must first create a `Reader` object. The constructor for
4343
the reader object takes a `File` representing your MaxMind DB. Optionally you
44-
may pass a second parameter with a `FileMode` with a value of `MEMORY_MAP` or
45-
`MEMORY`. The default mode is `MEMORY_MAP`, which maps the file to virtual
46-
memory. This often provides performance comparable to loading the file into
47-
real memory with `MEMORY`.
44+
may pass a second parameter with a `FileMode` with a value of `MEMORY_MAPPED`
45+
or `MEMORY`. The default mode is `MEMORY_MAPPED`, which maps the file to
46+
virtual memory. This often provides performance comparable to loading the file
47+
into real memory with `MEMORY`.
4848

4949
To look up an IP address, pass the address as an `InetAddress` to the `get`
5050
method on `Reader`, along with the class of the object you want to
@@ -251,16 +251,22 @@ threads.
251251

252252
### File Lock on Windows ###
253253

254-
By default, this API uses the `MEMORY_MAP` mode, which memory maps the file.
255-
On Windows, this may create an exclusive lock on the file that prevents it
256-
from being renamed or deleted. Due to the implementation of memory mapping in
257-
Java, this lock will not be released when the `DatabaseReader` is closed; it
258-
will only be released when the object and the `MappedByteBuffer` it uses are
259-
garbage collected. Older JVM versions may also not release the lock on exit.
260-
261-
To work around this problem, use the `MEMORY` mode or try upgrading your JVM
262-
version. You may also call `System.gc()` after dereferencing the
263-
`DatabaseReader` object to encourage the JVM to garbage collect sooner.
254+
By default, this API uses the `MEMORY_MAPPED` mode, which memory maps the file.
255+
On Windows, a live memory mapping may prevent the file from being renamed,
256+
replaced, or deleted. This is not a Java `FileLock`, but it can have similar
257+
effects when updating a database file in place.
258+
259+
Closing the `Reader` releases this library's reference to the mapped buffer,
260+
but Java does not provide a supported way to unmap the underlying
261+
`MappedByteBuffer` immediately. The mapping remains valid until the buffer
262+
becomes unreachable and is garbage collected. Any outstanding lookup or
263+
`Networks` iterator may also keep a duplicate buffer reachable.
264+
265+
To avoid this behavior, use the `MEMORY` mode. If you must use
266+
`MEMORY_MAPPED`, close and dereference the `Reader` and any iterators that were
267+
created from it before replacing the file. You may call `System.gc()` to
268+
encourage earlier cleanup, but garbage collection is not guaranteed to run
269+
immediately.
264270

265271
### Packaging Database in a JAR ###
266272

src/main/java/com/maxmind/db/Reader.java

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,15 @@ public enum FileMode {
3838
* The default file mode. This maps the database to virtual memory. This
3939
* often provides similar performance to loading the database into real
4040
* memory without the overhead.
41+
*
42+
* <p>On Windows, a live memory mapping may prevent the database file
43+
* from being renamed, replaced, or deleted until the mapped buffer is
44+
* garbage collected.
4145
*/
4246
MEMORY_MAPPED,
4347
/**
44-
* Loads the database into memory when the reader is constructed.
48+
* Loads the database into memory when the reader is constructed. This
49+
* avoids keeping a live memory mapping of the database file.
4550
*/
4651
MEMORY
4752
}
@@ -497,10 +502,12 @@ public Metadata getMetadata() {
497502
* </p>
498503
* <p>
499504
* If you are using <code>FileMode.MEMORY_MAPPED</code>, this will
500-
* <em>not</em> unmap the underlying file due to a limitation in Java's
501-
* <code>MappedByteBuffer</code>. It will however set the reference to
502-
* the buffer to <code>null</code>, allowing the garbage collector to
503-
* collect it.
505+
* release this reader's reference to the mapped buffer, allowing the
506+
* garbage collector to collect it when no other references remain. Java
507+
* does not provide a supported way to unmap a
508+
* <code>MappedByteBuffer</code> immediately. On Windows, this means the
509+
* database file may remain unavailable for rename, replacement, or
510+
* deletion until the mapped buffer is garbage collected.
504511
* </p>
505512
*
506513
* @throws IOException if an I/O error occurs.

0 commit comments

Comments
 (0)