Skip to content

Commit e867523

Browse files
committed
Added GraalVM documentation
1 parent 7bfedb3 commit e867523

File tree

1 file changed

+187
-0
lines changed

1 file changed

+187
-0
lines changed

GraalVM.md

+187
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
# GraalVM Compatibility for AWS Lambda Powertools Java
2+
3+
## Table of Contents
4+
- [Overview](#overview)
5+
- [Prerequisites](#prerequisites)
6+
- [General Implementation Steps](#general-implementation-steps)
7+
- [Known Issues and Solutions](#known-issues-and-solutions)
8+
- [Reference Implementation](#reference-implementation)
9+
- [Module-Specific Implementation](#module-specific-implementation)
10+
- [1. Powertools Common](#1-powertools-common)
11+
- [2. Powertools Logging](#2-powertools-logging)
12+
- [2.1 Powertools Logging (log4j)](#21-powertools-logging-log4j)
13+
- [2.2 Powertools Logging (logback)](#22-powertools-logging-logback)
14+
- [3. Powertools Metrics](#3-powertools-metrics)
15+
16+
## Overview
17+
This documentation provides guidance for adding GraalVM support for AWS Lambda Powertools Java modules and using the modules in Lambda functions.
18+
19+
## Prerequisites
20+
- GraalVM 21+ installation
21+
- Maven 3.x
22+
23+
## General Implementation Steps
24+
GraalVM native image compilation requires complete knowledge of an application's dynamic features at build time. The GraalVM reachability metadata (GRM) JSON files are essential because Java applications often use features that are determined at runtime, such as reflection, dynamic proxy classes, resource loading, and JNI (Java Native Interface). The metadata files tell GraalVM which classes need reflection access, which resources need to be included in the native image, and which proxy classes need to be generated.
25+
26+
In order to generate the metadata reachability files for Powertools for Lambda, follow these general steps.
27+
28+
1. **Add Maven Profiles**
29+
- Add profile for generating GraalVM reachability metadata files. You can find an example of this in profile `generate-graalvm-files` of this [pom.xml](powertools-common/pom.xml).
30+
- Add another profile for running the tests in the native image. You can find and example of this in profile `graalvm-native` of this [pom.xml](powertools-common/pom.xml).
31+
32+
2. **Generate Reachability Metadata**
33+
- Set the `JAVA_HOME` environment variable to use GraalVM
34+
- Run tests with `-Pgenerate-graalvm-files` profile. You can find module specific commands in the [Module-Specific Implementation](#module-specific-implementation) section
35+
- Some tests may need to be skipped depending on the module
36+
37+
3. **Validate Native Image Tests**
38+
- Set the `JAVA_HOME` environment variable to use GraalVM
39+
- Run tests with `-Pgraalvm-native` profile. This will build a GraalVM native image and run the JUnit tests. You can find module specific commands in the [Module-Specific Implementation](#module-specific-implementation) section
40+
- Verify test execution in native mode
41+
42+
4. **Clean Up Metadata**
43+
- GraalVM metadata reachability files generated in Step 2 contains references to the test scoped dependencies as well.
44+
- Remove the references in generated metadata files for the following (and any other references to test scoped resources and classes):
45+
- JUnit
46+
- Mockito
47+
- ByteBuddy
48+
49+
## Known Issues and Solutions
50+
51+
1. **Mockito Compatibility**
52+
- Powertools uses Mockito 5.x which uses “inline mock maker” as the default. This mock maker does not play well with GraalVM. Mockito [recommends](https://github.com/mockito/mockito/releases/tag/v5.0.0) using subclass mock maker with GraalVM.
53+
- However, subclass mock maker does not support testing static methods. Some test cases in Powertools uses inline mock maker to mock static methods. These tests have to be skipped while generating the GraalVM reachability metadata files.
54+
- This obviously affects the coverage and possibility of missing a required entry in GRM files. At this point we are relying on community to report any missing entries and will update the GRM based on the reports.
55+
- This issue remains open until ability of test static methods in Mockito 5.x/inline mock maker is available.
56+
57+
2. **Log4j Compatibility**
58+
- Version 2.22.1 fails with this error
59+
```
60+
java.lang.InternalError: com.oracle.svm.core.jdk.UnsupportedFeatureError: Defining hidden classes at runtime is not supported.
61+
```
62+
- This has been [fixed](https://github.com/apache/logging-log4j2/discussions/2364#discussioncomment-8950077) in Log4j 2.24.0. PT has been updated to use this version of Log4j
63+
64+
65+
## Reference Implementation
66+
Working example is available in the [examples](examples/powertools-examples-core-utilities/sam-graalvm).
67+
68+
## Module-Specific Implementation
69+
70+
### 1. Powertools Common
71+
72+
Generate metadata files
73+
```shell
74+
75+
mvn \
76+
-Dtest=\
77+
\!UserAgentConfiguratorTest#testGetVersionFromProperties_InvalidFile,\
78+
\!UserAgentConfiguratorTest#testGetVersion,\
79+
\!UserAgentConfiguratorTest#testGetUserAgent_SetAWSExecutionEnv,\
80+
\!LambdaHandlerProcessorTest#serviceName_Undefined,\
81+
\!LambdaHandlerProcessorTest#serviceName,\
82+
\!LambdaHandlerProcessorTest#isSamLocal,\
83+
\!LambdaHandlerProcessorTest#getXrayTraceId_present,\
84+
\!LambdaHandlerProcessorTest#getXrayTraceId_notPresent \
85+
-Pgenerate-graalvm-files clean test
86+
```
87+
88+
Run native tests
89+
```shell
90+
91+
mvn \
92+
-Dtest=\
93+
\!UserAgentConfiguratorTest#testGetVersionFromProperties_InvalidFile,\
94+
\!UserAgentConfiguratorTest#testGetVersion,\
95+
\!UserAgentConfiguratorTest#testGetUserAgent_SetAWSExecutionEnv,\
96+
\!LambdaHandlerProcessorTest#serviceName_Undefined,\
97+
\!LambdaHandlerProcessorTest#serviceName,\
98+
\!LambdaHandlerProcessorTest#isSamLocal,\
99+
\!LambdaHandlerProcessorTest#getXrayTraceId_present,\
100+
\!LambdaHandlerProcessorTest#getXrayTraceId_notPresent \
101+
-Pgraalvm-native clean test
102+
103+
```
104+
105+
### 2. Powertools Logging
106+
107+
Generate metadata files
108+
```shell
109+
110+
mvn -Dtest=\!LambdaLoggingAspectTest#shouldLogxRayTraceIdEnvVarSet,\
111+
\!LambdaLoggingAspectTest#shouldLogxRayTraceIdSystemPropertySet \
112+
-Pgenerate-graalvm-files clean test
113+
114+
```
115+
116+
Run native tests
117+
```shell
118+
119+
mvn -Dtest=\!LambdaLoggingAspectTest#shouldLogxRayTraceIdEnvVarSet,\
120+
\!LambdaLoggingAspectTest#shouldLogxRayTraceIdSystemPropertySet \
121+
-Pgraalvm-native clean test
122+
123+
```
124+
#### 2.1 Powertools Logging (log4j)
125+
126+
Generate metadata files
127+
```shell
128+
129+
mvn -Dtest=\!PowertoolsResolverTest#shouldResolveRegion \
130+
-Pgenerate-graalvm-files clean test
131+
132+
```
133+
134+
Run native tests
135+
```shell
136+
137+
mvn -Dtest=\!PowertoolsResolverTest#shouldResolveRegion \
138+
-Pgraalvm-native clean test
139+
140+
```
141+
142+
#### 2.2 Powertools Logging (logback)
143+
144+
Generate metadata files
145+
```shell
146+
147+
mvn -Dtest=\!MetricsLoggerTest#shouldLogxRayTraceIdEnvVarSet,\
148+
\!MetricsLoggerTest#shouldLogxRayTraceIdSystemPropertySet \
149+
-Pgenerate-graalvm-files clean test
150+
151+
```
152+
153+
Run native tests
154+
```shell
155+
156+
mvn -Dtest=\!MetricsLoggerTest#shouldLogxRayTraceIdEnvVarSet,\
157+
\!MetricsLoggerTest#shouldLogxRayTraceIdSystemPropertySet \
158+
-Pgraalvm-native clean test
159+
```
160+
161+
### 3. Powertools Metrics
162+
* All tests need to mock static methods.
163+
* Comment out the references to `mockStatic` in the JUnits and set the env variables explicitly
164+
* Also pass the system property via mvn build cli
165+
166+
Generate metadata files
167+
```shell
168+
169+
export AWS_EMF_ENVIRONMENT="Lambda"
170+
export _X_AMZN_TRACE_ID="Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1"
171+
export POWERTOOLS_METRICS_NAMESPACE="GlobalName"
172+
173+
mvn -Dcom.amazonaws.xray.traceHeader="Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1" \
174+
-Pgenerate-graalvm-files clean test
175+
```
176+
177+
Run native tests
178+
```shell
179+
180+
export AWS_EMF_ENVIRONMENT="Lambda"
181+
export _X_AMZN_TRACE_ID="Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1"
182+
export POWERTOOLS_METRICS_NAMESPACE="GlobalName"
183+
184+
mvn -Dcom.amazonaws.xray.traceHeader="Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1" \
185+
-Pgraalvm-native clean test
186+
187+
```

0 commit comments

Comments
 (0)