# How to Integrate SDS via Java Agent: Bytecode Instrumentation Guide

> Learn to integrate SDS via Java Agent with this guide. Instrument bytecode at JVM startup to protect methods using @SdsDowngradeMethod without altering business logic. Protect your applications easily.

- Repository: [DiDi/sds](https://github.com/didi/sds)
- Tags: how-to-guide
- Published: 2026-02-28

---

**The SDS Java Agent integrates Service Degradation System capabilities into your application by instrumenting bytecode at JVM startup, allowing you to protect methods with the `@SdsDowngradeMethod` annotation without modifying business logic.**

SDS (Service Degradation System) is an open-source framework developed by Didi that provides automatic circuit breaking and degradation capabilities for Java applications. By leveraging the Java Agent mechanism, SDS can weave degradation logic into your application transparently at runtime. This article explains the instrumentation principle and step-by-step configuration for integrating SDS via Java Agent based on the actual implementation in the `didi/sds` repository.

## How the SDS Java Agent Works

### Bytecode Instrumentation Architecture

When you launch the JVM with the SDS agent attached, the entry point `SdsBootStrap.premain` executes before the application's `main` method. This method, located in [`sds-bootstrap/src/main/java/com/didiglobal/sds/bootstrap/SdsBootStrap.java`](https://github.com/didi/sds/blob/main/sds-bootstrap/src/main/java/com/didiglobal/sds/bootstrap/SdsBootStrap.java), performs three critical operations:

1. Parses the agent arguments to extract configuration
2. Initializes the `SdsClient` singleton for server communication
3. Registers the `SdsClassFileTransformer` with the JVM's `Instrumentation` instance

```java
// From SdsBootStrap.java - registers the bytecode transformer
instrumentation.addTransformer(new SdsClassFileTransformer(param[3]));

```

### The Class File Transformer

The `SdsClassFileTransformer` (defined in [`sds-bootstrap/src/main/java/com/didiglobal/sds/bootstrap/transformer/SdsClassFileTransformer.java`](https://github.com/didi/sds/blob/main/sds-bootstrap/src/main/java/com/didiglobal/sds/bootstrap/transformer/SdsClassFileTransformer.java)) intercepts every class loaded by the JVM. It filters classes based on the configured package prefixes and searches for methods annotated with `@SdsDowngradeMethod`.

When such a method is found, the transformer uses Javassist to inject three distinct code blocks:

| Injection Point | Purpose | Code Logic |
|----------------|---------|------------|
| **Method Entry** | Check degradation status | Calls `SdsClient.shouldDowngrade(point)`; throws `SdsException` if degrading |
| **Catch Block** | Record exceptions | Invokes `SdsClient.exceptionSign(point, e)` for non-SDS exceptions |
| **Finally Block** | Update statistics | Always executes `SdsClient.downgradeFinally(point)` |

```java
// Excerpt from SdsClassFileTransformer showing injection logic
declaredMethod.insertBefore(
    String.format("SdsClient __sdsClient = SdsBootStrap.getClient(); " +
                  "if (__sdsClient != null && __sdsClient.shouldDowngrade(\"%s\")) {  " +
                  "  throw new SdsException(\"%s\", ExceptionCode.DOWNGRADE); } ",
                  sdsDowngradeMethod.point(), sdsDowngradeMethod.point()));

```

This approach ensures that **degradation logic is completely non-intrusive**—your business code remains clean while SDS handles protection transparently.

## Configuring the SDS Java Agent

### Building the Agent JAR

First, compile the bootstrap module to produce the agent JAR:

```bash
cd sds-bootstrap
mvn clean package -DskipTests

# Output: target/sds-bootstrap.jar

```

### JVM Startup Arguments

Attach the agent to your application using the `-javaagent` flag. The agent requires **four comma-separated parameters**:

1. **Application group name** – Logical grouping for services (e.g., `payment-group`)
2. **Application name** – Unique service identifier (e.g., `order-service`)
3. **SDS server URL** – Endpoint for fetching degradation strategies (e.g., `http://sds-server:8080`)
4. **Package scan list** – Semicolon-separated package prefixes to instrument (e.g., `com.mycorp.service;com.mycorp.controller`)

```bash
java -javaagent:/path/to/sds-bootstrap.jar=groupA,order-service,http://sds.example.com:8080,com.mycorp.service;com.mycorp.controller \
     -jar myapp.jar

```

The `SdsBootStrap.premain` method splits these arguments:

```java
String[] param = agentArgs.split(",");
// param[0] = group, param[1] = app, param[2] = url, param[3] = packages

```

### Maven Dependencies

Add the SDS client library to your project to access annotations and exceptions:

```xml
<dependency>
    <groupId>com.didiglobal.sds</groupId>
    <artifactId>sds-client</artifactId>
    <version>1.3.0</version>
</dependency>

```

This provides `SdsDowngradeMethod`, `SdsException`, and the `SdsClient` API.

### Annotating Methods for Protection

Mark methods requiring degradation protection with `@SdsDowngradeMethod`. The `point` attribute defines the degradation strategy identifier:

```java
import com.didiglobal.sds.client.annotation.SdsDowngradeMethod;

public class OrderService {

    @SdsDowngradeMethod(point = "order.create")
    public Order createOrder(Request req) {
        // Business logic
        return order;
    }
}

```

Optionally specify a `fallback` method for graceful degradation:

```java
@SdsDowngradeMethod(point = "order.update", fallback = "updateOrderFallback")
public void updateOrder(User user) {
    // Primary logic
}

public void updateOrderFallback(User user) {
    // Return cached data or queue for later processing
}

```

## Complete Integration Example

Build and run a protected service:

```bash

# Build the agent

cd sds-bootstrap
mvn clean package

# Launch application with SDS protection

java -javaagent:target/sds-bootstrap.jar=demoGroup,demoApp,http://localhost:8080,com.example.service \
     -jar ../target/my-service.jar

```

Application code with protection:

```java
package com.example.service;

import com.didiglobal.sds.client.annotation.SdsDowngradeMethod;
import com.didiglobal.sds.client.exception.SdsException;

public class UserService {

    @SdsDowngradeMethod(point = "user.get", fallback = "getUserFallback")
    public User getUser(Long id) {
        // Database call
        return userRepository.findById(id);
    }

    public User getUserFallback(Long id) {
        // Return default user or cached value
        return new User(id, "Default User");
    }

    @SdsDowngradeMethod(point = "user.update")
    public void updateUser(User user) {
        // Critical update operation
        userRepository.save(user);
    }
}

```

## Key Implementation Files

| File Path | Role |
|-----------|------|
| [`sds-bootstrap/src/main/java/com/didiglobal/sds/bootstrap/SdsBootStrap.java`](https://github.com/didi/sds/blob/main/sds-bootstrap/src/main/java/com/didiglobal/sds/bootstrap/SdsBootStrap.java) | Entry point containing `premain`; parses agent arguments and registers the class file transformer. |
| [`sds-bootstrap/src/main/java/com/didiglobal/sds/bootstrap/transformer/SdsClassFileTransformer.java`](https://github.com/didi/sds/blob/main/sds-bootstrap/src/main/java/com/didiglobal/sds/bootstrap/transformer/SdsClassFileTransformer.java) | Implements `ClassFileTransformer`; scans packages and injects degradation logic into annotated methods. |
| [`sds-client/src/main/java/com/didiglobal/sds/client/annotation/SdsDowngradeMethod.java`](https://github.com/didi/sds/blob/main/sds-client/src/main/java/com/didiglobal/sds/client/annotation/SdsDowngradeMethod.java) | Annotation definition used to mark methods requiring SDS protection. |
| [`sds-bootstrap/pom.xml`](https://github.com/didi/sds/blob/main/sds-bootstrap/pom.xml) | Maven configuration for building the `sds-bootstrap.jar` agent package. |

## Summary

- **Non-intrusive integration**: The SDS Java Agent uses bytecode instrumentation to inject degradation logic without modifying source code.
- **Three-point injection**: The agent wraps methods with `shouldDowngrade` checks at entry, `exceptionSign` in catch blocks, and `downgradeFinally` in finally blocks.
- **Four required parameters**: Configure the agent with application group, application name, SDS server URL, and semicolon-separated package prefixes.
- **Annotation-driven**: Simply add `@SdsDowngradeMethod(point="...")` to methods requiring protection, with optional fallback methods for graceful degradation.
- **Key classes**: `SdsBootStrap.premain` initializes the agent, while `SdsClassFileTransformer` performs the bytecode manipulation using Javassist.

## Frequently Asked Questions

### What is the performance overhead of the SDS Java Agent?

The SDS Java Agent performs bytecode transformation only once during class loading, so there is no ongoing compilation overhead. At runtime, the injected code performs simple boolean checks via `SdsClient.shouldDowngrade()`, which typically involves in-memory threshold comparisons. According to the implementation in `SdsClassFileTransformer`, the degradation check is a lightweight client-side operation that adds minimal latency—usually microseconds—unless the SDS server itself becomes a bottleneck.

### Can I use SDS without modifying my application code?

No, while the Java Agent handles the bytecode instrumentation automatically, you must still add the `@SdsDowngradeMethod` annotation to methods that require protection. This annotation serves as the marker for the `SdsClassFileTransformer` to identify which methods to instrument. Additionally, you need to include the `sds-client` dependency to access the annotation and exception classes. The "non-intrusive" aspect refers to not needing manual try-catch blocks or explicit client calls, not zero code changes.

### How does the agent handle exceptions during degradation?

The agent injects three distinct exception handling mechanisms. First, if `shouldDowngrade` returns true, it throws `SdsException` immediately, preventing the method body from executing. Second, for business exceptions thrown during execution, the injected catch block captures them and calls `exceptionSign(point, e)` to record error statistics, then re-throws the original exception. Finally, the finally block ensures `downgradeFinally(point)` always executes to update internal counters, regardless of whether degradation occurred or an exception was thrown.

### What JVM versions are supported by the SDS agent?

The SDS Java Agent uses the standard `Instrumentation` API and Javassist for bytecode manipulation, which are compatible with Java 8 and later versions. The `premain` method signature and `ClassFileTransformer` interface have been stable since Java 5, but the specific bytecode manipulation patterns used in `SdsClassFileTransformer` target Java 8+ bytecode structures. For optimal compatibility, use Java 8, 11, 17, or 21 LTS versions, ensuring you match the Javassist version defined in the [`sds-bootstrap/pom.xml`](https://github.com/didi/sds/blob/main/sds-bootstrap/pom.xml) with your target JVM.