

# Java の Lambda 関数ハンドラーの定義
<a name="java-handler"></a>

Lambda 関数*ハンドラー*は、イベントを処理する関数コード内のメソッドです。関数が呼び出されると、Lambda はハンドラーメソッドを実行します。関数は、ハンドラーが応答を返すか、終了するか、タイムアウトするまで実行されます。

このページでは、プロジェクトのセットアップオプション、命名規則、ベストプラクティスなど、Java で Lambda 関数ハンドラーを使用する方法について説明します。このページには、注文に関する情報を取得し、テキストファイル受信を生成し、このファイルを Amazon Simple Storage Service (Amazon S3) バケットに配置する Java Lambda 関数の例も含まれています。関数を書き込んだ後にデプロイする方法については、「[.zip または JAR ファイルアーカイブで Java Lambda 関数をデプロイする](java-package.md)」または「[コンテナイメージを使用した Java Lambda 関数のデプロイ](java-image.md)」を参照してください。

**Topics**
+ [

## Java ハンドラープロジェクトのセットアップ
](#java-handler-setup)
+ [

## Java Lambda 関数のコードの例
](#java-example-code)
+ [

## Java ハンドラーの有効なクラス定義
](#java-handler-signatures)
+ [

## ハンドラーの命名規則
](#java-example-naming)
+ [

## 入力イベントオブジェクトの定義とアクセス
](#java-handler-input)
+ [

## Lambda コンテキストオブジェクトへのアクセスと使用
](#java-example-context)
+ [

## ハンドラーでの AWS SDK for Java v2 の使用
](#java-example-sdk-usage)
+ [

## 環境変数にアクセスする
](#java-example-envvars)
+ [

## グローバルな状態を使用する
](#java-handler-state)
+ [

## Java Lambda 関数のコードのベストプラクティス
](#java-best-practices)

## Java ハンドラープロジェクトのセットアップ
<a name="java-handler-setup"></a>

Java で Lambda 関数を使用する場合、このプロセスにはコードの記述、コンパイル、コンパイルされたアーティファクトの Lambda へのデプロイが含まれます。Java Lambda プロジェクトはさまざまな方法で初期化できます。例えば、[Lambda 関数の Maven Archetype](https://github.com/aws/aws-sdk-java-v2/tree/master/archetypes/archetype-lambda)、AWS SAM CLI [sam init コマンド](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-init.html)、または IntelliJ IDEA や Visual Studio Code といった任意の IDE での標準 Java プロジェクト設定などのツールを使用できます。または、必要なファイル構造を手動で作成することもできます。

一般的な Java Lambda 関数プロジェクトは、次の一般的な構造に従います。

```
/project-root
    └ src
        └ main
            └ java
                └ example
                    └ OrderHandler.java (contains main handler)
                    └ <other_supporting_classes>
     └ build.gradle OR pom.xml
```

Maven または Gradle を使用してプロジェクトを構築し、依存関係を管理できます。

関数のメインハンドラーロジックは、`src/main/java/example` ディレクトリの Java ファイルにあります。このページの例では、このファイルに `OrderHandler.java` という名前を付けます。このファイルとは別に、必要に応じて追加の Java クラスを含めることができます。関数を Lambda にデプロイする際は、呼び出し中に Lambda が呼び出すメインハンドラーメソッドを含む Java クラスを必ず指定してください。

## Java Lambda 関数のコードの例
<a name="java-example-code"></a>

以下の Java 21 Lambda 関数コードの例では、注文に関する情報を取得し、テキストファイル受信を生成し、このファイルを Amazon S3 バケットに配置します。

**Example `OrderHandler.java` Lambda 関数**  

```
package example;

import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
import software.amazon.awssdk.services.s3.model.S3Exception;

import java.nio.charset.StandardCharsets;

/**
 * Lambda handler for processing orders and storing receipts in S3.
 */
public class OrderHandler implements RequestHandler<OrderHandler.Order, String> {

    private static final S3Client S3_CLIENT = S3Client.builder().build();

    /**
     * Record to model the input event.
     */
    public record Order(String orderId, double amount, String item) {}

    @Override
    public String handleRequest(Order event, Context context) {
        try {
            // Access environment variables
            String bucketName = System.getenv("RECEIPT_BUCKET");
            if (bucketName == null || bucketName.isEmpty()) {
                throw new IllegalArgumentException("RECEIPT_BUCKET environment variable is not set");
            }

            // Create the receipt content and key destination
            String receiptContent = String.format("OrderID: %s\nAmount: $%.2f\nItem: %s",
                    event.orderId(), event.amount(), event.item());
            String key = "receipts/" + event.orderId() + ".txt";

            // Upload the receipt to S3
            uploadReceiptToS3(bucketName, key, receiptContent);

            context.getLogger().log("Successfully processed order " + event.orderId() +
                    " and stored receipt in S3 bucket " + bucketName);
            return "Success";

        } catch (Exception e) {
            context.getLogger().log("Failed to process order: " + e.getMessage());
            throw new RuntimeException(e);
        }
    }

    private void uploadReceiptToS3(String bucketName, String key, String receiptContent) {
        try {
            PutObjectRequest putObjectRequest = PutObjectRequest.builder()
                    .bucket(bucketName)
                    .key(key)
                    .build();

            // Convert the receipt content to bytes and upload to S3
            S3_CLIENT.putObject(putObjectRequest, RequestBody.fromBytes(receiptContent.getBytes(StandardCharsets.UTF_8)));
        } catch (S3Exception e) {
            throw new RuntimeException("Failed to upload receipt to S3: " + e.awsErrorDetails().errorMessage(), e);
        }
    }
}
```

この `OrderHandler.java` ファイルには以下のコードのセクションが含まれます:
+ `package example`: Java では、これは任意のものにできますが、プロジェクトのディレクトリ構造と一致する必要があります。ここでは、ディレクトリ構造が `src/main/java/example` であるため、`package example` を使用します。
+ `import` ステートメント: これらを使用して、Lambda 関数に必要な Java クラスをインポートします。
+ `public class OrderHandler ...`: これは Java クラスを定義します。また、[有効なクラス定義](#java-handler-signatures)である必要があります。
+ `private static final S3Client S3_CLIENT ...`: これにより、クラスのメソッドの外部で S3 クライアントが初期化されます。これにより、Lambda は[初期化フェーズ](lambda-runtime-environment.md#runtimes-lifecycle-ib)中にこのコードを実行します。
+ `public record Order ...`: このカスタム Java [レコード](https://openjdk.org/jeps/395)で予想される入力イベントの形状を定義します。
+ `public String handleRequest(Order event, Context context)`: これは**メインハンドラーメソッド**で、メインアプリケーションロジックが含まれています。
+ `private void uploadReceiptToS3(...) {}`: これは、メイン `handleRequest` ハンドラーメソッドによって参照されるヘルパーメソッドです。

### build.gradle および pom.xml ファイルのサンプル
<a name="java-gradle-maven-example"></a>

次の `build.gradle` または `pom.xml` ファイルは、この関数に付随します。

------
#### [ build.gradle ]

```
plugins {
    id 'java'
}

repositories {
    mavenCentral()
}

dependencies {
    implementation 'com.amazonaws:aws-lambda-java-core:1.2.3'
    implementation 'software.amazon.awssdk:s3:2.28.29'
    implementation 'org.slf4j:slf4j-nop:2.0.16'
}

task buildZip(type: Zip) {
    from compileJava
    from processResources
    into('lib') {
        from configurations.runtimeClasspath
    }
}

java {
    sourceCompatibility = JavaVersion.VERSION_21
    targetCompatibility = JavaVersion.VERSION_21
}

build.dependsOn buildZip
```

------
#### [ pom.xml ]

```
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>example-java</artifactId>
    <packaging>jar</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>example-java-function</name>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>21</maven.compiler.source>
        <maven.compiler.target>21</maven.compiler.target>
    </properties>
    <dependencies>
        <dependency>
            <groupId>com.amazonaws</groupId>
            <artifactId>aws-lambda-java-core</artifactId>
            <version>1.2.3</version>
        </dependency>
        <dependency>
            <groupId>software.amazon.awssdk</groupId>
            <artifactId>s3</artifactId>
            <version>2.28.29</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-nop</artifactId>
            <version>2.0.16</version>
        </dependency>
    </dependencies>
    
    <build>
        <plugins>
            <plugin>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>3.5.2</version>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>3.4.1</version>
                <configuration>
                    <createDependencyReducedPom>false</createDependencyReducedPom>
                    <filters>
                        <filter>
                            <artifact>*:*</artifact>
                            <excludes>
                                <exclude>META-INF/*</exclude>
                                <exclude>META-INF/versions/**</exclude>
                            </excludes>
                        </filter>
                    </filters>
                </configuration>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.13.0</version>
                <configuration>
                    <release>21</release>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
```

------

この関数が正しく機能するには、[実行ロール](lambda-intro-execution-role.md)で `s3:PutObject` アクションを許可する必要があります。また、必ず `RECEIPT_BUCKET` 環境変数を定義してください。呼び出しに成功したら、Amazon S3 バケットに受信ファイルが含まれているはずです。

**注記**  
この関数がタイムアウトすることなく正常に実行されるには、追加の構成設定が必要になる場合があります。メモリを 256 MB、タイムアウトを 10 秒に設定することをお勧めします。[コールドスタート](lambda-runtime-environment.md#cold-start-latency)により、最初の呼び出しにさらに時間がかかる場合があります。実行環境が再利用されるため、それ以降の呼び出しはより高速に実行されます。

## Java ハンドラーの有効なクラス定義
<a name="java-handler-signatures"></a>

クラスを定義するために、[aws-lambda-java-core](https://github.com/aws/aws-lambda-java-libs/tree/master/aws-lambda-java-core) ライブラリは、ハンドラーメソッドの 2 つのインターフェイスを定義します。用意されているインターフェイスを使用して、ハンドラー設定をシンプルにし、コンパイル時にメソッドシグネチャを検証します。
+ [com.amazonaws.services.lambda.runtime.RequestHandler](https://github.com/aws/aws-lambda-java-libs/blob/master/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/RequestHandler.java)
+ [com.amazonaws.services.lambda.runtime.RequestStreamHandler](https://github.com/aws/aws-lambda-java-libs/blob/master/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/RequestStreamHandler.java)

`RequestHandler` インターフェイスは、入力タイプと出力タイプの 2 つのパラメータを受け取る汎用タイプです。どちらのタイプもオブジェクトであることが必要です。この例では、`OrderHandler` クラスは `RequestHandler<OrderHandler.Order, String>` を実装します。入力タイプはクラス内で定義する `Order` レコードで、出力タイプは `String` です。

```
public class OrderHandler implements RequestHandler<OrderHandler.Order, String> {
    ...
}
```

このインターフェイスを使用すると、Java ランタイムはイベントを入力タイプのオブジェクトに逆シリアル化し、出力をテキストにシリアル化します。組み込みのシリアル化が入力タイプと出力タイプで機能する場合は、このインターフェイスを使用します。

独自のシリアル化を使用するために、`RequestStreamHandler` インターフェイスを実装できます。このインターフェイスでは、Lambda はハンドラーに入力ストリームと出力ストリームを渡します。ハンドラーは、入力ストリームからバイトを読み取り、出力ストリームに書き込み、void を返します。Java 21 ランタイムを使用したこの例については、「[HandlerStream.java](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/java-basic/src/main/java/example/HandlerStream.java)」を参照してください。

Java 関数で基本型と汎用型 (`String`、`Integer`、`List` または `Map`) のみを使用している場合は、インターフェイスを実装する必要はありません。例えば、関数が `Map<String, String>` 入力を受け取り、`String` を返す場合、クラス定義とハンドラー署名は次のようになります。

```
public class ExampleHandler {
    public String handleRequest(Map<String, String> input, Context context) {
        ...
    }
}
```

さらに、インターフェイスを実装しない場合、[コンテキスト](java-context.md)オブジェクトはオプションです。例えば、クラス定義とハンドラー署名は次のようになります。

```
public class NoContextHandler {
   public String handleRequest(Map<String, String> input) {
        ...
   }
}
```

## ハンドラーの命名規則
<a name="java-example-naming"></a>

Java の Lambda 関数では、`RequestHandler` または `RequestStreamHandler` インターフェイスを実装する場合、メインハンドラーメソッドの名前は `handleRequest` である必要があります。また、`handleRequest` メソッドの上に `@Override` タグを含めます。関数を Lambda にデプロイするときは、関数の設定でメインハンドラーを次の形式で指定します。
+ *<package>*.*<Class>* – 例: `example.OrderHandler`。

`RequestHandler` または `RequestStreamHandler` インターフェイスを実装しない Java の Lambda 関数の場合、ハンドラーには任意の名前を使用できます。関数を Lambda にデプロイするときは、関数の設定でメインハンドラーを次の形式で指定します。
+ *<package>*.*<Class>*::*<handler\$1method\$1name>* – 例: `example.Handler::mainHandler`。

## 入力イベントオブジェクトの定義とアクセス
<a name="java-handler-input"></a>

JSON は Lambda 関数の最も一般的な標準入力形式です。この例では、関数は以下のような入力を想定しています:

```
{
    "orderId": "12345",
    "amount": 199.99,
    "item": "Wireless Headphones"
}
```

Java 17 以降で Lambda 関数を使用する場合、予想される入力イベントの形状を Java レコードとして定義できます。この例では、`Order` オブジェクトを表すレコードを `OrderHandler` クラス内で定義します。

```
public record Order(String orderId, double amount, String item) {}
```

このレコードは、予想される入力形状と一致します。レコードを定義したら、レコード定義に準拠する JSON 入力を取り込むハンドラー署名を記述できます。Java ランタイムは、この JSON を Java オブジェクトに自動的に逆シリアル化します。その後、オブジェクトのフィールドにアクセスできます。例えば、`event.orderId` は元の入力から `orderId` の値を取得します。

**注記**  
Java レコードは、Java 17 ランタイム以降の機能です。すべての Java ランタイムで、クラスを使用してイベントデータを表すことができます。このような場合は、[jackson](https://github.com/FasterXML/jackson) などのライブラリを使用して JSON 入力を逆シリアル化できます。

### その他の入力イベントタイプ
<a name="java-input-event-types"></a>

Java の Lambda 関数には、多くの入力イベントが考えられます。
+ `Integer``Long` 、`Double`、など － イベントは、追加の形式のない数値です (`3.5` など)。Java ランタイムは、値を指定されたタイプのオブジェクトに変換します。
+ `String` － イベントは、引用符を含む JSON 文字列です ( など)`“My string”`。ランタイムは、値を引用符なしの `String` オブジェクトに変換します。
+ `List<Integer>``List<String>` 、`List<Object>`、など － イベントは JSON 配列です。ランタイムは、それを指定されたタイプまたはインターフェイスのオブジェクトに逆シリアル化します。
+ `InputStream` － イベントは任意の JSON タイプです。ランタイムは、ドキュメントのバイトストリームを変更せずにハンドラーに渡します。入力を逆シリアル化し、出力を出力ストリームに書き込みます。
+ ライブラリタイプ － 他の AWS サービスによって送信されるイベントの場合、[aws-lambda-java-events](https://github.com/aws/aws-lambda-java-libs/tree/main/aws-lambda-java-events) ライブラリのタイプを使用します。例えば、Lambda 関数が Amazon Simple Queue Service (SQS) によって呼び出された場合、`SQSEvent` オブジェクトを入力として使用します。

## Lambda コンテキストオブジェクトへのアクセスと使用
<a name="java-example-context"></a>

Lambda [コンテキストオブジェクト](java-context.md)には、呼び出し、関数、および実行環境に関する情報が含まれます。この例では、コンテキストオブジェクトは `com.amazonaws.services.lambda.runtime.Context` 型で、メインハンドラー関数の 2 番目の引数です。

```
public String handleRequest(Order event, Context context) {
    ...
}
```

クラスで [RequestHandler](https://github.com/aws/aws-lambda-java-libs/blob/master/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/RequestHandler.java) インターフェイスまたは [RequestStreamHandler](https://github.com/aws/aws-lambda-java-libs/blob/master/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/RequestStreamHandler.java) インターフェイスを実装する場合、コンテキストオブジェクトは必須引数です。それ以外の場合、コンテキストオブジェクトはオプションです。有効な受理されたハンドラー署名の詳細については、「[Java ハンドラーの有効なクラス定義](#java-handler-signatures)」を参照してください。

AWS SDK を使用して他のサービスを呼び出す場合、コンテキストオブジェクトはいくつかの重要な領域で必要です。例えば、Amazon CloudWatch の関数ログを生成するには、`context.getLogger()` メソッドを使用してログ記録用の `LambdaLogger` オブジェクトを取得できます。この例では、何らかの理由で処理が失敗した場合、ロガーを使用してエラーメッセージをログに記録できます。

```
context.getLogger().log("Failed to process order: " + e.getMessage());
```

ログ記録以外では、関数のモニタリングにコンテキストオブジェクトを使用することもできます。コンテキストオブジェクトの詳細については、「[Lambda コンテキストオブジェクトを使用して Java 関数の情報を取得する](java-context.md)」を参照してください。

## ハンドラーでの AWS SDK for Java v2 の使用
<a name="java-example-sdk-usage"></a>

多くの場合、Lambda 関数を使用して、他の AWS リソースとやり取りしたり、更新したりします。これらのリソースとインターフェイスする最も簡単な方法は、AWS SDK for Java v2 を使用することです。

**注記**  
AWS SDK for Java (v1) はメンテナンスモードであり、2025 年 12 月 31 日にサポートが終了する予定です。今後は AWS SDK for Java v2 のみを使用することをお勧めします。

SDK 依存関係を関数に追加するには、Gradle の場合は `build.gradle` に、Maven の場合は `pom.xml` ファイルに追加します。関数に必要なライブラリのみを追加することをお勧めします。前のコード例では、`software.amazon.awssdk.services.s3` ライブラリを使用しました。Gradle では、`build.gradle` の依存関係セクションに次の行を追加することで、この依存関係を追加できます。

```
implementation 'software.amazon.awssdk:s3:2.28.29'
```

Maven で、`pom.xml` の `<dependencies>` セクションに次の行を追加します。

```
    <dependency>
        <groupId>software.amazon.awssdk</groupId>
        <artifactId>s3</artifactId>
        <version>2.28.29</version>
    </dependency>
```

**注記**  
これは SDK の最新バージョンではない場合があります。アプリケーションに適したバージョンの SDK を選択します。

次に、依存関係を Java クラスに直接インポートします。

```
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
import software.amazon.awssdk.services.s3.model.S3Exception;
```

次に、コード例は次のように Amazon S3 クライアントを初期化します。

```
private static final S3Client S3_CLIENT = S3Client.builder().build();
```

この例では、関数を呼び出すたびに Amazon S3 クライアントを初期化する必要がないように、メインハンドラー関数の外で Amazon S3 クライアントを初期化しました。SDK クライアントを初期化したら、SDK クライアントを使用して他の AWS サービスとやり取りできます。サンプルコードは、以下のように Amazon S3 `PutObject` API を呼び出します。

```
PutObjectRequest putObjectRequest = PutObjectRequest.builder()
    .bucket(bucketName)
    .key(key)
    .build();

// Convert the receipt content to bytes and upload to S3
S3_CLIENT.putObject(putObjectRequest, RequestBody.fromBytes(receiptContent.getBytes(StandardCharsets.UTF_8)));
```

## 環境変数にアクセスする
<a name="java-example-envvars"></a>

ハンドラーコードでは、`System.getenv()` メソッドを使用して任意の[環境変数](configuration-envvars.md)を参照できます。この例では、以下のコード行を使用して、定義された `RECEIPT_BUCKET` 環境変数を参照します:

```
String bucketName = System.getenv("RECEIPT_BUCKET");
if (bucketName == null || bucketName.isEmpty()) {
    throw new IllegalArgumentException("RECEIPT_BUCKET environment variable is not set");
}
```

## グローバルな状態を使用する
<a name="java-handler-state"></a>

Lambda は、関数を初めて呼び出す前の[初期化フェーズ](lambda-runtime-environment.md#runtimes-lifecycle-ib)で静的コードとクラスコンストラクターを実行します。初期化中に作成されたリソースは呼び出し間でメモリに保持されるため、関数を呼び出すたびにリソースを作成する必要がなくなります。

コード例では、S3 クライアント初期化コードはメインハンドラーメソッドの外にあります。ランタイムは、関数が最初のイベントを処理する前にクライアントを初期化し、クライアントはすべての呼び出しで再利用できます。

## Java Lambda 関数のコードのベストプラクティス
<a name="java-best-practices"></a>

Lambda 関数をビルドするときは、次のリストのガイドラインに従って、コーディングのベストプラクティスを実行してください。
+ **Lambda ハンドラーをコアロジックから分離します。**これにより、関数の単体テストが実行しやすくなります。
+ **関数のデプロイパッケージ内で依存関係を制御します。**AWS Lambda 実行環境には多数のライブラリが含まれています。最新の機能やセキュリティ更新プログラムを有効にするために、Lambda はこれらのライブラリを定期的に更新します。この更新により、Lambda 関数の動作が微妙に変化する場合があります。関数で使用する依存関係を完全に制御するには、すべての依存関係をデプロイパッケージでパッケージングします。
+ **依存関係の複雑さを最小限に抑えます。**フレームワークを単純化して、[実行環境](lambda-runtime-environment.md)起動時のロードを高速化します。たとえば、[Spring Framework](https://github.com/spring-projects/spring-framework) などの複雑なフレームワークよりも、[Dagger](https://google.github.io/dagger/) や [Guice](https://github.com/google/guice) などの単純な Java 依存関係インジェクション (IoC) フレームワークを使用します。
+ **デプロイパッケージをランタイムに必要な最小限のサイズにします。**これにより、呼び出しに先立ってデプロイパッケージをダウンロードして解凍する所要時間が短縮されます。Java で記述された関数の場合は、デプロイパッケージの一部として AWS SDK ライブラリ全体をアップロードしないようにしてください。代わりに、SDK のコンポーネントを必要に応じて選別するモジュール (DynamoDB、Amazon S3 SDK モジュール、[Lambda コアライブラリ](https://github.com/aws/aws-lambda-java-libs)など) を使用します。

**実行環境の再利用を活用して関数のパフォーマンスを向上させます。**関数ハンドラー外で SDK クライアントとデータベース接続を初期化し、静的なアセットを `/tmp` ディレクトリにローカルにキャッシュします。関数の同じインスタンスで処理された後続の呼び出しは、これらのリソースを再利用できます。これにより、関数の実行時間が短縮され、コストが節約されます。

呼び出し間でデータが漏れるのを防ぐため、実行環境を使用してセキュリティ上の懸念があるユーザーデータ、イベント、またはその他の情報を保存しないでください。関数がハンドラー内のメモリに保存できない変更可能な状態に依存している場合は、ユーザーごとに個別の関数または個別のバージョンの関数を作成することを検討してください。

**keep-alive ディレクティブを使用して永続的な接続を維持します。**Lambda は、時間の経過とともにアイドル状態の接続を消去します。関数を呼び出すときにアイドル状態の接続を再利用しようとすると、接続エラーが発生します。永続的な接続を維持するには、ランタイムに関連付けられている keep-alive ディレクティブを使用します。例については、「[Node.js で Keep-alive を使用して接続を再利用する](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/node-reusing-connections.html)」を参照してください。

**[環境変数](configuration-envvars.md)を使用して、オペレーショナルパラメータを関数に渡します。**たとえば、Amazon S3 バケットに書き込む場合、書き込み先のバケット名はハードコーディングせずに、環境変数として設定します。

Lambda 関数では、**再帰呼び出しを使用しないでください**。関数が自身を呼び出すこともあれば、新たに開始されたプロセスで関数が再度呼び出される可能性もあります。これを行うと意図しないボリュームで関数が呼び出され、料金が急増する可能性があります。意図しない呼び出しがいくつも見つかった場合は、すぐに関数の予約済同時実行数を `0` に設定して、コードを更新している間のすべての関数の呼び出しをスロットリングします。

Lambda 関数コードで**文書化されていない非公開の API を使用しないでください**。AWS Lambda マネージドランタイムでは、Lambda が Lambda の内部 API にセキュリティと機能面の更新を定期的に適用します。これらの内部 API 更新には後方互換性がないことがあり、関数にこれらの非公開 API に対する依存関係がある場合、呼び出しの失敗などの意図しない結果につながります。公開されている API のリストについては、「[API リファレンス](https://docs.aws.amazon.com/lambda/latest/api/welcome.html)」を参照してください。

**冪等性コードを記述します。**関数の記述に冪等性コードを使用すると、重複するイベントが同じ方法で処理されるようになります。コードでは、イベントを適切に検証し、重複するイベントを適切に処理する必要があります。詳細については、「[Lambda 関数を冪等にするにはどうすればよいですか?](https://aws.amazon.com/premiumsupport/knowledge-center/lambda-function-idempotent/)」を参照してください。
+ **Java DNS キャッシュを使用しない** Lambda 関数は、既に DNS レスポンスをキャッシュしています。別の DNS キャッシュを使用すると、接続タイムアウトが発生する可能性があります。

  `java.util.logging.Logger` クラスは JVM DNS キャッシュを間接的に有効にできます。デフォルト設定を上書きするには、 を初期化する前に [networkaddress.cache.ttl](https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/net/InetAddress.html#inetaddress-caching-heading) を 0 に設定します`logger`。例:

  ```
  public class MyHandler {
    // first set TTL property
    static{
     java.security.Security.setProperty("networkaddress.cache.ttl" , "0");
    }
   // then instantiate logger
    var logger = org.apache.logging.log4j.LogManager.getLogger(MyHandler.class);
  }
  ```
+ Java で記述された**デプロイパッケージを Lambda で解凍する所要時間を短縮します**。そのために、依存する `.jar` ファイルを別個の /lib ディレクトリにファイルします。これで関数のすべてのコードを多数の `.class` ファイルと一緒に単一の Jar に収納するよりも高速化されます。手順については、「[.zip または JAR ファイルアーカイブで Java Lambda 関数をデプロイする](java-package.md)」を参照してください。