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);