{"record":{"id":"5063bb4145d665f3","repo":"NationalSecurityAgency/ghidra","slug":"constructor-must-be-a-non-static-method","errorCode":null,"errorMessage":"Constructor must be a non-static method","messagePattern":"Constructor must be a non-static method","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"Ghidra/Debug/ProposedUtils/src/main/java/generic/depends/DependentServiceResolver.java","lineNumber":75,"sourceCode":"\t\t}\n\t\tClass<?> superCls = cls.getSuperclass();\n\t\tif (superCls == null) {\n\t\t\treturn;\n\t\t}\n\t\taddClass(superCls);\n\t\tfor (Class<?> superIf : cls.getInterfaces()) {\n\t\t\taddClass(superIf);\n\t\t}\n\n\t\tfor (Method m : cls.getDeclaredMethods()) {\n\t\t\tDependentService annot = m.getAnnotation(DependentService.class);\n\t\t\tif (annot == null) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tint mods = m.getModifiers();\n\t\t\tif (Modifier.isStatic(mods)) {\n\t\t\t\tthrow new IllegalArgumentException(\"Constructor must be a non-static method\");\n\t\t\t}\n\n\t\t\tClass<?> override = annot.override();\n\t\t\tClass<?> rCls = m.getReturnType();\n\t\t\tif (override != DependentService.Sentinel.class) {\n\t\t\t\tif (!override.isAssignableFrom(rCls)) {\n\t\t\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\t\t\"Overridden constructor must return same or subclass of original\");\n\t\t\t\t}\n\t\t\t\tdepsByDependents.computeIfAbsent(override, o -> new HashSet<>()).add(rCls);\n\t\t\t\tconstructors.put(override, m);\n\t\t\t}\n\t\t\tconstructors.put(rCls, m);\n\t\t\tm.setAccessible(true);\n\n\t\t\tfor (Class<?> pType : m.getParameterTypes()) {\n\t\t\t\tdepsByDependents.computeIfAbsent(rCls, c -> new HashSet<>()).add(pType);\n\t\t\t}","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/NationalSecurityAgency/ghidra/blob/d5f144c24d6bc53c9cbf4448c6d11143e7696206/Ghidra/Debug/ProposedUtils/src/main/java/generic/depends/DependentServiceResolver.java#L57-L93","documentation":"Thrown by DependentServiceResolver.addClass() when a method annotated @DependentService is declared static. The DI framework constructs services by invoking the factory on a receiver instance, so a static method has no valid receiver and cannot participate. Non-static is an enforced precondition.","triggerScenarios":"Adding @DependentService to a static helper or utility method. Declaring the factory method static because it does not use instance state. Migrating an instance method to static and forgetting to drop the annotation.","commonSituations":"Refactoring that turns an instance factory method static; utility-class-style service factories; copy-paste of an annotation onto a static builder method.","solutions":["Make the @DependentService method an instance (non-static) method.","If the logic must be static, wrap it in a thin instance method that delegates to the static helper, and annotate only the instance method.","Remove @DependentService from methods that should not be DI factories."],"exampleFix":"// before\npublic class Factory {\n  @DependentService\n  public static MyService create() { return new MyService(); } // static -> throws\n}\n\n// after\npublic class Factory {\n  @DependentService\n  public MyService create() { return new MyService(); } // instance method\n}","handlingStrategy":"validation","validationCode":"for (Method m : cls.getDeclaredMethods()) {\n  if (m.getAnnotation(DependentService.class) != null &&\n      Modifier.isStatic(m.getModifiers())) {\n    throw new IllegalStateException(\"Remove @DependentService or de-static \" + m);\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep @DependentService methods instance-level.","Run a build/test after converting any method to static.","Use static analysis or a reflective test to scan for static annotated methods."],"tags":["ghidra","dependency-injection","reflection","static-method"],"backgroundTag":null,"analyzedSha":"d5f144c24d6bc53c9cbf4448c6d11143e7696206","analyzedAt":"2026-08-14T01:00:57.564Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}