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);