JDK-8168500 : (se) EPollArrayWrapper optimization for update events should be robust to dynamic changes in file descriptor resource limits
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.nio
  • Affected Version: 9
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • OS: linux
  • Submitted: 2016-10-21
  • Updated: 2018-03-28
  • Resolved: 2016-11-15
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
9 b145Fixed
Related Reports
Duplicate :  
Duplicate :  
Duplicate :  
sun.nio.ch.EPollArrayWrapper uses an optimization to store events for file descriptors smaller than a certain threshold in an array and those greater than or equal to that threshold in a HashMap. The threshold is determined statically for the class and is by default based on the resource limit on the file descriptor number. It is conceivable however that this resource limit could change between when the static values are initialized and either the class is instantiated (and HashMap initialized or not) or when the pending update events are set or queried for a given file descriptor. If the resource limit on file descriptor number increases to a value greater than the event array size then an attempt could be made to dereference the uninitialized HashMap resulting in a NullPointerException. It is suspected but not verified that this is what happened to cause JDK-8165823. In any case, EPollArrayWrapper should be robust to a dynamically changed file descriptor resource limit.
Review thread: http://mail.openjdk.java.net/pipermail/nio-dev/2016-November/003967.html

Was able to reproduce the problem first observed in JDK-8165823 by making the following changes then running LotsOfChannels and using prlimit at the places indicated below: --- a/src/java.base/linux/classes/sun/nio/ch/EPollArrayWrapper.java +++ b/src/java.base/linux/classes/sun/nio/ch/EPollArrayWrapper.java @@ -135,8 +135,18 @@ pollArrayAddress = pollArray.address(); // eventHigh needed when using file descriptors > 64k - if (OPEN_MAX > MAX_UPDATE_ARRAY_SIZE) + if (OPEN_MAX > MAX_UPDATE_ARRAY_SIZE) { eventsHigh = new HashMap<>(); + System.out.println("Created eventsHigh"); + } else { + System.out.println("Did not create eventsHigh"); + } + try { + System.out.println("epoll sleeping"); + Thread.sleep(10000); // During sleep do sudo prlimit --nofile=2048:2048 --pid PID + System.out.println("epoll done sleeping"); + } catch (Exception e) { + } } void initInterrupt(int fd0, int fd1) { diff --git a/test/java/nio/channels/Selector/LotsOfChannels.java b/test/java/nio/channels/Selector/LotsOfChannels.java --- a/test/java/nio/channels/Selector/LotsOfChannels.java +++ b/test/java/nio/channels/Selector/LotsOfChannels.java @@ -41,6 +41,13 @@ private final static int LOOPS = 10; public static void main(String[] argv) throws Exception { + long seconds = 40L; + System.out.printf("Sleeping for %d seconds%n", seconds); + try { + Thread.sleep(1000L*seconds); // During sleep do: prlimit --nofile=512:512 --pid PID + } catch (Exception e) { + } + System.out.println("Done sleeping");