

# Hooks de runtime do Lambda SnapStart para Java
<a name="snapstart-runtime-hooks-java"></a>

É possível usar hooks de runtime para implementar o código antes que o Lambda crie um snapshot ou depois que o Lambda retorna uma função de um snapshot. Os hooks de runtime estão disponíveis como parte do projeto de código aberto Coordinated Restore at Checkpoint (CRaC). O CRaC está em desenvolvimento para o [Open Java Development Kit (OpenJDK)](https://wiki.openjdk.org/display/crac). Para obter um exemplo de como usar o CRaC com uma aplicação de referência, consulte o repositório [CRaC](https://github.com/CRaC/docs/blob/master/STEP-BY-STEP.md) no GitHub. O CRaC usa três elementos principais:
+ `Resource`: uma interface com dois métodos, `beforeCheckpoint()` e `afterRestore()`. Use esses métodos para implementar o código deseja executar antes de um snapshot e depois de uma restauração.
+ `Context <R extends Resource>`: para receber notificações de pontos de verificação e restaurações, `Resource` deve estar registrado em um `Context`.
+ `Core`: o serviço de coordenação, que fornece o padrão global `Context` por meio do método estático `Core.getGlobalContext()`.

Para obter mais informações sobre `Context` e `Resource`, consulte [Package org.crac](https://javadoc.io/doc/io.github.crac/org-crac/latest/index.html) (Pacote org.crac) na documentação do CRaC.

Use as etapas a seguir para implementar os hooks de runtime com o [pacote org.crac](https://github.com/CRaC/org.crac). O runtime do Lambda contém uma implementação de contexto CRaC personalizada que chama os hooks de runtime antes do ponto de verificação e depois da restauração.

## Registro e execução do hook de runtime
<a name="runtime-hooks-registration-java"></a>

A ordem em que o Lambda executa seus hooks de runtime é determinada pela ordem de registro. A ordem de registro segue a ordem de importação, definição ou execução em seu código.
+ `beforeCheckpoint()`: executado na ordem inversa do registro
+ `afterRestore()`: executado na ordem de registro

Certifique-se de que todos os hooks registrados sejam importados e incluídos corretamente no código da sua função. Se você registrar hooks de runtime em um arquivo ou módulo separado, o módulo deverá ser importado, seja diretamente ou como parte de um pacote maior, no arquivo do manipulador da sua função. Se o arquivo ou módulo não for importado no manipulador da função, o Lambda vai ignorar os hooks de runtime.

**nota**  
Quando o Lambda cria um snapshot, o código de inicialização pode ser executado por até 15 minutos. O limite de tempo é de 130 segundos ou o [tempo limite da função configurada](configuration-timeout.md) (máximo de 900 segundos), o que for maior. Seus hooks de runtime de `beforeCheckpoint()` contam até o limite de tempo do código de inicialização. Quando o Lambda restaura um snapshot, o runtime deve ser carregado e os hooks de runtime `afterRestore()` devem ser concluídos dentro do limite de tempo limite (dez segundos). Caso contrário, você obterá uma SnapStartTimeoutException.

## Etapa 1: atualizar a configuração de compilação
<a name="runtime-hooks-java-update-build"></a>

Adicione a dependência `org.crac` à configuração de compilação. O exemplo a seguir usa o Gradle. Para obter exemplos de outros sistemas de compilação, consulte a [documentação do Apache Maven](https://search.maven.org/artifact/io.github.crac/org-crac/0.1.3/jar).

```
dependencies {
    compile group: 'com.amazonaws', name: 'aws-lambda-java-core', version: '1.2.1'
    # All other project dependecies go here:
    # ...
    # Then, add the org.crac dependency:
 implementation group: 'org.crac', name: 'crac', version: '1.4.0'
}
```

## Etapa 2: atualizar o manipulador do Lambda
<a name="runtime-hooks-java-update-handler"></a>

O *manipulador* da função do Lambda é o método no código da função que processa eventos. Quando sua função é invocada, o Lambda executa o método do manipulador. A função é executada até que o manipulador retorne uma resposta, seja encerrado ou atinja o tempo limite.

Para obter mais informações, consulte [Definir o manipulador da função do Lambda em Java](java-handler.md).

O manipulador exemplificado a seguir mostra como executar o código antes do ponto de verificação (`beforeCheckpoint()`) e depois da restauração (`afterRestore()`). Esse manipulador também registra o `Resource` no `Context` global gerenciado pelo runtime.

**nota**  
Quando o Lambda cria um snapshot, o código de inicialização pode ser executado por até 15 minutos. O limite de tempo é de 130 segundos ou o [tempo limite da função configurada](configuration-timeout.md) (máximo de 900 segundos), o que for maior. Seus hooks de runtime de `beforeCheckpoint()` contam até o limite de tempo do código de inicialização. Quando o Lambda restaura um snapshot, o runtime (JVM) deve ser carregado e os hooks de runtime `afterRestore()` devem ser concluídos dentro do limite de tempo-limite (dez segundos). Caso contrário, você obterá uma SnapStartTimeoutException.

```
...
  import org.crac.Resource;
  import org.crac.Core;
  ... 
public class CRaCDemo implements RequestStreamHandler, Resource {
    public CRaCDemo() {
      Core.getGlobalContext().register(this);
    }
    public String handleRequest(String name, Context context) throws IOException {
      System.out.println("Handler execution");
      return "Hello " + name;
    }
    @Override
    public void beforeCheckpoint(org.crac.Context<? extends Resource> context)
        throws Exception {
      System.out.println("Before checkpoint");
    }
    @Override
    public void afterRestore(org.crac.Context<? extends Resource> context)
        throws Exception {
      System.out.println("After restore");
```

`Context` mantém somente uma [https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/ref/WeakReference.html](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/ref/WeakReference.html) para o objeto registrado. Se um [https://javadoc.io/static/io.github.crac/org-crac/0.1.3/org/crac/Resource.html](https://javadoc.io/static/io.github.crac/org-crac/0.1.3/org/crac/Resource.html) estiver na coleta de resíduos, os hooks de runtime não serão executados. O código deve manter uma referência forte para o `Resource` com a finalidade de garantir que o hook de runtime seja executado.

Veja a seguir dois exemplos de padrões a serem evitados:

**Example : objeto sem uma referência forte**  

```
Core.getGlobalContext().register( new MyResource() );
```

**Example : objetos de classes anônimas**  

```
Core.getGlobalContext().register( new Resource() {
   
   @Override
   public void afterRestore(Context<? extends Resource> context) throws Exception {
    // ...
   }
   
   @Override
   public void beforeCheckpoint(Context<? extends Resource> context) throws Exception {
    // ...
   }

} );
```

Em vez disso, mantenha uma referência forte. No exemplo a seguir, o recurso registrado não está na coleta de resíduos e os hooks de runtime são executados de forma consistente.

**Example : objeto com uma referência forte**  

```
Resource myResource = new MyResource(); // This reference must be maintained to prevent the registered resource from being garbage collected
Core.getGlobalContext().register( myResource );
```