Skip to content

Commit

Permalink
Throw NoClassDefFoundError: MH.resolveInvokeDynamic(...)
Browse files Browse the repository at this point in the history
If ConstantPool.getClassAt(...) returns null while resolving bootstrap
method handles, then we should throw NoClassDefFoundError, and the
cause of NoClassDefFoundError should be ClassNotFoundException. The
message of NoClassDefFoundError and ClassNotFoundException should
contain the name of the class, which wasn't found.

Signed-off-by: Babneet Singh <[email protected]>
  • Loading branch information
babsingh committed Sep 25, 2017
1 parent c01ae1b commit a45bf26
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 0 deletions.
38 changes: 38 additions & 0 deletions jcl/src/java.base/share/classes/java/lang/invoke/MethodHandle.java
Original file line number Diff line number Diff line change
Expand Up @@ -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 <i>index</i> in <i>clazz</i>'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 <i>clazz</i> is null
* @throws IllegalArgumentException if <i>index</i> 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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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() {
Expand Down
50 changes: 50 additions & 0 deletions runtime/jcl/common/sun_reflect_ConstantPool.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
1 change: 1 addition & 0 deletions runtime/jcl/uma/se7_exports.xml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
<export name="Java_java_lang_invoke_MethodHandle_getCPTypeAt" />
<export name="Java_java_lang_invoke_MethodHandle_getCPMethodTypeAt" />
<export name="Java_java_lang_invoke_MethodHandle_getCPMethodHandleAt" />
<export name="Java_java_lang_invoke_MethodHandle_getCPClassNameAt" />
<export name="Java_java_lang_invoke_ThunkTuple_registerNatives" />
<export name="Java_java_lang_invoke_InterfaceHandle_registerNatives" />
<export name="Java_java_lang_invoke_MethodType_makeTenured" />
Expand Down
1 change: 1 addition & 0 deletions runtime/oti/jclprots.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit a45bf26

Please sign in to comment.