mirror of
https://github.com/openjdk/jdk.git
synced 2026-05-10 05:29:48 +00:00
8335638: Calling VarHandle.{access-mode} methods reflectively throws wrong exception
Reviewed-by: liach
This commit is contained in:
parent
27af80ef9e
commit
9fe6e2316a
@ -1360,6 +1360,18 @@ JVM_ENTRY(jobject, MH_invokeExact_UOE(JNIEnv* env, jobject mh, jobjectArray args
|
||||
}
|
||||
JVM_END
|
||||
|
||||
/**
|
||||
* Throws a java/lang/UnsupportedOperationException unconditionally.
|
||||
* This is required by the specification of VarHandle.{access-mode} if
|
||||
* invoked directly.
|
||||
*/
|
||||
JVM_ENTRY(jobject, VH_UOE(JNIEnv* env, jobject vh, jobjectArray args)) {
|
||||
THROW_MSG_NULL(vmSymbols::java_lang_UnsupportedOperationException(), "VarHandle access mode methods cannot be invoked reflectively");
|
||||
return nullptr;
|
||||
}
|
||||
JVM_END
|
||||
|
||||
|
||||
/// JVM_RegisterMethodHandleMethods
|
||||
|
||||
#define LANG "Ljava/lang/"
|
||||
@ -1399,6 +1411,40 @@ static JNINativeMethod MH_methods[] = {
|
||||
{CC "invoke", CC "([" OBJ ")" OBJ, FN_PTR(MH_invoke_UOE)},
|
||||
{CC "invokeExact", CC "([" OBJ ")" OBJ, FN_PTR(MH_invokeExact_UOE)}
|
||||
};
|
||||
static JNINativeMethod VH_methods[] = {
|
||||
// UnsupportedOperationException throwers
|
||||
{CC "get", CC "([" OBJ ")" OBJ, FN_PTR(VH_UOE)},
|
||||
{CC "set", CC "([" OBJ ")V", FN_PTR(VH_UOE)},
|
||||
{CC "getVolatile", CC "([" OBJ ")" OBJ, FN_PTR(VH_UOE)},
|
||||
{CC "setVolatile", CC "([" OBJ ")V", FN_PTR(VH_UOE)},
|
||||
{CC "getAcquire", CC "([" OBJ ")" OBJ, FN_PTR(VH_UOE)},
|
||||
{CC "setRelease", CC "([" OBJ ")V", FN_PTR(VH_UOE)},
|
||||
{CC "getOpaque", CC "([" OBJ ")" OBJ, FN_PTR(VH_UOE)},
|
||||
{CC "setOpaque", CC "([" OBJ ")V", FN_PTR(VH_UOE)},
|
||||
{CC "compareAndSet", CC "([" OBJ ")Z", FN_PTR(VH_UOE)},
|
||||
{CC "compareAndExchange", CC "([" OBJ ")" OBJ, FN_PTR(VH_UOE)},
|
||||
{CC "compareAndExchangeAcquire", CC "([" OBJ ")" OBJ, FN_PTR(VH_UOE)},
|
||||
{CC "compareAndExchangeRelease", CC "([" OBJ ")" OBJ, FN_PTR(VH_UOE)},
|
||||
{CC "weakCompareAndSetPlain", CC "([" OBJ ")Z", FN_PTR(VH_UOE)},
|
||||
{CC "weakCompareAndSet", CC "([" OBJ ")Z", FN_PTR(VH_UOE)},
|
||||
{CC "weakCompareAndSetAcquire", CC "([" OBJ ")Z", FN_PTR(VH_UOE)},
|
||||
{CC "weakCompareAndSetRelease", CC "([" OBJ ")Z", FN_PTR(VH_UOE)},
|
||||
{CC "getAndSet", CC "([" OBJ ")" OBJ, FN_PTR(VH_UOE)},
|
||||
{CC "getAndSetAcquire", CC "([" OBJ ")" OBJ, FN_PTR(VH_UOE)},
|
||||
{CC "getAndSetRelease", CC "([" OBJ ")" OBJ, FN_PTR(VH_UOE)},
|
||||
{CC "getAndAdd", CC "([" OBJ ")" OBJ, FN_PTR(VH_UOE)},
|
||||
{CC "getAndAddAcquire", CC "([" OBJ ")" OBJ, FN_PTR(VH_UOE)},
|
||||
{CC "getAndAddRelease", CC "([" OBJ ")" OBJ, FN_PTR(VH_UOE)},
|
||||
{CC "getAndBitwiseOr", CC "([" OBJ ")" OBJ, FN_PTR(VH_UOE)},
|
||||
{CC "getAndBitwiseOrAcquire", CC "([" OBJ ")" OBJ, FN_PTR(VH_UOE)},
|
||||
{CC "getAndBitwiseOrRelease", CC "([" OBJ ")" OBJ, FN_PTR(VH_UOE)},
|
||||
{CC "getAndBitwiseAnd", CC "([" OBJ ")" OBJ, FN_PTR(VH_UOE)},
|
||||
{CC "getAndBitwiseAndAcquire", CC "([" OBJ ")" OBJ, FN_PTR(VH_UOE)},
|
||||
{CC "getAndBitwiseAndRelease", CC "([" OBJ ")" OBJ, FN_PTR(VH_UOE)},
|
||||
{CC "getAndBitwiseXor", CC "([" OBJ ")" OBJ, FN_PTR(VH_UOE)},
|
||||
{CC "getAndBitwiseXorAcquire", CC "([" OBJ ")" OBJ, FN_PTR(VH_UOE)},
|
||||
{CC "getAndBitwiseXorRelease", CC "([" OBJ ")" OBJ, FN_PTR(VH_UOE)}
|
||||
};
|
||||
|
||||
/**
|
||||
* This one function is exported, used by NativeLookup.
|
||||
@ -1406,9 +1452,12 @@ static JNINativeMethod MH_methods[] = {
|
||||
JVM_ENTRY(void, JVM_RegisterMethodHandleMethods(JNIEnv *env, jclass MHN_class)) {
|
||||
assert(!MethodHandles::enabled(), "must not be enabled");
|
||||
assert(vmClasses::MethodHandle_klass() != nullptr, "should be present");
|
||||
assert(vmClasses::VarHandle_klass() != nullptr, "should be present");
|
||||
|
||||
oop mirror = vmClasses::MethodHandle_klass()->java_mirror();
|
||||
jclass MH_class = (jclass) JNIHandles::make_local(THREAD, mirror);
|
||||
oop mh_mirror = vmClasses::MethodHandle_klass()->java_mirror();
|
||||
oop vh_mirror = vmClasses::VarHandle_klass()->java_mirror();
|
||||
jclass MH_class = (jclass) JNIHandles::make_local(THREAD, mh_mirror);
|
||||
jclass VH_class = (jclass) JNIHandles::make_local(THREAD, vh_mirror);
|
||||
|
||||
{
|
||||
ThreadToNativeFromVM ttnfv(thread);
|
||||
@ -1420,6 +1469,10 @@ JVM_ENTRY(void, JVM_RegisterMethodHandleMethods(JNIEnv *env, jclass MHN_class))
|
||||
status = env->RegisterNatives(MH_class, MH_methods, sizeof(MH_methods)/sizeof(JNINativeMethod));
|
||||
guarantee(status == JNI_OK && !env->ExceptionOccurred(),
|
||||
"register java.lang.invoke.MethodHandle natives");
|
||||
|
||||
status = env->RegisterNatives(VH_class, VH_methods, sizeof(VH_methods)/sizeof(JNINativeMethod));
|
||||
guarantee(status == JNI_OK && !env->ExceptionOccurred(),
|
||||
"register java.lang.invoke.VarHandle natives");
|
||||
}
|
||||
|
||||
log_debug(methodhandles, indy)("MethodHandle support loaded (using LambdaForms)");
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -33,6 +33,7 @@ import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandleInfo;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@ -52,15 +53,33 @@ public class VarHandleTestReflection extends VarHandleBaseTest {
|
||||
}
|
||||
|
||||
@Test(dataProvider = "accessModesProvider", expectedExceptions = IllegalArgumentException.class)
|
||||
public void methodInvocation(VarHandle.AccessMode accessMode) throws Exception {
|
||||
public void methodInvocationArgumentMismatch(VarHandle.AccessMode accessMode) throws Exception {
|
||||
VarHandle v = handle();
|
||||
|
||||
// Try a reflective invoke using a Method
|
||||
// Try a reflective invoke using a Method, with no arguments
|
||||
|
||||
Method vhm = VarHandle.class.getMethod(accessMode.methodName(), Object[].class);
|
||||
vhm.invoke(v, new Object[]{});
|
||||
}
|
||||
|
||||
@Test(dataProvider = "accessModesProvider")
|
||||
public void methodInvocationMatchingArguments(VarHandle.AccessMode accessMode) throws Exception {
|
||||
VarHandle v = handle();
|
||||
|
||||
// Try a reflective invoke using a Method, with the minimal required arguments
|
||||
|
||||
Method vhm = VarHandle.class.getMethod(accessMode.methodName(), Object[].class);
|
||||
Object arg = new Object[0];
|
||||
try {
|
||||
vhm.invoke(v, arg);
|
||||
} catch (InvocationTargetException e) {
|
||||
if (!(e.getCause() instanceof UnsupportedOperationException)) {
|
||||
throw new RuntimeException("expected UnsupportedOperationException but got: "
|
||||
+ e.getCause().getClass().getName(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "accessModesProvider", expectedExceptions = UnsupportedOperationException.class)
|
||||
public void methodHandleInvoke(VarHandle.AccessMode accessMode) throws Throwable {
|
||||
VarHandle v = handle();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user