mybatis/mybatis-3 · error · ReflectionException
Failed to invoke 'Class.isRecord()'.
Error message
Failed to invoke 'Class.isRecord()'.
What it means
Reflector caches a MethodHandle for Class.isRecord() (absent on Java < 16) and invokes it via invokeExact to detect record classes. This ReflectionException means the invoke itself threw — the handle existed but the exact invocation failed, which should not happen on a standard JVM.
Source
Thrown at src/main/java/org/apache/ibatis/reflection/Reflector.java:491
*
* @return True if the object has a readable property by the name
*/
public boolean hasGetter(String propertyName) {
return getMethods.containsKey(propertyName);
}
public String findPropertyName(String name) {
return caseInsensitivePropertyMap.get(name.toUpperCase(Locale.ENGLISH));
}
/**
* Class.isRecord() alternative for Java 15 and older.
*/
private static boolean isRecord(Class<?> clazz) {
try {
return isRecordMethodHandle != null && (boolean) isRecordMethodHandle.invokeExact(clazz);
} catch (Throwable e) {
throw new ReflectionException("Failed to invoke 'Class.isRecord()'.", e);
}
}
private static MethodHandle getIsRecordMethodHandle() {
MethodHandles.Lookup lookup = MethodHandles.lookup();
MethodType mt = MethodType.methodType(boolean.class);
try {
return lookup.findVirtual(Class.class, "isRecord", mt);
} catch (NoSuchMethodException | IllegalAccessException e) {
return null;
}
}
}
View on GitHub (pinned to 008069adb1)
Solutions
- Run on a standard JDK 16+ (or any supported stock JDK) and re-test.
- Disable class transformers/agents that rewrite java.lang.Class or the application classes involved.
- If on GraalVM native-image, ensure a recent version with full MethodHandle support and proper reflection metadata registered.
Defensive patterns
Strategy: fallback
Validate before calling
if (Runtime.version().feature() >= 16 && Runtime.getPages... ) { /* placeholder */ }
// simpler: detect standard JVM before relying on record resultTypes
boolean recordsSafe = System.getProperty("java.vm.vendor", "").contains("Oracle") || System.getProperty("java.vm.name", "").contains("HotSpot"); Try / catch
try {
sessionFactory.getConfiguration().addMapper(RecordMapper.class);
} catch (ReflectionException e) {
if (e.getMessage().contains("isRecord")) {
// fall back to a class-based DTO instead of a record on this runtime
}
} Prevention
- Test record resultTypes on the exact production JVM early in the project.
- Keep a class-based DTO variant for environments with restricted MethodHandle support.
When it happens
Trigger: Running on a non-standard JVM or bytecode-rewritten runtime (AOP agents, Android-derived runtimes, some GraalVM/native-image configurations) where MethodHandle invocation of Class.isRecord fails; also possible if the class is redefined concurrently.
Common situations: Record resultTypes under an instrumented/transformed classloader; exotic JVM forks; native-image builds where method handle intrinsics are unavailable.
Related errors
- There is no 'privateLookupIn(Class, Lookup)' method in java.
- Error creating instance. Cause: {cause}
- Error in result map '{resultMapId}'. Failed to find a constr
- Failed to create a new Configuration instance.
- Cannot get Configuration as factory method [" + this.configu
AI-assisted analysis of mybatis/mybatis-3@008069adb1 (2026-08-14).
Data as JSON: /api/errors/1f359106cd1481fc.
Report an issue: GitHub.