diff --git a/jcl/src/java.base/share/classes/java/lang/invoke/MethodHandle.java b/jcl/src/java.base/share/classes/java/lang/invoke/MethodHandle.java index 3e034af7fb0..284f064baa1 100644 --- a/jcl/src/java.base/share/classes/java/lang/invoke/MethodHandle.java +++ b/jcl/src/java.base/share/classes/java/lang/invoke/MethodHandle.java @@ -807,6 +807,21 @@ MethodHandle insertArguments(MethodHandle equivalent, MethodHandle unboxingHandl * equivalent for MethodHandle. */ private static final native MethodHandle getCPMethodHandleAt(Class clazz, int index); + + /** + * Get the class name from a constant pool class element, which is located + * at the specified index in clazz's constant pool. + * + * @param an instance of class - its constant pool is accessed + * @param the constant pool index + * + * @return instance of String which contains the class name or NULL in + * case of error + * + * @throws NullPointerException if clazz is null + * @throws IllegalArgumentException if index has wrong constant pool type + */ + private static final native String getCPClassNameAt(Class clazz, int index); private static final int BSM_ARGUMENT_SIZE = Short.SIZE / Byte.SIZE; private static final int BSM_ARGUMENT_COUNT_OFFSET = BSM_ARGUMENT_SIZE; @@ -861,6 +876,9 @@ private static final MethodHandle resolveInvokeDynamic(Class clazz, String na switch (cpType) { case 1: cpEntry = cp.getClassAt(index); + if (cpEntry == null) { + throw throwNoClassDefFoundError(clazz, index); + } break; case 2: cpEntry = cp.getStringAt(index); @@ -991,6 +1009,26 @@ private static Throwable throwNoClassDefFoundError(TypeNotPresentException e) { } throw e; } + + /** + * Retrieve the class name of the constant pool class element located at the specified + * index in clazz's constant pool. Then, throw a NoClassDefFoundError with the cause + * set as ClassNotFoundException. The message of NoClassDefFoundError and + * ClassNotFoundException contains the name of the class, which couldn't be found. + * + * @param an instance of Class - its constant pool is accessed + * @param integer value of the constant pool index + * + * @return Throwable to prevent any fall through case + * + * @throws NoClassDefFoundError with the cause set as ClassNotFoundException + */ + private static Throwable throwNoClassDefFoundError(Class clazz, int index) { + String className = getCPClassNameAt(clazz, index); + NoClassDefFoundError noClassDefFoundError = new NoClassDefFoundError(className); + noClassDefFoundError.initCause(new ClassNotFoundException(className)); + throw noClassDefFoundError; + } @Override public String toString() { diff --git a/runtime/jcl/common/sun_reflect_ConstantPool.c b/runtime/jcl/common/sun_reflect_ConstantPool.c index 5cfa4a93560..7126c226108 100644 --- a/runtime/jcl/common/sun_reflect_ConstantPool.c +++ b/runtime/jcl/common/sun_reflect_ConstantPool.c @@ -458,6 +458,56 @@ Java_sun_reflect_ConstantPool_getFieldAtIfLoaded0(JNIEnv *env, jobject unusedObj return getFieldAt(env, constantPoolOop, cpIndex, J9_RESOLVE_FLAG_JIT_COMPILE_TIME | J9_RESOLVE_FLAG_NO_THROW_ON_FAIL); } +/** + * Get the class name from a constant pool class element, which is located + * at the specified index in a class's constant pool. + * + * @param env[in] the JNI env + * @param unusedObject[in] unused + * @param constantPoolOop[in] the class - its constant pool is accessed + * @param cpIndex[in] the constant pool index + * + * @return instance of String which contains the class name or NULL in + * case of error + * + * @throws NullPointerException if constantPoolOop is null + * @throws IllegalArgumentException if cpIndex has wrong type + */ +jobject JNICALL +Java_java_lang_invoke_MethodHandle_getCPClassNameAt(JNIEnv *env, jobject unusedObject, jobject constantPoolOop, jint cpIndex) +{ + jobject classNameObject = NULL; + J9VMThread *vmThread = (J9VMThread *) env; + J9InternalVMFunctions *vmFunctions = vmThread->javaVM->internalVMFunctions; + J9MemoryManagerFunctions *gcFunctions = vmThread->javaVM->memoryManagerFunctions; + SunReflectCPResult result = NULL_POINTER_EXCEPTION; + + if (NULL != constantPoolOop) { + UDATA cpType = J9CPTYPE_UNUSED; + J9ROMConstantPoolItem *romCPItem = NULL; + vmFunctions->internalEnterVMFromJNI(vmThread); + result = getROMCPItemAndType(vmThread, constantPoolOop, cpIndex, &cpType, &romCPItem); + if (OK == result) { + switch (cpType) { + case J9CPTYPE_CLASS: { + J9UTF8 *className = J9ROMCLASSREF_NAME((J9ROMClassRef*)romCPItem); + j9object_t internalClassNameObject = gcFunctions->j9gc_createJavaLangString(vmThread, J9UTF8_DATA(className), (U_32) J9UTF8_LENGTH(className), 0); + classNameObject = vmFunctions->j9jni_createLocalRef(env, internalClassNameObject); + break; + } + default: + result = WRONG_CP_ENTRY_TYPE_EXCEPTION; + break; + } + } + vmFunctions->internalReleaseVMAccess(vmThread); + } + + checkResult(env, result); + + return classNameObject; +} + jobject JNICALL Java_sun_reflect_ConstantPool_getMemberRefInfoAt0(JNIEnv *env, jobject unusedObject, jobject constantPoolOop, jint cpIndex) { diff --git a/runtime/jcl/uma/se7_exports.xml b/runtime/jcl/uma/se7_exports.xml index 012d093d8a9..1cca6a8ca9d 100644 --- a/runtime/jcl/uma/se7_exports.xml +++ b/runtime/jcl/uma/se7_exports.xml @@ -57,6 +57,7 @@ + diff --git a/runtime/oti/jclprots.h b/runtime/oti/jclprots.h index 5c63550942a..491343b9753 100644 --- a/runtime/oti/jclprots.h +++ b/runtime/oti/jclprots.h @@ -992,6 +992,7 @@ jobject JNICALL Java_sun_reflect_ConstantPool_getUTF8At0(JNIEnv *env, jobject un jint JNICALL Java_java_lang_invoke_MethodHandle_getCPTypeAt(JNIEnv *env, jclass unusedClass, jobject constantPoolOop, jint cpIndex); jobject JNICALL Java_java_lang_invoke_MethodHandle_getCPMethodTypeAt(JNIEnv *env, jclass unusedClass, jobject constantPoolOop, jint cpIndex); jobject JNICALL Java_java_lang_invoke_MethodHandle_getCPMethodHandleAt(JNIEnv *env, jclass unusedClass, jobject constantPoolOop, jint cpIndex); +jobject JNICALL Java_java_lang_invoke_MethodHandle_getCPClassNameAt(JNIEnv *env, jobject unusedObject, jobject constantPoolOop, jint cpIndex); jint JNICALL Java_jdk_internal_reflect_ConstantPool_getClassRefIndexAt0(JNIEnv *env, jobject unusedObject, jobject constantPoolOop, jint cpIndex); jint JNICALL Java_jdk_internal_reflect_ConstantPool_getNameAndTypeRefIndexAt0(JNIEnv *env, jobject unusedObject, jobject constantPoolOop, jint cpIndex); jobject JNICALL Java_jdk_internal_reflect_ConstantPool_getNameAndTypeRefInfoAt0(JNIEnv *env, jobject unusedObject, jobject constantPoolOop, jint cpIndex);