ibmruntimes / openj9-openjdk-jdk9

Extensions for OpenJDK for Eclipse OpenJ9
GNU General Public License v2.0
67 stars 76 forks source link

JCL patch to remove the references to java.lang.String field coder #91

Closed JasonFengJ9 closed 6 years ago

JasonFengJ9 commented 6 years ago

Copied from https://github.com/eclipse/openj9/issues/223

OpenJDK j.l.String has three instance fields as following:

private final byte[] value;
private final byte coder;
private int hash;

On the other hand, OpenJ9 j.l.String has three instance fields as following:

private final byte[] value;
private final int count;
private int hashCode;

OpenJ9 bundles coder and count into a single field thus getting the benefit of having a count which speeds up substring operations and StringBuilder interaction while also supporting string compression. However this breaks Java 18.3 raw builds as following stacktrace:

Exception in thread "main" java/lang/NoSuchFieldError: java/lang/String.coder
        at java/io/UnixFileSystem.canonicalize0 (java.base@9/NativeMethod:4294967295)
        at java/io/UnixFileSystem.canonicalize (java.base@9/UnixFileSystem.java:170)
        at java/io/File.getCanonicalPath (java.base@9/File.java:618)
        at java/io/File.getCanonicalFile (java.base@9/File.java:643)
        at jdk/internal/loader/URLClassPath.toFileURL (java.base@9/URLClassPath.java:253)
        at jdk/internal/loader/URLClassPath.<init> (java.base@9/URLClassPath.java:188)
        at jdk/internal/loader/ClassLoaders.<clinit> (java.base@9/ClassLoaders.java:85)
        at java/lang/ClassLoader.initializeClassLoaders (java.base@9/ClassLoader.java:183)
        at java/lang/Thread.initialize (java.base@9/Thread.java:422)
        at java/lang/Thread.<init> (java.base@9/Thread.java:153)

This is due to jni_util.c referring the field in question as following:

    String_coder_ID = (*env)->GetFieldID(env, strClazz, "coder", "B");
......
    jbyte coder = (*env)->GetByteField(env, jstr, String_coder_ID);

An OpenJDK patch can replace all occurrences of j.l.String field coder reflection with method reflection for coder() instead. A code snippet to get coder of a string instance should look like following:

jbyte
getStringCoder(JNIEnv *env, jstring strObject)
{
        jclass strClass = NULL;
        jbyte coder = 0;
        strClass = (*env)->FindClass(env, "java/lang/String");
        if (NULL != strClass) {
                jmethodID coderMethod = (*env)->GetMethodID(env, strClass, "coder", "()B");
                if (NULL != coderMethod) {
                        coder = (*env)->CallByteMethod(env, strObject, coderMethod);
                }
        }
        return coder;
}

The target file to be patched is jni_util.c. @andrew-m-leonard, pls let us know if anything else is needed to submit a patch for this change to OpenJDK Java 10 repo.

FYI: @DanHeidinga @pshipton

keithc-ca commented 6 years ago

Like https://github.com/eclipse/openj9/issues/223, I think this can be closed.