-
Notifications
You must be signed in to change notification settings - Fork 45
Open
Description
We have identified a memory leak in cybersource-rest-client-java SDK, caused by the way HttpClientFactory caches OkHttpClient instances.
Each time a new ApiClient is created, a new HttpClientFactoryAdditionalSettings is instantiated:
// ApiClient class
.........
private HttpClientFactoryAdditionalSettings additionalSettings = new HttpClientFactoryAdditionalSettings();
.........
public ApiClient() {
.....
additionalSettings.setCustomRetryOnConnectionFailure(true);
additionalSettings.setCustomRetryInterceptor(new RetryInterceptor(this.apiRequestMetrics));
additionalSettings.setCustomNetworkEventListener(new NetworkEventListener(this.getNewRandomId(), System.nanoTime()));
.........This additionalSettings object contributes to the hash generated in GetHashOfMerchantConfiguration:
// HttpClientFactory
private static int GetHashOfMerchantConfiguration(MerchantConfig merchantConfig, HttpClientFactoryAdditionalSettings additionalSettings) {
return Objects.hash(
merchantConfig.getUserDefinedConnectionTimeout(),
merchantConfig.getUserDefinedReadTimeout(),
merchantConfig.getUserDefinedWriteTimeout(),
merchantConfig.getUserDefinedKeepAliveDuration(),
merchantConfig.getUserDefinedMaxIdleConnections(),
additionalSettings.getCustomLoggingInterceptor(),
additionalSettings.getCustomRetryInterceptor(),
additionalSettings.getCustomSSLSocketFactory(),
additionalSettings.getCustomX509TrustManager(),
additionalSettings.getCustomHostnameVerifier(),
additionalSettings.getCustomRetryOnConnectionFailure(),
additionalSettings.getCustomNetworkEventListener(),
additionalSettings.getCustomProxy(),
additionalSettings.getCustomProxyAuthenticator()
);
}-
Because
additionalSettingsis a new object for eachApiClient, the hash is effectively always unique. -
_httpClientInstances.computeIfAbsent(hash, ...)therefore creates a new OkHttpClient every time and stores it in the static map. -
These
OkHttpClientinstances are never garbage collected, leading to memory leak.
Impact:
- Heap usage increases over time.
- Can eventually lead to OutOfMemoryError or exhaustion of file descriptors in long-running applications.
Reproduction steps:
- Create a new
ApiClientinstance:
ApiClient apiClient = new ApiClient();
MerchantConfig merchantConfig = new MerchantConfig(merchantProp);
apiClient.merchantConfig = merchantConfig;
CreatePaymentRequest requestObj = new CreatePaymentRequest();
PaymentsApi apiInstance = new PaymentsApi(apiClient);
result = apiInstance.createPayment(requestObj);- Repeat the multiple times.
- Observe heap growth and accumulation of
OkHttpClientinstances in_httpClientInstances.
References
- SDK version: 0.0.84
Metadata
Metadata
Assignees
Labels
No labels