{"record":{"id":"0450f6b28145954a","repo":"LSPosed/LSPosed","slug":"subclass-is-not-inherited-from-superclass","errorCode":null,"errorMessage":"${subClass} is not inherited from ${superClass}","messagePattern":"(.+?) is not inherited from (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/lsposed/lspd/impl/LSPosedContext.java","lineNumber":272,"sourceCode":"            throw new IllegalArgumentException(\"Cannot invoke special on static method: \" + method);\n        }\n        return HookBridge.invokeSpecialMethod(method, getExecutableShorty(method), method.getDeclaringClass(), thisObject, args);\n    }\n\n    @NonNull\n    @Override\n    public <T> T newInstanceOrigin(@NonNull Constructor<T> constructor, Object... args) throws InvocationTargetException, IllegalAccessException, InstantiationException {\n        var obj = HookBridge.allocateObject(constructor.getDeclaringClass());\n        HookBridge.invokeOriginalMethod(constructor, obj, args);\n        return obj;\n    }\n\n    @NonNull\n    @Override\n    public <T, U> U newInstanceSpecial(@NonNull Constructor<T> constructor, @NonNull Class<U> subClass, Object... args) throws InvocationTargetException, IllegalArgumentException, IllegalAccessException, InstantiationException {\n        var superClass = constructor.getDeclaringClass();\n        if (!superClass.isAssignableFrom(subClass)) {\n            throw new IllegalArgumentException(subClass + \" is not inherited from \" + superClass);\n        }\n        var obj = HookBridge.allocateObject(subClass);\n        HookBridge.invokeSpecialMethod(constructor, getExecutableShorty(constructor), superClass, obj, args);\n        return obj;\n    }\n\n    @Override\n    public void log(@NonNull String message) {\n        Log.i(TAG, mPackageName + \": \" + message);\n    }\n\n    @Override\n    public void log(@NonNull String message, @NonNull Throwable throwable) {\n        Log.e(TAG, mPackageName + \": \" + message, throwable);\n    }\n\n    @Override\n    public DexParser parseDex(@NonNull ByteBuffer dexData, boolean includeAnnotations) throws IOException {","sourceCodeStart":254,"sourceCodeEnd":290,"githubUrl":"https://github.com/LSPosed/LSPosed/blob/df74d83eb03a44cc6ad268841ac2ada28d077c77/core/src/main/java/org/lsposed/lspd/impl/LSPosedContext.java#L254-L290","documentation":"newInstanceSpecial allocates an instance of subClass and runs the superclass constructor on it via invokespecial. For that to be legal, subClass must actually inherit from the constructor's declaring class; LSPosedContext checks superClass.isAssignableFrom(subClass) (line 272) and throws IllegalArgumentException naming both classes otherwise.","triggerScenarios":"Calling context.newInstanceSpecial(constructor, subClass, args) where subClass is not a subclass (or subinterface/array type) of constructor.getDeclaringClass().","commonSituations":"Passing an unrelated class or the declaring class itself when the constructor belongs to a different branch of the hierarchy; refactoring that moved the constructor's class so the old subClass argument no longer extends it.","solutions":["Pass a class that genuinely extends constructor.getDeclaringClass()","Derive the argument from the constructor itself if possible, or assert the relation before calling","If you just want a normal instance of the declaring class, use newInstanceOrigin(constructor, args)"],"exampleFix":"// before\nObject o = context.newInstanceSpecial(BaseCtor, UnrelatedClass.class, args);\n\n// after\nassert BaseCtor.getDeclaringClass().isAssignableFrom(ChildClass.class);\nObject o = context.newInstanceSpecial(BaseCtor, ChildClass.class, args);","handlingStrategy":"validation","validationCode":"Class<?> sup = constructor.getDeclaringClass();\nif (!sup.isAssignableFrom(subClass)) {\n    throw new IllegalArgumentException(subClass + \" must extend \" + sup);\n}\nreturn context.newInstanceSpecial(constructor, subClass, args);","typeGuard":"static boolean isValidSpecialTarget(Constructor<?> ctor, Class<?> sub) {\n    return ctor.getDeclaringClass().isAssignableFrom(sub);\n}","tryCatchPattern":null,"preventionTips":["Assert isAssignableFrom before newInstanceSpecial","Derive subClass from the same hierarchy as the constructor, or just use newInstanceOrigin for normal instantiation"],"tags":["reflection","instantiation","type-mismatch","argument-error","lsposed"],"backgroundTag":null,"analyzedSha":"df74d83eb03a44cc6ad268841ac2ada28d077c77","analyzedAt":"2026-08-14T10:46:48.326Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}