Issue title: Cannot monitor file/directory changes in Java code - missing 'inotify_add_watch' (and maybe others)
 Issue body: I am using _Java_ code similar to the _Groovy_ script below in order to monitor file/directory changes (similar to _tail -f_). The code works fine on Windows and Linux and it **used to work** on OSV, but no longer. When I run it now I get:

```
java.io.IOException: No file descriptors available
    at sun.nio.fs.LinuxWatchService.<init>(LinuxWatchService.java:61)
    at sun.nio.fs.LinuxFileSystem.newWatchService(LinuxFileSystem.java:47)
```

The _Groovy_ test script (which can easily be turned into a _Java_ one...):

``` groovy
#!/usr/bin/env groovy

import java.nio.file.FileSystem
import java.nio.file.FileSystems
import java.nio.file.Path
import java.nio.file.StandardWatchEventKinds
import java.nio.file.WatchEvent
import java.nio.file.WatchKey
import java.nio.file.WatchService
import java.nio.file.WatchEvent.Kind
import java.util.concurrent.atomic.AtomicLong

import org.codehaus.groovy.tools.shell.ExitNotification

if (args.length <= 0) {
    dieWithMessage("Usage: FollowFile file")
}

try {
    monitorFileChanges(new File(args[0]).canonicalFile)
} catch(Throwable t) {
    System.err.println(t.getClass().getSimpleName() + ": " + t.getMessage())
    t.printStackTrace(System.err)
}
return

void monitorFileChanges(File targetFile) {
    String          absPath=targetFile.absolutePath
    FileSystem      fs=FileSystems.getDefault()
    Path            filePath=targetFile.toPath()
    Path            dirPath=filePath.getParent()
    AtomicLong      lastAccessedOffset=new AtomicLong(0L)
    println "Start following $absPath"

    WatchService    watchService=fs.newWatchService()
    try {
        WatchKey      registrationKey=dirPath.register(watchService, StandardWatchEventKinds.ENTRY_MODIFY)
        try {
            while(true) {
                long    curOffset=lastAccessedOffset.get(), available=targetFile.length()
                if (curOffset < available) {
                    updateDisplayedContents(targetFile, curOffset, available - curOffset, System.out)
                    lastAccessedOffset.set(available)
                }

                WatchKey    key=watchService.take()
                if (key == null) {
                    continue
                }

                if (!key.isValid()) {
                    break
                }

                Collection<WatchEvent<?>>   events=key.pollEvents();
                if ((events == null) || events.isEmpty()) {
                    continue
                }

                for (WatchEvent<?> event : events) {
                    Kind<?> kind=event.kind()
                    if (!StandardWatchEventKinds.ENTRY_MODIFY.equals(kind)) {
                        continue
                    }

                    Path    modifiedPath=((WatchEvent<Path>) event).context()
                    File    modifiedFile=modifiedPath.toFile()
                    String  absModified=modifiedFile.absolutePath
                    if (!absPath.equals(absModified)) {
                        continue
                    }

                    break  // no need to examine the rest of the events
                }
            }
        } finally {
            registrationKey.cancel()
        }
    } finally {
        watchService.close()
    }
}

void updateDisplayedContents(File file, long curOffset, long displaySize, OutputStream outputStream) {
    RandomAccessFile    raf=new RandomAccessFile(file, "r")
    try {
        raf.seek(curOffset)

        byte[]  workBuf=new byte[4096]
        for (long remSize=displaySize; remSize > 0L; ) {
            int readLen=raf.read(workBuf)
            if (readLen <= 0) {
                break
            }
            outputStream.write(workBuf, 0, readLen)
            remSize -= readLen
        }
        outputStream.flush()
    } finally {
        raf.close()
    }

}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////

def dieWithMessage(String msg, int rc=1) {
    System.err.println(msg)
    throw new ExitNotification(rc)
}
```

 Comments: 
 Comment 0: On Mon, Aug 4, 2014 at 3:40 PM, Lyor Goldstein cwalker@example.org
wrote:

> I am using _Java_ code similar to the _Groovy_ script below in order to
> monitor file/directory changes (similar to _tail -f_). The code works
> fine on Windows and Linux and it _used to work_ on OSV, but no longer.
> When I run it now I get:
> 
> java.io.IOException: No file descriptors available
>     at sun.nio.fs.LinuxWatchService.<init>(LinuxWatchService.java:61)
>     at sun.nio.fs.LinuxFileSystem.newWatchService(LinuxFileSystem.java:47)
> 
> OpenJDK's LinuxWatchService.c uses inotify_add_watch() and friends, which
> in OSv are stubbed (see libc/inotify.cc), so I don't understand how this
> used to work.
> Could it be that you tried this 4 months ago, before these stubs were added?

By the way, if you just need something similar to "tail -f" on a single
file, inotify is an overkill.

 Comment 1: @nyh `I don't understand how this
used to work.` I am pretty sure it worked (though I may be wrong). Regardless, it does not work now (so if you wish you can change the title and remove the _Regression_ word).

`By the way, if you just need something similar to "tail -f" on a single file, inotify is an overkill` - there is no _inotify_ in Java (which is what I am describing here...) + this bug has nothing to do with _tail -f_ - it was just an **example** of where such a monitoring API is required.

Anyway, OSV is supposed to support the **full** Java 7 API, so it must also support this one...

{'source': 'GithubIssues', 'repo_name_with_owner': 'cloudius-systems/osv', 'issue_id': 39416651, 'repo_stars': 3801.0}