JDK-8223014 : Calling java.lang.Class.newInstance from JNI Invocation API causes NPE
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.lang:reflect
  • Affected Version: 12
  • Priority: P3
  • Status: Closed
  • Resolution: Duplicate
  • OS: linux
  • CPU: x86_64
  • Submitted: 2019-04-24
  • Updated: 2019-04-26
  • Resolved: 2019-04-26
Related Reports
Duplicate :  
Description
A DESCRIPTION OF THE PROBLEM :
I can reproduce this with the OpenJDK 12 RPMs on Fedora 30, but from looking at <https://hg.openjdk.java.net/jdk/jdk12/file/06222165c35f/src/java.base/share/classes/java/lang/Class.java> it looks plausible that it is a common issue that Reflection.getCallerClass() returns null when java.lang.Class.newInstance is called from the JNI Invocation API, and that null is propagated to jdk.internal.reflect.Reflection.verifyMemberAccess as parameter currentClass, which dereferences it at <https://hg.openjdk.java.net/jdk/jdk12/file/06222165c35f/src/java.base/share/classes/jdk/internal/reflect/Reflection.java#l130>.
This is known to have been working with older OpenJDK (at least 1.8).

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile the provided test.cc with `g++ -I/usr/lib/jvm/java-12-openjdk-12.0.0.33-1.ea.1.rolling.fc30.x86_64/include -I/usr/lib/jvm/java-12-openjdk-12.0.0.33-1.ea.1.rolling.fc30.x86_64/include/linux /usr/lib/jvm/java-12-openjdk-12.0.0.33-1.ea.1.rolling.fc30.x86_64/lib/server/libjvm.so test.cc` and run it with `LD_LIBRARY_PATH=/usr/lib/jvm/java-12-openjdk-12.0.0.33-1.ea.1.rolling.fc30.x86_64/lib/server ./a.out`.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
exit 0
ACTUAL -
Exception in thread "main" java.lang.NullPointerException
	at java.base/jdk.internal.reflect.Reflection.verifyMemberAccess(Reflection.java:130)
	at java.base/java.lang.reflect.AccessibleObject.slowVerifyAccess(AccessibleObject.java:673)
	at java.base/java.lang.reflect.AccessibleObject.verifyAccess(AccessibleObject.java:666)
	at java.base/java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:638)
	at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:490)
	at java.base/java.lang.reflect.ReflectAccess.newInstance(ReflectAccess.java:166)
	at java.base/jdk.internal.reflect.ReflectionFactory.newInstance(ReflectionFactory.java:404)
	at java.base/java.lang.Class.newInstance(Class.java:590)
Aborted

---------- BEGIN SOURCE ----------
#include <cstdlib>

#include "jni.h"

void handleError(JNIEnv * env) {
    if (env->ExceptionCheck()) {
        env->ExceptionDescribe();
        std::abort();
    }
}

int main() {
    JavaVM * vm;
    JNIEnv * env;
    JavaVMInitArgs args{JNI_VERSION_1_2, 0, nullptr, true};
    if (JNI_CreateJavaVM(&vm, reinterpret_cast<void **>(&env), &args) != JNI_OK) {
        std::abort();
    }
    auto const c1 = env->FindClass("java/lang/Class");
    handleError(env);
    auto const id = env->GetMethodID(c1, "newInstance", "()Ljava/lang/Object;");
    handleError(env);
    auto const c2 = env->FindClass("java/lang/Object");
    handleError(env);
    env->CallObjectMethod(c2, id);
    handleError(env);
}
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Call via JNI the suggested replacement of clazz.getDeclaredConstructor().newInstance() instead of the deprecated java.lang.Class.newInstance().


Comments
Tested on ubuntu linux x64 , and following were the results : JDK 8u211 - Pass JDK 9 - Pass JDK 10 - Pass JDK 11- Pass JDK 12 -Fail` JDK 12.0.1 - Fail JDK 13-ea+17 - Pass Output on JDK-12 : Exception in thread "main" java.lang.NullPointerException at java.base/jdk.internal.reflect.Reflection.verifyMemberAccess(Reflection.java:130) at java.base/java.lang.reflect.AccessibleObject.slowVerifyAccess(AccessibleObject.java:673) at java.base/java.lang.reflect.AccessibleObject.verifyAccess(AccessibleObject.java:666) at java.base/java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:638) at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:490) at java.base/java.lang.reflect.ReflectAccess.newInstance(ReflectAccess.java:166) at java.base/jdk.internal.reflect.ReflectionFactory.newInstance(ReflectionFactory.java:404) at java.base/java.lang.Class.newInstance(Class.java:590) Aborted (core dumped) This was a regression introduced due to JDK-8206240 and it has been fixed with JDK-8221530. Closing it as duplicate.
26-04-2019