Resolving InaccessibleObjectException in Java 17 with OANDA v20 SDK and Gson

While integrating the OANDA v20 SDK into a Spring Boot application for algorithmic trading, I encountered a persistent InaccessibleObjectException when running the application with Java 17. This error stems from Java’s module system restrictions introduced in Java 9 and enhanced in subsequent versions, including Java 17. In this blog post, I’ll walk through the problem, the debugging process, the potential fixes attempted, and ultimately, how downgrading to Java 11 resolved the issue. Additionally, we’ll explore why Java introduced stricter module encapsulation and how it affects reflection-based libraries like Gson.

The Problem

When attempting to retrieve specific order details from the OANDA API using the following endpoint:

curl --location 'http://localhost:8080/accounts/101-004-29672771-001/orders/1234' \
--header 'Content-Type: application/json'

The application threw an exception:

com.google.gson.JsonIOException: Failed making field 'java.lang.Throwable#detailMessage' accessible; either change its visibility or write a custom TypeAdapter for its declaring type
Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make field private java.lang.String java.lang.Throwable.detailMessage accessible: module java.base does not "opens java.lang" to unnamed module

This error indicates that the Gson library, used internally by the OANDA SDK, is unable to access the private detailMessage field of java.lang.Throwable due to Java’s module system restrictions.

Debugging the Issue

Initial Investigation

The error suggested that reflection access to internal Java classes was restricted:

  • Error Source: Gson attempting to access java.lang.Throwable#detailMessage.
  • Cause: Java’s module system preventing reflective access to internal fields.

First Attempt: Adding JVM Arguments

I added JVM arguments to open the necessary modules:

<jvmArguments>--add-opens java.base/java.lang=ALL-UNNAMED</jvmArguments>

Result: This resolved similar issues in the past, but the error persisted in this case.

Second Attempt: Opening Additional Modules

I extended the JVM arguments to include more modules:

<jvmArguments>
    --add-opens java.base/java.lang=ALL-UNNAMED
    --add-opens java.base/java.lang.reflect=ALL-UNNAMED
    --add-opens java.base/java.util=ALL-UNNAMED
</jvmArguments>

Result: The error still occurred, indicating that opening additional modules did not resolve the issue.

Third Attempt: Updating Gson Library

I updated the Gson dependency to the latest version (2.11.0) in pom.xml:

<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.11.0</version>
</dependency>

Result: Still no change—the error persisted.

Fourth Attempt: Excluding Gson from OANDA SDK

I suspected that the OANDA SDK might be using an older version of Gson internally. So, I excluded Gson from the SDK dependency:

<dependency>
    <groupId>com.oanda.v20</groupId>
    <artifactId>v20</artifactId>
    <version>3.0.25</version>
    <exclusions>
        <exclusion>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
        </exclusion>
    </exclusions>
</dependency>

Result: Unfortunately, the error remained.

The Solution: Downgrading to Java 11

After several attempts, I decided to downgrade the application’s Java version from 17 to 11. This involved updating the java.version property in pom.xml:

<properties>
    <java.version>11</java.version>
</properties>

Result: The application ran successfully without any InaccessibleObjectException. The OANDA SDK and Gson library functioned as expected, and the endpoint returned the correct data.

Why Java 17 Introduced Stricter Module Encapsulation

Background on Java’s Module System

  • Introduced in Java 9: The Java Platform Module System (JPMS), also known as Project Jigsaw, was introduced to modularize the JDK and improve security, performance, and maintainability.
  • Strong Encapsulation: JPMS enforces strong encapsulation of internal classes and packages, limiting access to only those explicitly exported.

Implications for Reflection

  • Reflection Restrictions: Reflective access to non-exported types or members is prohibited unless explicitly allowed.
  • IllegalAccessException: Attempting to access restricted members via reflection throws IllegalAccessException or InaccessibleObjectException.

Enhancements in Java 16 and 17

  • Stricter Enforcement: Java 16 and later versions have increased enforcement of encapsulation rules.
  • Warnings to Errors: What used to be warnings in earlier versions are now errors, causing applications relying on reflection to fail.

Impact on Libraries like Gson

  • Gson’s Use of Reflection: Gson heavily relies on reflection to serialize and deserialize objects, including private fields.
  • Conflict with JPMS: When Gson tries to access private fields in internal Java classes (e.g., java.lang.Throwable), it violates the module encapsulation rules.

Lessons Learned

  • Compatibility Matters: Always ensure that third-party libraries and SDKs are compatible with the Java version used in your project.
  • Module System Awareness: Understanding Java’s module system is crucial when dealing with reflection and internal APIs.
  • Downgrading as a Viable Option: Sometimes, using an earlier Java version is the practical solution until libraries catch up with newer Java releases.
  • Community Resources: Checking library documentation and community forums can provide insights into known issues and compatibility notes.

Conclusion

Encountering the InaccessibleObjectException highlighted the challenges that can arise when using libraries that rely on reflection in conjunction with Java’s module system. Downgrading to Java 11 provided a workable solution, allowing the application to function correctly while avoiding the module encapsulation issues present in Java 17.

For developers facing similar issues:

  • Check Library Compatibility: Ensure all dependencies support the Java version you’re using.
  • Consider Java Version: If possible, use a Java version compatible with your libraries.
  • Stay Informed: Keep up-to-date with changes in Java releases and how they might impact your projects.

Further Reading

References

📚 Further Reading & Related Topics

If you’re dealing with Java 17 compatibility issues, reflection, and SDK integration, these related articles will provide deeper insights:

• Java 17’s Enhanced Pseudo-Random Number Generators (PRNG): A Dive into JEP 356 – Explore other key improvements in Java 17, including enhancements to randomness and security features.

• Navigating Algorithmic Trading Strategies: Risk, Reward, and Strategy Duration – If you’re working with OANDA’s v20 SDK, this guide provides a broader understanding of algorithmic trading strategies and risk management.

One response to “Resolving InaccessibleObjectException in Java 17 with OANDA v20 SDK and Gson”

  1. Building a Foundation for Algorithmic Trading with OANDA’s REST API – Scalable Human Blog Avatar

    […] with OANDA’s API, complementing the guide by offering practical tools for implementation. • Resolving InaccessibleObjectException in Java 17 with OANDA V20 SDK and Gson – It addresses common technical issues when integrating OANDA’s V20 SDK in Java environments, […]

    Like

Leave a reply to Building a Foundation for Algorithmic Trading with OANDA’s REST API – Scalable Human Blog Cancel reply

I’m Sean

Welcome to the Scalable Human blog. Just a software engineer writing about algo trading, AI, and books. I learn in public, use AI tools extensively, and share what works. Educational purposes only – not financial advice.

Let’s connect