{"record":{"id":"4d4fb3ef7ca85c2a","repo":"Tencent/matrix","slug":"both-of-invoker-and-fieldname-can-not-be-null-or-n-4d4fb3","errorCode":null,"errorMessage":"Both of invoker and fieldName can not be null or nil.","messagePattern":"Both of invoker and fieldName can not be null or nil\\.","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"matrix/matrix-android/matrix-android-lib/src/main/java/com/tencent/matrix/util/ReflectMethod.java","lineNumber":18,"sourceCode":"package com.tencent.matrix.util;\n\n\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\n\npublic class ReflectMethod {\n    private static final String TAG = \"ReflectFiled\";\n    private Class<?> mClazz;\n    private String mMethodName;\n\n    private boolean mInit;\n    private Method mMethod;\n    private Class[] mParameterTypes;\n\n    public ReflectMethod(Class<?> clazz, String methodName, Class<?>... parameterTypes) {\n        if (clazz == null || methodName == null || methodName.length() == 0) {\n            throw new IllegalArgumentException(\"Both of invoker and fieldName can not be null or nil.\");\n        }\n        this.mClazz = clazz;\n        this.mMethodName = methodName;\n        this.mParameterTypes = parameterTypes;\n    }\n\n    private synchronized void prepare() {\n        if (mInit) {\n            return;\n        }\n        Class<?> clazz = mClazz;\n        while (clazz != null) {\n            try {\n                Method method = clazz.getDeclaredMethod(mMethodName, mParameterTypes);\n                method.setAccessible(true);\n                mMethod = method;\n                break;\n            } catch (Exception e) {","sourceCodeStart":1,"sourceCodeEnd":36,"githubUrl":"https://github.com/Tencent/matrix/blob/3b8293bd65d47eeea7caf1f32a3a5d4d5eab60e7/matrix/matrix-android/matrix-android-lib/src/main/java/com/tencent/matrix/util/ReflectMethod.java#L1-L36","documentation":"ReflectMethod is a reflective helper that lazily resolves a java.lang.Method by name and parameter types from a target class. The constructor validates that both the target class and the method name are provided; if either is null or the method name is an empty string, it throws this IllegalArgumentException immediately (the message's 'invoker'/'fieldName' wording is a copy-paste artifact from a sibling class, but it means clazz/methodName). Failing fast here prevents a useless ReflectMethod instance that could never be invoked.","triggerScenarios":"new ReflectMethod(null, \"someMethod\") — clazz is null; or new ReflectMethod(SomeClass.class, null) / new ReflectMethod(SomeClass.class, \"\") — methodName is null or empty. Any parameterTypes are irrelevant to this check.","commonSituations":"Passing a Class fetched reflectively (Class.forName on a miss returns via exception but callers sometimes cache a null), building method names dynamically from string concatenation that yields \"\" or null (e.g. a config-driven hook name), or calling from Kotlin where a null String slipped through platform types.","solutions":["Ensure the Class argument is non-null before constructing (check the result of Class.forName or the constant class reference).","Ensure the method-name string is non-null and non-empty; trim and validate any dynamically built name.","If the method may legitimately be absent, verify the name against the target class with clazz.getDeclaredMethod(...) in a try/catch instead of passing a blank name.","For Kotlin callers, declare parameters as non-null types (Class, String) so the compiler rejects nulls at compile time."],"exampleFix":"// before\nReflectMethod method = new ReflectMethod(getCachedClass(name), buildMethodName(prefix), paramTypes);\n// after\nClass<?> clazz = getCachedClass(name);\nString methodName = buildMethodName(prefix);\nif (clazz == null || methodName == null || methodName.isEmpty()) {\n    MatrixLog.w(TAG, \"skip reflection: clazz=%s methodName=%s\", name, methodName);\n    return;\n}\nReflectMethod method = new ReflectMethod(clazz, methodName, paramTypes);","handlingStrategy":"validation","validationCode":"if (clazz == null) throw new IllegalArgumentException(\"clazz must not be null\");\nif (methodName == null || methodName.isEmpty()) throw new IllegalArgumentException(\"methodName must not be empty\");\nReflectMethod m = new ReflectMethod(clazz, methodName, paramTypes);","typeGuard":"boolean isValidTarget(Class<?> clazz, String name) {\n    return clazz != null && name != null && !name.isEmpty();\n}","tryCatchPattern":"try {\n    ReflectMethod m = new ReflectMethod(clazz, methodName);\n} catch (IllegalArgumentException e) {\n    MatrixLog.w(TAG, \"invalid reflection target: %s\", e.getMessage());\n}","preventionTips":["Validate class and method-name arguments before constructing ReflectMethod.","Never build method names by unchecked string concatenation; log the built name.","Use Kotlin non-null types to push the check to compile time.","Keep a null-check helper (e.g. Util.isNullOrNil) in your reflective utilities."],"tags":["reflection","android","illegal-argument","null-check"],"backgroundTag":"null-argument","analyzedSha":"3b8293bd65d47eeea7caf1f32a3a5d4d5eab60e7","analyzedAt":"2026-09-08T08:01:39.722Z","contentChangedAt":"2026-09-08T08:01:39.722Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}