diff --git a/CHANGELOG.md b/CHANGELOG.md index 15b6c0871..566f55671 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ - fix: add overflow check in `TimeBounds.expiresAfter()` to prevent integer overflow when timeout is too large. - fix: add validation for `ManageDataOperation` value length to ensure it does not exceed 64 bytes. - fix: use `StandardCharsets.UTF_8` explicitly when converting byte arrays to strings to ensure consistent behavior across different platforms. +- refactor: use static initialization for `GsonSingleton` to ensure thread safety. ## 2.2.1 diff --git a/src/main/java/org/stellar/sdk/responses/gson/GsonSingleton.java b/src/main/java/org/stellar/sdk/responses/gson/GsonSingleton.java index 3e8ecee54..bc9f6ea1f 100644 --- a/src/main/java/org/stellar/sdk/responses/gson/GsonSingleton.java +++ b/src/main/java/org/stellar/sdk/responses/gson/GsonSingleton.java @@ -26,58 +26,54 @@ *

Usually, you shouldn't need to use this class directly. */ public class GsonSingleton { - private static Gson instance = null; + private static final Gson INSTANCE = createInstance(); - protected GsonSingleton() {} + private GsonSingleton() {} public static Gson getInstance() { - if (instance == null) { - TypeToken> accountPageType = new TypeToken>() {}; - TypeToken> assetPageType = new TypeToken>() {}; - TypeToken> effectPageType = new TypeToken>() {}; - TypeToken> ledgerPageType = new TypeToken>() {}; - TypeToken> liquidityPoolPageType = - new TypeToken>() {}; - TypeToken> offerPageType = new TypeToken>() {}; - TypeToken> operationPageType = - new TypeToken>() {}; - TypeToken> pathPageType = new TypeToken>() {}; - TypeToken> tradePageType = new TypeToken>() {}; - TypeToken> tradeAggregationPageType = - new TypeToken>() {}; - TypeToken> transactionPageType = - new TypeToken>() {}; - TypeToken> claimableBalancePageType = - new TypeToken>() {}; + return INSTANCE; + } + + private static Gson createInstance() { + TypeToken> accountPageType = new TypeToken>() {}; + TypeToken> assetPageType = new TypeToken>() {}; + TypeToken> effectPageType = new TypeToken>() {}; + TypeToken> ledgerPageType = new TypeToken>() {}; + TypeToken> liquidityPoolPageType = + new TypeToken>() {}; + TypeToken> offerPageType = new TypeToken>() {}; + TypeToken> operationPageType = + new TypeToken>() {}; + TypeToken> pathPageType = new TypeToken>() {}; + TypeToken> tradePageType = new TypeToken>() {}; + TypeToken> tradeAggregationPageType = + new TypeToken>() {}; + TypeToken> transactionPageType = + new TypeToken>() {}; + TypeToken> claimableBalancePageType = + new TypeToken>() {}; - instance = - new GsonBuilder() - .registerTypeAdapter(Asset.class, new AssetDeserializer()) - .registerTypeAdapter(Predicate.class, new PredicateDeserializer()) - .registerTypeAdapter(OperationResponse.class, new OperationDeserializer()) - .registerTypeAdapter(EffectResponse.class, new EffectDeserializer()) - .registerTypeAdapter( - accountPageType.getType(), new PageDeserializer<>(accountPageType)) - .registerTypeAdapter(assetPageType.getType(), new PageDeserializer<>(assetPageType)) - .registerTypeAdapter(effectPageType.getType(), new PageDeserializer<>(effectPageType)) - .registerTypeAdapter(ledgerPageType.getType(), new PageDeserializer<>(ledgerPageType)) - .registerTypeAdapter( - liquidityPoolPageType.getType(), new PageDeserializer<>(liquidityPoolPageType)) - .registerTypeAdapter(offerPageType.getType(), new PageDeserializer<>(offerPageType)) - .registerTypeAdapter( - operationPageType.getType(), new PageDeserializer<>(operationPageType)) - .registerTypeAdapter(pathPageType.getType(), new PageDeserializer<>(pathPageType)) - .registerTypeAdapter(tradePageType.getType(), new PageDeserializer<>(tradePageType)) - .registerTypeAdapter( - tradeAggregationPageType.getType(), - new PageDeserializer<>(tradeAggregationPageType)) - .registerTypeAdapter( - transactionPageType.getType(), new PageDeserializer<>(transactionPageType)) - .registerTypeAdapter( - claimableBalancePageType.getType(), - new PageDeserializer<>(claimableBalancePageType)) - .create(); - } - return instance; + return new GsonBuilder() + .registerTypeAdapter(Asset.class, new AssetDeserializer()) + .registerTypeAdapter(Predicate.class, new PredicateDeserializer()) + .registerTypeAdapter(OperationResponse.class, new OperationDeserializer()) + .registerTypeAdapter(EffectResponse.class, new EffectDeserializer()) + .registerTypeAdapter(accountPageType.getType(), new PageDeserializer<>(accountPageType)) + .registerTypeAdapter(assetPageType.getType(), new PageDeserializer<>(assetPageType)) + .registerTypeAdapter(effectPageType.getType(), new PageDeserializer<>(effectPageType)) + .registerTypeAdapter(ledgerPageType.getType(), new PageDeserializer<>(ledgerPageType)) + .registerTypeAdapter( + liquidityPoolPageType.getType(), new PageDeserializer<>(liquidityPoolPageType)) + .registerTypeAdapter(offerPageType.getType(), new PageDeserializer<>(offerPageType)) + .registerTypeAdapter(operationPageType.getType(), new PageDeserializer<>(operationPageType)) + .registerTypeAdapter(pathPageType.getType(), new PageDeserializer<>(pathPageType)) + .registerTypeAdapter(tradePageType.getType(), new PageDeserializer<>(tradePageType)) + .registerTypeAdapter( + tradeAggregationPageType.getType(), new PageDeserializer<>(tradeAggregationPageType)) + .registerTypeAdapter( + transactionPageType.getType(), new PageDeserializer<>(transactionPageType)) + .registerTypeAdapter( + claimableBalancePageType.getType(), new PageDeserializer<>(claimableBalancePageType)) + .create(); } }