uk.ac.starlink.fits

## Class Unmapper

- java.lang.Object
- - uk.ac.starlink.fits.Unmapper

-     public abstract class Unmapper
      extends java.lang.Object

  Knows how to map a region of a file in such a way that it is possible to attempt subsequent freeing of associated resources.

  This is a tricky business. At Java 8 there is no good way to unmap the memory mapped by a `MappedByteBuffer`. The MappedByteBuffer javadocs say "A mapped byte buffer and the file mapping that it represents remain valid until the buffer itself is garbage-collected.", and there is no explicit unmap method. However, since the resources locked by memory mapping are separate from the JVM heap, there is no guarantee that garbage collection will happen even when mapped memory reaches crisis levels, and in practice this can lead to cache thrashing and the OS locking up even when there are many MappedByteBuffers without active references, at least on some platforms (I see it on Scientific Linux 6.5 with 24Gb RAM, but not SL 6.3 with 4Gb, but I'm not sure what the relevant differences are).

  The best way around this is dependent on Java version. Before about Java 22, the only way was using implementation-specific classes in the `sun.*` namespace to do the unmapping. This is not guaranteed to work on all J2SE implementations, and moreover it risks a JVM crash if the buffer instance is used after the umapping has been done. So use it WITH EXTREME CAUTION.

  At Java 22 and later (previewed in Java 19?), public classes in the `java.lang.foreign` package can be used for this purpose, which is safe.

  Provision of the default Unmapper instance, available from the static `getInstance()` method, is therefore done using reflection to provide an implementation that depends on the current JRE. It is possible to specify a preference for how this is done among the available options (or providing a custom Unampper implementation) by use of the `UNMAP_PROPERTY` ("startable.unmap") system property, or programmatically using the `setInstance` method.

  Since:
    2 Dec 2014
  See Also:
    Java Bug #4724038, JEP 498, JEP 471

- - ### Field Summary

    Fields
    Modifier and Type | Field and Description
    --- | ---
    `static Unmapper` | `NOP` Unmapper instance that makes no attempt to reclaim resources.
    `static java.lang.String` | `UNMAP_PROPERTY` Name of system property to control buffer unmapping ("startable.unmap").

  - ### Constructor Summary

    Constructors
    Modifier | Constructor and Description
    --- | ---
    `protected` | `Unmapper()` Constructor.

  - ### Method Summary

    All Methods Static Methods Instance Methods Abstract Methods Concrete Methods
    Modifier and Type | Method and Description
    --- | ---
    `static Unmapper` | `getInstance()` Returns the standard instance of this class.
    `abstract UnmappableBuffer` | `mapFile(java.nio.channels.FileChannel channel, long offset, int leng)` Creates an object that represents a read-only mapped region of a file, and for which it is possible to attempt release of resources at a later date.
    `void` | `setInstance(Unmapper unmapper)` Sets the instance of this class that will be returned by the `getInstance()` method.

    - ### Methods inherited from class java.lang.Object

      `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- - ### Field Detail

    - #### UNMAP_PROPERTY

          public static final java.lang.String UNMAP_PROPERTY

      Name of system property to control buffer unmapping ("startable.unmap"). Possible values are currently:
      - "`sun`": best-efforts sun.misc-based option
      - "`cleaner`": sun.misc.Cleaner-based option (available in Oracle Java 6 through Java 8)
      - "`unsafe`": sun.misc.Unsafe-based option (available in Oracle Java 9 through Java 25?)
      - "`memseg`": java.lang.foreign.MemorySegment-based option (available in approx Java 22 and later)
      - "`none`": no unmapping
      - "`default`": tries to use `memseg`, then `sun`, then `none`, depending on what's available
      You can also give the classname of an `Unmapper` concrete subclass with a no-arg constructor.

      If the property is not set, behaviour is as "`default`".

      See Also:
        Constant Field Values

    - #### NOP

          public static final Unmapper NOP

      Unmapper instance that makes no attempt to reclaim resources. It is safe.

  - ### Constructor Detail

    - #### Unmapper

          protected Unmapper()

      Constructor.

  - ### Method Detail

    - #### mapFile

          public abstract UnmappableBuffer mapFile(java.nio.channels.FileChannel channel,
                                                   long offset,
                                                   int leng)
                                            throws java.io.IOException

      Creates an object that represents a read-only mapped region of a file, and for which it is possible to attempt release of resources at a later date. Whether such a release attempt is successful depends on the implementation.

      No explicit checking of the parameters is done by this method; helpful messages to users about bad parameter choices should be generated by the caller.

      Parameters:
        `channel` - file channel
        `offset` - offset into file of mapped region start
        `leng` - number of bytes to map
      Returns:
        unmappable buffer object
      Throws:
        `java.io.IOException`

    - #### getInstance

          public static Unmapper getInstance()

      Returns the standard instance of this class. Under normal circumstances this will return a usable instance, but if the `UNMAP_PROPERTY` has asked for something specific that cannot be provided, a RuntimeException will be thrown.
      Returns:
        lazily constructed instance
      Throws:
        `java.lang.RuntimeException` - if an option has been explicitly chosen that cannot be instantiated

    - #### setInstance

          public void setInstance(Unmapper unmapper)

      Sets the instance of this class that will be returned by the `getInstance()` method.
      Parameters:
        `unmapper` - default instance