in aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/AWSLambda.java [199:286]
private static void startRuntime(String handler, LambdaLogger lambdaLogger) throws Throwable {
UnsafeUtil.disableIllegalAccessWarning();
System.setOut(new PrintStream(new LambdaOutputStream(System.out), false, "UTF-8"));
System.setErr(new PrintStream(new LambdaOutputStream(System.err), false, "UTF-8"));
setupRuntimeLogger(lambdaLogger);
String runtimeApi = getEnvOrExit(ReservedRuntimeEnvironmentVariables.AWS_LAMBDA_RUNTIME_API);
LambdaRuntimeClient runtimeClient = new LambdaRuntimeClient(runtimeApi);
EnvReader envReader = new EnvReader();
try (EnvWriter envWriter = new EnvWriter(envReader)) {
envWriter.unsetLambdaInternalEnv();
envWriter.setupEnvironmentCredentials();
envWriter.setupAwsExecutionEnv();
}
String taskRoot = System.getProperty("user.dir");
String libRoot = "/opt/java";
// Make system classloader the customer classloader's parent to ensure any aws-lambda-java-core classes
// are loaded from the system classloader.
customerClassLoader = new CustomerClassLoader(taskRoot, libRoot, ClassLoader.getSystemClassLoader());
Thread.currentThread().setContextClassLoader(customerClassLoader);
// Load the user's handler
UserMethods methods;
try {
methods = findUserMethods(handler, customerClassLoader);
} catch (UserFault userFault) {
lambdaLogger.log(userFault.reportableError());
ByteArrayOutputStream payload = new ByteArrayOutputStream(1024);
Failure failure = new Failure(userFault);
GsonFactory.getInstance().getSerializer(Failure.class).toJson(failure, payload);
runtimeClient.postInitError(payload.toByteArray(), failure.getErrorType());
System.exit(1);
return;
}
// Call the user's init handler(a function called 'init'), if provided in the same module as the request handler.
// This is an undocumented feature, and still exists to keep backward compatibility. Continue if this call fails.
try {
methods.initHandler.run();
} catch (UserFault f) {
lambdaLogger.log(f.reportableError());
}
try (EnvWriter envWriter = new EnvWriter(envReader)) {
boolean shouldExit = false;
while (!shouldExit) {
UserFault userFault = null;
InvocationRequest request = runtimeClient.waitForNextInvocation();
if (request.getXrayTraceId() != null) {
envWriter.modifyEnv(m -> m.put("_X_AMZN_TRACE_ID", request.getXrayTraceId()));
} else {
envWriter.modifyEnv(m -> m.remove("_X_AMZN_TRACE_ID"));
}
ByteArrayOutputStream payload;
try {
payload = methods.requestHandler.call(request);
// TODO calling payload.toByteArray() creates a new copy of the underlying buffer
runtimeClient.postInvocationResponse(request.getId(), payload.toByteArray());
} catch (UserFault f) {
userFault = f;
UserFault.filterStackTrace(f);
payload = new ByteArrayOutputStream(1024);
Failure failure = new Failure(f);
GsonFactory.getInstance().getSerializer(Failure.class).toJson(failure, payload);
shouldExit = f.fatal;
runtimeClient.postInvocationError(request.getId(), payload.toByteArray(), failure.getErrorType());
} catch (Throwable t) {
UserFault.filterStackTrace(t);
userFault = UserFault.makeUserFault(t);
payload = new ByteArrayOutputStream(1024);
Failure failure = new Failure(t);
GsonFactory.getInstance().getSerializer(Failure.class).toJson(failure, payload);
// These two categories of errors are considered fatal.
shouldExit = Failure.isInvokeFailureFatal(t);
runtimeClient.postInvocationError(request.getId(), payload.toByteArray(), failure.getErrorType(),
serializeAsXRayJson(t));
} finally {
if (userFault != null) {
lambdaLogger.log(userFault.reportableError());
}
}
}
}
}