# Ghidra Extension Points and ServiceProvider API: Complete Implementation Guide

> Master Ghidra extension points and the ServiceProvider API. Learn how to implement dynamic service lookup for loose coupling in your plugins and extensions.

- Repository: [National Security Agency/ghidra](https://github.com/NationalSecurityAgency/ghidra)
- Tags: how-to-guide
- Published: 2026-03-04

---

**Ghidra extension points are marker interfaces discovered at runtime through suffix-based manifest files, while the ServiceProvider API enables loose coupling between plugins by allowing dynamic lookup of shared services.**

The NationalSecurityAgency/ghidra repository implements a sophisticated plugin architecture that centers on two core abstractions: extension points for automatic class discovery and service providers for dependency injection. Understanding how `ghidra.util.classfinder.ExtensionPoint` and `ghidra.framework.plugintool.ServiceProvider` interact allows developers to build modular extensions that integrate seamlessly with Ghidra's reverse engineering framework.

## Understanding Ghidra Extension Points

Extension points form the backbone of Ghidra's modularity, allowing third-party code to be discovered and loaded without explicit registration in a central registry.

### The ExtensionPoint Marker Interface

At the core of this system is `ghidra.util.classfinder.ExtensionPoint`, a marker interface located in [`Ghidra/Framework/Generic/src/main/java/ghidra/util/classfinder/ExtensionPoint.java`](https://github.com/NationalSecurityAgency/ghidra/blob/main/Ghidra/Framework/Generic/src/main/java/ghidra/util/classfinder/ExtensionPoint.java). Any class wishing to participate in automatic discovery must implement this interface, but implementation alone is insufficient for loading.

The critical requirement is the **suffix rule**: Ghidra's `ClassSearcher` only loads classes whose simple names end with suffixes declared in `data/ExtensionPoint.manifest` files. For example, classes ending in "Initializer", "Provider", or "Factory" are loaded only if those suffixes appear in a manifest file within the module's `data/` directory.

### The Discovery Mechanism

Discovery occurs at startup through `ClassSearcher` ([`Ghidra/Framework/Generic/src/main/java/ghidra/util/classfinder/ClassSearcher.java`](https://github.com/NationalSecurityAgency/ghidra/blob/main/Ghidra/Framework/Generic/src/main/java/ghidra/util/classfinder/ClassSearcher.java)), which performs three operations:

1. **Gather suffixes** from every module's `data/ExtensionPoint.manifest` file (e.g., `Ghidra/Framework/Generic/data/ExtensionPoint.manifest`)
2. **Scan the classpath** for classes ending with those suffixes
3. **Instantiate** valid classes via their no-arg constructor and sort them by priority

Common extension point interfaces in the codebase include:
- **`ghidra.service.graph.GraphDisplayProvider`** – Supplies graph viewer implementations ([`Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/service/graph/GraphDisplayProvider.java`](https://github.com/NationalSecurityAgency/ghidra/blob/main/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/service/graph/GraphDisplayProvider.java))
- **`ghidra.pcode.exec.PcodeUseropLibraryFactory`** – Provides custom P-code user-ops for the emulator ([`Ghidra/Framework/Emulation/src/main/java/ghidra/pcode/exec/PcodeUseropLibraryFactory.java`](https://github.com/NationalSecurityAgency/ghidra/blob/main/Ghidra/Framework/Emulation/src/main/java/ghidra/pcode/exec/PcodeUseropLibraryFactory.java))
- **`ghidra.program.util.LanguageTranslator`** – Translates between language specifications ([`Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/util/LanguageTranslator.java`](https://github.com/NationalSecurityAgency/ghidra/blob/main/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/util/LanguageTranslator.java))

### Controlling Loading with Annotations

The `@ExtensionPointProperties` annotation ([`Ghidra/Framework/Generic/src/main/java/ghidra/util/classfinder/ExtensionPointProperties.java`](https://github.com/NationalSecurityAgency/ghidra/blob/main/Ghidra/Framework/Generic/src/main/java/ghidra/util/classfinder/ExtensionPointProperties.java)) provides two key controls:

- **Priority**: Higher integer values load first (useful when order matters)
- **Exclusion**: Set `exclude=true` to prevent automatic discovery while keeping the interface implementation

```java
import ghidra.util.classfinder.ExtensionPointProperties;

@ExtensionPointProperties(priority = 100)
public class HighPriorityProvider implements SomeExtensionPoint {
    // This loads before providers with lower priority values
}

```

## Implementing Extension Points in Your Plugin

To create a discoverable extension, you must define the interface, declare the suffix in a manifest, and implement the contract.

### Step 1: Define the Extension Point Interface

Create an interface extending `ExtensionPoint`:

```java
package com.example.ghidra.extensions;

import ghidra.util.classfinder.ExtensionPoint;

public interface AnalysisReporter extends ExtensionPoint {
    void reportFinding(String address, String details);
}

```

### Step 2: Register the Suffix

Create `data/ExtensionPoint.manifest` in your extension's root directory containing:

```

Reporter

```

### Step 3: Implement and Deploy

Implement the interface with a class whose name ends in the registered suffix:

```java
package com.example.ghidra.extensions.impl;

import com.example.ghidra.extensions.AnalysisReporter;

public class ConsoleAnalysisReporter implements AnalysisReporter {
    @Override
    public void reportFinding(String address, String details) {
        System.out.printf("[Analysis] %s: %s%n", address, details);
    }
}

```

When Ghidra starts, `ClassSearcher` automatically instantiates `ConsoleAnalysisReporter` because its name ends with "Reporter" and it implements `ExtensionPoint`.

## Using the ServiceProvider API

While extension points enable discovery, the ServiceProvider API enables runtime collaboration between plugins through dependency injection.

### Core ServiceProvider Interfaces

The service provider infrastructure resides in `Ghidra/Framework/Utility/src/main/java/ghidra/framework/plugintool/` and consists of three primary components:

- **`ServiceProvider`** – The contract defining `getService(Class<T>)` for service retrieval
- **`ServiceProviderStub`** – A minimal implementation returning `null` for all services, useful in unit tests
- **`ServiceProviderDecorator`** – Wraps existing providers to add or override services without modifying the original

### Accessing Services in Plugins

Plugins receive a `ServiceProvider` through the `PluginTool` instance. In [`Ghidra/Framework/Utility/src/main/java/ghidra/framework/plugintool/Plugin.java`](https://github.com/NationalSecurityAgency/ghidra/blob/main/Ghidra/Framework/Utility/src/main/java/ghidra/framework/plugintool/Plugin.java), which implements `ExtensionPoint`, the standard pattern retrieves services in the constructor:

```java
import ghidra.framework.plugintool.Plugin;
import ghidra.framework.plugintool.PluginTool;
import ghidra.framework.plugintool.ServiceProvider;
import ghidra.app.services.GraphService;

public class MyAnalysisPlugin extends Plugin {
    private final GraphService graphService;
    
    public MyAnalysisPlugin(PluginTool tool) {
        super(tool);
        ServiceProvider services = tool.getServiceProvider();
        this.graphService = services.getService(GraphService.class);
    }
}

```

### Decorating and Extending Service Providers

To expose your own services to other plugins, use `ServiceProviderDecorator` ([`ServiceProviderDecorator.java`](https://github.com/NationalSecurityAgency/ghidra/blob/main/ServiceProviderDecorator.java)):

```java
import ghidra.framework.plugintool.ServiceProvider;
import ghidra.framework.plugintool.ServiceProviderDecorator;

ServiceProvider original = tool.getServiceProvider();
ServiceProvider enhanced = ServiceProviderDecorator.decorate(original)
    .addService(MyCustomService.class, new MyCustomServiceImpl())
    .getProvider();
tool.setServiceProvider(enhanced);

```

This pattern allows plugins to layer capabilities without requiring other plugins to import your implementation classes directly.

## Complete Integration Example

The following example demonstrates defining an extension point, implementing it, and consuming it through the ServiceProvider API:

```java
// Extension point definition
package example;
import ghidra.util.classfinder.ExtensionPoint;

public interface LogFormatter extends ExtensionPoint {
    String format(String message);
}

// Implementation (discovered automatically if "Formatter" is in ExtensionPoint.manifest)
package example.impl;
import example.LogFormatter;

public class TimestampLogFormatter implements LogFormatter {
    @Override
    public String format(String message) {
        return String.format("[%tF %<tT] %s", System.currentTimeMillis(), message);
    }
}

// Consumer using ServiceProvider to access the extension
package example.client;
import ghidra.framework.plugintool.ServiceProvider;
import ghidra.util.classfinder.ClassSearcher;
import example.LogFormatter;
import java.util.List;

public class LogClient {
    private final ServiceProvider provider;
    
    public LogClient(ServiceProvider provider) {
        this.provider = provider;
    }
    
    public void logAllServices() {
        // Direct discovery via ClassSearcher
        List<LogFormatter> formatters = ClassSearcher.getInstances(LogFormatter.class);
        
        for (LogFormatter formatter : formatters) {
            System.out.println(formatter.format("System initialized"));
        }
    }
}

```

Note that while `ClassSearcher` provides direct access to extension point implementations, exposing them through `ServiceProvider` enables other plugins to retrieve them via the standard service lookup mechanism.

## Summary

- **Extension points** require implementing `ghidra.util.classfinder.ExtensionPoint` and following the suffix naming convention defined in `data/ExtensionPoint.manifest` files for automatic discovery by `ClassSearcher`.
- **Discovery order** can be controlled via the `@ExtensionPointProperties` annotation using priority values or exclusion flags.
- **ServiceProvider** (`ghidra.framework.plugintool.ServiceProvider`) decouples plugins by allowing runtime lookup of services rather than compile-time dependencies.
- **ServiceProviderDecorator** enables extending service capabilities without modifying existing provider implementations, supporting layered plugin architectures.
- **PluginTool** serves as the primary source of `ServiceProvider` instances for plugins, retrieved via `getServiceProvider()` in the plugin constructor.

## Frequently Asked Questions

### What is the difference between an ExtensionPoint and a ServiceProvider?

An **ExtensionPoint** is a marker interface for classes that Ghidra discovers and instantiates automatically at startup based on naming suffixes in manifest files. A **ServiceProvider** is a runtime lookup mechanism that allows plugins to retrieve shared objects (services) dynamically using `getService(Class<T>)`. Extension points define *what* can be extended; ServiceProvider defines *how* plugins share functionality.

### How does Ghidra automatically discover my extension point implementation?

Ghidra's `ClassSearcher` ([`Ghidra/Framework/Generic/src/main/java/ghidra/util/classfinder/ClassSearcher.java`](https://github.com/NationalSecurityAgency/ghidra/blob/main/Ghidra/Framework/Generic/src/main/java/ghidra/util/classfinder/ClassSearcher.java)) scans the classpath at startup, reading every module's `data/ExtensionPoint.manifest` file to collect valid suffixes. It then instantiates any class whose simple name ends with a registered suffix and which implements the `ExtensionPoint` marker interface. Simply implementing the interface is insufficient; the suffix must be declared in a manifest file.

### Can I prevent my extension point from being loaded automatically?

Yes. Add the `@ExtensionPointProperties` annotation with `exclude=true` to your class declaration. Located in [`Ghidra/Framework/Generic/src/main/java/ghidra/util/classfinder/ExtensionPointProperties.java`](https://github.com/NationalSecurityAgency/ghidra/blob/main/Ghidra/Framework/Generic/src/main/java/ghidra/util/classfinder/ExtensionPointProperties.java), this annotation tells `ClassSearcher` to skip the class during discovery, allowing you to instantiate it manually or control its lifecycle programmatically.

### How do I access services from a class that is not a Plugin?

If your class does not extend `Plugin` but needs access to services, obtain a `ServiceProvider` instance from an existing plugin or tool context, or use `ServiceProviderStub` for testing scenarios. For standalone utilities, you can also use `ClassSearcher.getInstances(ServiceClass.class)` to discover implementations directly, though this bypasses the service lifecycle management that `PluginTool` provides.