Gracefully skip non-assignable lambda callbacks on Java 18.

We now consider IllegalArgumentException as marker for incompatible lambda payload that was introduced with Java 18's reflection rewrite that uses method handles internally.

Closes #2583
This commit is contained in:
Mark Paluch
2022-03-23 10:43:53 +01:00
parent 35418205e7
commit f5ee277a6e
3 changed files with 40 additions and 14 deletions

View File

@@ -109,7 +109,7 @@ class DefaultEntityCallbacks implements EntityCallbacks {
throw new IllegalArgumentException(
String.format("Callback invocation on %s returned null value for %s", callback.getClass(), entity));
} catch (ClassCastException ex) {
} catch (IllegalArgumentException | ClassCastException ex) {
var msg = ex.getMessage();
if (msg == null || EntityCallbackInvoker.matchesClassCastMessage(msg, entity.getClass())) {

View File

@@ -35,21 +35,26 @@ interface EntityCallbackInvoker {
<T> Object invokeCallback(EntityCallback<T> callback, T entity,
BiFunction<EntityCallback<T>, T, Object> callbackInvokerFunction);
static boolean matchesClassCastMessage(String classCastMessage, Class<?> eventClass) {
static boolean matchesClassCastMessage(String exceptionMessage, Class<?> eventClass) {
// On Java 8, the message starts with the class name: "java.lang.String cannot be cast..."
if (classCastMessage.startsWith(eventClass.getName())) {
if (exceptionMessage.startsWith(eventClass.getName())) {
return true;
}
// On Java 11, the message starts with "class ..." a.k.a. Class.toString()
if (classCastMessage.startsWith(eventClass.toString())) {
if (exceptionMessage.startsWith(eventClass.toString())) {
return true;
}
// On Java 9, the message used to contain the module name: "java.base/java.lang.String cannot be cast..."
var moduleSeparatorIndex = classCastMessage.indexOf('/');
if (moduleSeparatorIndex != -1 && classCastMessage.startsWith(eventClass.getName(), moduleSeparatorIndex + 1)) {
var moduleSeparatorIndex = exceptionMessage.indexOf('/');
if (moduleSeparatorIndex != -1 && exceptionMessage.startsWith(eventClass.getName(), moduleSeparatorIndex + 1)) {
return true;
}
// On Java 18, the message is "IllegalArgumentException: argument type mismatch"
if (exceptionMessage.equals("argument type mismatch")) {
return true;
}