Pi4J / pi4j-v1

DEPRECATED Java I/O library for Raspberry Pi (GPIO, I2C, SPI, UART)
http://www.pi4j.com
Apache License 2.0
1.3k stars 446 forks source link

Remove class jdk.internal.misc.SharedSecrets in Pi4J v1.4 / JDK11 #521

Closed savageautomate closed 3 years ago

savageautomate commented 3 years ago

Reported by: Steven F. LeBrun

I have been using your Pi4J library on a robotic car that uses a Raspberry Pi 3B. I want to move my project to Java 11 but cannot with Pi4J limited to Java 8. This is due to Pi4J using the class jdk.internal.misc.SharedSecrets. Is this Java 8 restriction going to be removed in the V1.x? Or, is this a feature of Pi4J V2.x?

I have a fix that I believe should work in the Pi4J V1.x branches. It involves replacing the SharedSecrets class with a C/C++ native function that extracts the File Descriptor ID from the Java FileDescriptor class.

I have included the code as snippets ... Please feel free to use this code. The following is the code changes:

In pi4j-core --> LinuxFile.java Remove the "import jdk.internal.misc.SharedSecrets;" line.

Change the getFileDescriptor() method to:

    /**
     * Gets the real POSIX file descriptor for use by custom jni calls.
     */
    private int getFileDescriptor() throws IOException {
        final int fd = getPosixFD(getFD());

        if(fd < 1)
            throw new IOException("failed to get POSIX file descriptor!");

        return fd;
    }

Add the following line to the end of the LinuxFile class:

 protected static native int getPosixFD(FileDescriptor  fileDescriptor);

In pi4j-core --> com_pi4j_io_file_LinuxFile.h Add the following lines to the end of the file before the closing bracket:

/*
 * Class:      com_pi4j_io_file_LinuxFile
 * Method:     getFD
 * Signature:  (Ljava.io.FileDescriptor;)I
 */
  JNIEXPORT jint JNICALL Java_com_pi4j_io_file_LinuxFile_getPosixFD
  (  JNIEnv *env, jclass obj, jobject  fileDescriptor );

In pi4j-core --> com_pi4j_io_file_LinuxFile.c Add the following code to the end of the .c file:

/*
 * Class:       com_pi4j_io_file_LinuxFile
 * Method:      getFD
 * Signature:   (Ljava.io.FileDescriptor;)I
 *
 * Extracts POSIX File Descriptor from a Java FileDescriptor object.
 */
JNIEXPORT jint JNICALL Java_com_pi4j_io_file_LinuxFile_getPosixFD
  (JNIEnv *env, jclass obj, jobject fileDescriptorObj)
{
    jfieldID  fdFieldID;
    jclass    fdClass;
    int       fd = -1;

    // Get Class and Field information.
    fdClass = (*env)->FindClass(env, "java/io/FileDescriptor");

    if ( fdClass == NULL )
    {
        // Unable to obtain Class information
        return -2;
    }

    fdFieldID = (*env)->GetFieldID(env, fdClass, "fd", "I");

    if ( fdFieldID == NULL )
    {
        // Unable to obtain Field information
        return -3;
    }

    // Extract POSIX File Descriptor from Java FileDescriptor object
    fd = (*env)->GetIntField(env, fileDescriptorObj, fdFieldID);

    return fd;
}

Related Issues:

savageautomate commented 3 years ago

We are still trying to validate this fix. Reopening until validation is complete.

GeVanCo commented 2 years ago

In answer https://github.com/Pi4J/pi4j-v1/issues/521#issue-805878805

In pi4j-core --> com_pi4j_io_file_LinuxFile.h

In pi4j-core --> com_pi4j_io_file_LinuxFile.c

That must be both pi4j-native, right?

One more thing that is missing in the explanation text is to import the following in LinuxFile.java: import java.io.FileDescriptor FileDescriptor is used as parameter in the getPosixFD() JNI prototype call).