Jump to content

Non-blocking I/O (Java)

From Alfawiki
java.nio
Company typeAPI
IndustrySoftware development / Java platform
Founded2002
FounderSun Microsystems
ParentJava Platform, Standard Edition (J2SE)

java.nio (an abbreviation for New Input/Output) comprises a suite of Java APIs tailored for high-performance I/O tasks. Initially introduced in J2SE 1.4 by Sun Microsystems, NIO serves as a supplement to the conventional I/O framework and was developed through the Java Community Process under JSR 51. Its successor, NIO.2, which offers an updated file system API, debuted with Java SE 7 ("Dolphin").

Features and structure

The NIO APIs grant access to the underlying low-level I/O capabilities provided by contemporary operating systems, allowing implementations to utilize optimized platform-specific functionalities.

These APIs are located within the package and encompass:

  • Buffers designed for primitive data types
  • Encoders and decoders for various character sets
  • Pattern matching utilizing Perl-style regular expressions ()
  • Channels, a novel fundamental I/O abstraction
  • File interfaces that support locking and memory mapping up to 2 GiB
  • A multiplexed, non-blocking I/O mechanism facilitating scalable server architectures

NIO buffers

In NIO, data movement is managed through buffers (instances of classes), which represent sequential memory blocks with constrained data transfer capabilities. These buffers can be aligned with native OS memory regions to enable direct and efficient I/O transfers, frequently minimizing CPU involvement. Buffer classes exist for every Java primitive type except boolean, which is handled through byte buffers to allow flexible byte-level interpretations.

Operation

NIO buffers use pointers to regulate data access methods. Important methods include:

  • flip() resets the position pointer to zero and sets the limit pointer to the previous position value.
  • The three variants of get() extract data from a buffer; the bulk method copies content into a specified array, where "offset" indicates the starting index in the destination array.
  • Unless absolute get() or put() methods are invoked, operations occur at the current position. The mark() and reset() functions permit reading from different points without modifying the write position.
  • mark() records the current position, while reset() reverts to this saved point.
  • Calling clear() or flip() will erase any existing mark.
  • clear() sets limit to the buffer's capacity and resets position to zero but does not erase stored data.
  • The put() and get() methods are not inherently thread-safe.
  • Mapping a from a is capped at 2GiB (Integer.MAX_VALUE) per mapped segment; handling larger files necessitates managing offsets.

Channels

Channels (implementing ) facilitate bulk data exchange between NIO buffers and various I/O sources. They complement higher-level I/O classes such as and , and can be retrieved from classes like , , or . Channels operate similarly to Unix-style file descriptors.

File channels () support arbitrary buffer interactions and memory-mapped files, enabling efficient file operations including locking mechanisms. Socket channels ( and ) allow data transmission between sockets and NIO buffers.

FileChannel often provides superior performance for file copying compared to conventional read/write byte array techniques. A common usage pattern is: <syntaxhighlight lang="java"> // Acquiring file channels try(FileChannel in = FileChannel.open(source, StandardOpenOption.READ);

   FileChannel out = FileChannel.open(target, StandardOpenOption.WRITE)) {
   // JVM optimizes this call into native I/O operations.
   in.transferTo(0, in.size(), out);

} </syntaxhighlight>

Selectors

Selectors (along with their subclasses) facilitate monitoring multiple channels simultaneously and detecting when one or more become ready for data transfer. By associating channels with a selector, the program execution halts until at least one channel signals readiness or an interruption takes place.

Although thread-based multiplexing is possible, selectors provide a more resource-efficient alternative by utilizing underlying operating system mechanisms. For example, POSIX-compliant environments rely on native functions such as select(). This architecture is commonly employed in server applications to efficiently handle numerous concurrent connections.

Character sets

Within Java, a character set defines the mapping between Unicode characters (or subsets thereof) and their corresponding byte representations. The package offers utilities for identifying character sets and performing encoding and decoding operations, supporting custom mappings critical for internationalization and data interoperability.

Reception

Some critique exists concerning Channels linked to Java IO RandomAccessFile closing file descriptors upon interruption, which contrasts with the behavior of FileChannels associated with RandomAccessFiles that manage this differently.

JDK 7 and NIO.2

The release of JDK 7 brought forth the package alongside the new class, greatly improving filesystem-related functionality. Enhancements include support for symbolic and hard links as well as superior performance when processing large directory contents compared to the legacy File class.

Together, the package and deliver extensive capabilities for file input/output and filesystem access. Moreover, JDK 7 introduces a zip file system provider that allows zip archives to be accessed and manipulated as virtual filesystems.

The java.nio.file.LinkOption enum serves as an example of simulating extensible enums through interfaces. Since Java enums cannot inherit from other enums directly, LinkOption implements both OpenOption and CopyOption interfaces to mimic extensibility. This design enhances flexibility in option management but restricts sharing implementation across different enum types.

References

External links