

# 定义采用 Java 的 Lambda 函数处理程序
<a name="java-handler"></a>

Lambda 函数*处理程序*是函数代码中处理事件的方法。当调用函数时，Lambda 运行处理程序方法。您的函数会一直运行，直到处理程序返回响应、退出或超时。

本页介绍如何使用 Java Lambda 函数处理程序，包括项目设置选项、命名约定和最佳实践。本页还包括 Java Lambda 函数的示例，在示例中该函数接收订单信息，生成文本文件收据，然后将此文件放入 Amazon Simple Storage Service（Amazon S3）存储桶中。有关如何在编写函数后部署函数的信息，请参阅[使用 .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)，甚至可以在您首选的 IDE（如 IntelliJ IDEA 或 Visual Studio Code）中使用标准 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 中，此部分可以是任何内容，但必须与项目的目录结构相匹配。在这里，我们之所以使用 `package example`，是因为目录结构是 `src/main/java/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) 库为处理程序方法定义了两个接口。使用提供的接口简化处理程序配置，并在编译时验证方法签名。
+ [ 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` 接口是一个泛型类型，它采用两个参数：输入类型和输出类型。这两种类型都必须是对象。在此示例中，我们的 `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 记录。在此示例中，我们在 `OrderHandler` 类中定义了一条记录来表示 `Order` 对象：

```
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) 库中的类型。例如，如果 Amazon Simple Queue Service（SQS）调用了您的 Lambda 函数，则使用 `SQSEvent` 对象作为输入。

## 访问和使用 Lambda 上下文对象
<a name="java-example-context"></a>

Lambda [上下文对象](java-context.md)包含有关调用、函数和执行环境的信息。在此示例中，上下文对象的类型为 `com.amazonaws.services.lambda.runtime.Context`，是主处理程序函数的第二个参数。

```
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 依赖项，请将其添加到 `build.gradle`（Gradle）或 `pom.xml` 文件（Maven）。建议仅添加函数所需的库。在上述示例代码中，我们使用了 `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 客户端，以免每次调用函数时都必须对其进行初始化。初始化 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)启动时可以快速加载的更简单的框架。例如，首选更简单的 Java 依赖关系注入 (IoC) 框架，如 [Dagger](https://google.github.io/dagger/) 或 [Guice](https://github.com/google/guice)，而不是更复杂的 [Spring Framework](https://github.com/spring-projects/spring-framework)。
+ **将部署包大小精简为只包含运行时必要的部分。**这样会减少调用前下载和解压缩部署程序包所需的时间。对于用 Java 编写的函数，请勿将整个 AWS SDK 库作为部署包的一部分上传，而是要根据所需的模块有选择地挑选软件开发工具包中的组件（例如 DynamoDB、Simple Storage Service (Amazon S3) 软件开发工具包模块和 [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 参考](https://docs.aws.amazon.com/lambda/latest/api/welcome.html)以查看公开发布的 API 列表。

**编写幂等代码。**为您的函数编写幂等代码可确保以相同的方式处理重复事件。您的代码应该正确验证事件并优雅地处理重复事件。有关更多信息，请参阅[如何使我的 Lambda 函数具有幂等性？](https://aws.amazon.com/premiumsupport/knowledge-center/lambda-function-idempotent/)。
+ **避免使用 Java DNS 缓存。**Lambda 函数已经缓存了 DNS 响应。如果您使用了另一个 DNS 缓存，则可能会出现连接超时。

  `java.util.logging.Logger` 类可以间接启用 JVM DNS 缓存。要覆盖默认设置，请在初始化 `logger` 之前将 [networkaddress.cache.ttl](https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/net/InetAddress.html#inetaddress-caching-heading) 设置为 0。示例：

  ```
  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);
  }
  ```
+ 将依赖关系 `.jar` 文件置于单独的 /lib 目录中，可**减少 Lambda 解压缩部署程序包**（用 Java 编写）所需的时间。这样比将函数的所有代码置于具有大量 `.class` 文件的同一 jar 中要快。有关说明，请参阅[使用 .zip 或 JAR 文件归档部署 Java Lambda 函数](java-package.md)：