NationalSecurityAgency/ghidra · error · IllegalArgumentException

Constructor must be a non-static method

Error message

Constructor must be a non-static method

What it means

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.

Source

Thrown at Ghidra/Debug/ProposedUtils/src/main/java/generic/depends/DependentServiceResolver.java:75

		}
		Class<?> superCls = cls.getSuperclass();
		if (superCls == null) {
			return;
		}
		addClass(superCls);
		for (Class<?> superIf : cls.getInterfaces()) {
			addClass(superIf);
		}

		for (Method m : cls.getDeclaredMethods()) {
			DependentService annot = m.getAnnotation(DependentService.class);
			if (annot == null) {
				continue;
			}

			int mods = m.getModifiers();
			if (Modifier.isStatic(mods)) {
				throw new IllegalArgumentException("Constructor must be a non-static method");
			}

			Class<?> override = annot.override();
			Class<?> rCls = m.getReturnType();
			if (override != DependentService.Sentinel.class) {
				if (!override.isAssignableFrom(rCls)) {
					throw new IllegalArgumentException(
						"Overridden constructor must return same or subclass of original");
				}
				depsByDependents.computeIfAbsent(override, o -> new HashSet<>()).add(rCls);
				constructors.put(override, m);
			}
			constructors.put(rCls, m);
			m.setAccessible(true);

			for (Class<?> pType : m.getParameterTypes()) {
				depsByDependents.computeIfAbsent(rCls, c -> new HashSet<>()).add(pType);
			}

View on GitHub (pinned to d5f144c24d)

Solutions

  1. Make the @DependentService method an instance (non-static) method.
  2. 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.
  3. Remove @DependentService from methods that should not be DI factories.

Example fix

// before
public class Factory {
  @DependentService
  public static MyService create() { return new MyService(); } // static -> throws
}

// after
public class Factory {
  @DependentService
  public MyService create() { return new MyService(); } // instance method
}
Defensive patterns

Strategy: validation

Validate before calling

for (Method m : cls.getDeclaredMethods()) {
  if (m.getAnnotation(DependentService.class) != null &&
      Modifier.isStatic(m.getModifiers())) {
    throw new IllegalStateException("Remove @DependentService or de-static " + m);
  }
}

Prevention

When it happens

Trigger: 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.

Common situations: Refactoring that turns an instance factory method static; utility-class-style service factories; copy-paste of an annotation onto a static builder method.

Related errors


AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14). Data as JSON: /api/errors/5063bb4145d665f3. Report an issue: GitHub.