Hi list - I've been using this patch for years to a) allow access to the integer file descriptor in jni as in [1], and b) to use the FileChannel.map() method to map special files under linux using jamvm / classpath-0.98 (e.g. /dev/fb0).
Thought I would submit it to the list for inclusion in any new releases. Feedback from any people wanting to validate is welcome. If I recall correctly, one shortcoming is that the returned mapped byte buffer is not 'direct'. Getting a direct map would require some manipulation of fields in an underlying byte[] somewhere. Obviously, a direct-mapped byte buffer would be more ideal. I think that requires using some kind of Unsafe class somewhere, and I stopped at that point. I don't mind doing the legwork for a direct mapped byte buffer too, to make it for inclusion in the next release. C [1] http://www.kfu.com/~nsayer/Java/jni-filedesc.html
diff --git a/gnu/java/nio/FileChannelImpl.java b/gnu/java/nio/FileChannelImpl.java index d4a374b..06fa205 100644 --- a/gnu/java/nio/FileChannelImpl.java +++ b/gnu/java/nio/FileChannelImpl.java @@ -176,7 +176,7 @@ public final class FileChannelImpl extends FileChannel * * @param mode READ or WRITE */ - FileChannelImpl (VMChannel ch, int mode) + public FileChannelImpl (VMChannel ch, int mode) { this.mode = mode; this.description = "descriptor(" + ch.getState() + ")"; @@ -564,9 +564,14 @@ public final class FileChannelImpl extends FileChannel /** * @return The native file descriptor. - * / + */ public int getNativeFD() { - return fd; - }*/ + int fd = -1; + try { + fd = ch.getState().getNativeFD(); + } catch(IOException e) { + } + return fd; + } } diff --git a/java/io/FileDescriptor.java b/java/io/FileDescriptor.java index cf9ff20..c3da2a9 100644 --- a/java/io/FileDescriptor.java +++ b/java/io/FileDescriptor.java @@ -40,6 +40,7 @@ exception statement from your version. */ package java.io; import gnu.java.nio.FileChannelImpl; +import gnu.java.nio.VMChannel; import java.nio.channels.ByteChannel; import java.nio.channels.FileChannel; @@ -80,6 +81,7 @@ public final class FileDescriptor = new FileDescriptor (FileChannelImpl.err); final ByteChannel channel; + int fd; /** * This method is used to initialize an invalid FileDescriptor object. @@ -97,6 +99,17 @@ public final class FileDescriptor this.channel = channel; } + FileDescriptor(FileChannelImpl channel) + { + this.channel = channel; + this.fd = channel.getNativeFD(); + } + + FileDescriptor(int fd, int mode) throws IOException + { + channel = new FileChannelImpl(new VMChannel(fd), mode); + this.fd = fd; + } /** * This method forces all data that has not yet been physically written to @@ -135,6 +148,8 @@ public final class FileDescriptor public boolean valid () { ByteChannel c = channel; - return (c != null) && (c.isOpen()); + boolean valid = (c != null) && (c.isOpen()); + valid = (channel instanceof FileChannel) ? (fd >= 0) : valid; + return valid; } } diff --git a/native/jni/java-nio/gnu_java_nio_VMChannel.c b/native/jni/java-nio/gnu_java_nio_VMChannel.c index 7899f0b..0f12efd 100644 --- a/native/jni/java-nio/gnu_java_nio_VMChannel.c +++ b/native/jni/java-nio/gnu_java_nio_VMChannel.c @@ -1944,18 +1944,20 @@ Java_gnu_java_nio_VMChannel_map (JNIEnv *env, } if (position + size > st.st_size) { - if (ftruncate(fd, position + size) == -1) + if ( !(S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) ) { - JCL_ThrowException (env, IO_EXCEPTION, strerror (errno)); - return NULL; + if (ftruncate(fd, position + size) == -1) + { + JCL_ThrowException (env, IO_EXCEPTION, strerror (errno)); + return NULL; + } } } prot |= PROT_WRITE; } flags = (mode == 'c' ? MAP_PRIVATE : MAP_SHARED); - p = mmap (NULL, (size_t) ALIGN_UP (size, pagesize), prot, flags, - fd, ALIGN_DOWN (position, pagesize)); + p = mmap (NULL, (unsigned)size, prot, flags, fd, position); if (p == MAP_FAILED) { JCL_ThrowException (env, IO_EXCEPTION, strerror (errno)); @@ -1979,14 +1981,14 @@ Java_gnu_java_nio_VMChannel_map (JNIEnv *env, if ((*env)->ExceptionOccurred (env)) { - munmap (p, ALIGN_UP (size, pagesize)); + munmap (p, size); return NULL; } if (MappedByteBufferImpl_init == NULL) { JCL_ThrowException (env, "java/lang/InternalError", "could not get MappedByteBufferImpl constructor"); - munmap (p, ALIGN_UP (size, pagesize)); + munmap (p, size); return NULL; } diff --git a/vm/reference/gnu/java/nio/VMChannel.java b/vm/reference/gnu/java/nio/VMChannel.java index a9d1452..7d8f13e 100644 --- a/vm/reference/gnu/java/nio/VMChannel.java +++ b/vm/reference/gnu/java/nio/VMChannel.java @@ -85,7 +85,7 @@ public final class VMChannel * @param native_fd The native file descriptor integer. * @throws IOException */ - VMChannel(final int native_fd) throws IOException + public VMChannel(final int native_fd) throws IOException { this(); this.nfd.setNativeFD(native_fd);