1

I need to locate, recompile and deploy on my JDK running on Linux the following native methods below, from SocketDispatcher.java: (Native methods are on the bottom of the code below, so scroll it down please)

package sun.nio.ch;

import java.io.*;

/**
 * Allows different platforms to call different native methods
 * for read and write operations.
 */

class SocketDispatcher extends NativeDispatcher
{

    static {
        IOUtil.load();
    }

    int read(FileDescriptor fd, long address, int len) throws IOException {
        return read0(fd, address, len);
    }

    long readv(FileDescriptor fd, long address, int len) throws IOException {
        return readv0(fd, address, len);
    }

    int write(FileDescriptor fd, long address, int len) throws IOException {
        return write0(fd, address, len);
    }

    long writev(FileDescriptor fd, long address, int len) throws IOException {
        return writev0(fd, address, len);
    }

    void preClose(FileDescriptor fd) throws IOException {
        preClose0(fd);
    }

    void close(FileDescriptor fd) throws IOException {
        close0(fd);
    }

    //-- Native methods
    static native int read0(FileDescriptor fd, long address, int len)
        throws IOException;

    static native long readv0(FileDescriptor fd, long address, int len)
        throws IOException;

    static native int write0(FileDescriptor fd, long address, int len)
        throws IOException;

    static native long writev0(FileDescriptor fd, long address, int len)
        throws IOException;

    static native void preClose0(FileDescriptor fd) throws IOException;

    static native void close0(FileDescriptor fd) throws IOException;
}

Source: http://grepcode.com/file_/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/sun/nio/ch/SocketDispatcher.java/?v=source

So basically I want to make the native method write0 print "Hello from native write0!".

Questions:

  • Where is the C/C++ code for write0 for Linux?

  • How do I recompile (gcc command-line?) the C/C++ code for write0 on Linux?

  • How do I start my JVM and make it use my new compiled native code for write0 on Linux?

LatencyFighter
  • 351
  • 2
  • 11

1 Answers1

6

There is no native SocketDispatcher implementation on Linux. It is Windows-specific class; on Linux it just shares the implementation with FileDispatcherImpl.

The native code for FileDispatcherImpl is in src/solaris/native/sun/nio/ch/FileDispatcherImpl.c (in OpenJDK solaris directory stands for POSIX code, so Linux implementation is also there).

If you want to override native methods, you have to create a shared library with your own implementation. Native method names follow JNI conventions, e.g. the native function for FileDispatherImpl.write0 should have the following signature:

JNIEXPORT jint JNICALL
Java_sun_nio_ch_FileDispatcherImpl_write0(JNIEnv *env, jclass clazz,
                              jobject fdo, jlong address, jint len)

Once you've built your own shared library with one or more functions overriden, preload it with LD_PRELOAD, and JVM will link your functions before any native code from JDK. By the way, JDK natives for FileDispatcherImpl and other java.nio stuff comes in libnio.so.

Community
  • 1
  • 1
apangin
  • 92,924
  • 10
  • 193
  • 247
  • Thanks, but I would like to re-compile the file `src/solaris/native/sun/nio/ch/FileDispatcherImpl.c` instead of writing my own implementation from scratch. So I want to copy everything from FileDispatcher.c change some small things, recompile and override. – LatencyFighter Apr 12 '17 at 13:37
  • @LatencyFighter Then you'll have to build the whole OpenJDK. – apangin Apr 12 '17 at 14:02
  • I just want to recompile the code for that particular method to print to the console a "Hello from write!" message before the method does what it already does. I can use the `LD_PRELOAD`. I guess the challenge there would be **How to compile?**, what command line to use, what dependencies it needs, etc. – LatencyFighter Apr 12 '17 at 14:36
  • @LatencyFighter You don't need to copy the original source file if you just want to *prepend* some action. It is possible to chain the original library from your LD_PRELOAD'ed library by calling `dlsym(RTLD_NEXT, ...)` – apangin Apr 12 '17 at 15:06
  • 1
    `gcc -shared -fPIC -I $JAVA_HOME/include -I $JAVA_HOME/include/linux -olibmynio.so mynio.c -ldl` – apangin Apr 12 '17 at 15:06