Keywords: Java 9 | Illegal Reflective Access | Module System
Abstract: This article provides an in-depth exploration of illegal reflective access in Java 9's module system, detailing its definition, triggering conditions, and warning mechanisms. By analyzing the interaction between module encapsulation principles and reflection APIs, along with configuration of the --illegal-access runtime option, it offers a complete solution from detection to resolution, supplemented with practical case studies to help developers fully understand and address this critical change introduced in Java 9.
Introduction
With the introduction of the module system in Java 9, strong encapsulation has become a cornerstone of platform security. However, during the migration of existing applications, developers often encounter warnings about "illegal reflective access," which directly relates to the redefined access permissions between modules. Based on the design philosophy of the Java Platform Module System (JPMS), this article systematically explains the nature, triggering scenarios, and countermeasures for illegal reflective access.
Definition and Core Principles of Illegal Reflective Access
Illegal reflective access refers to operations via reflection APIs that violate module encapsulation rules in Java 9 and later versions. Specifically, when code attempts to access members in packages that are not exported or opened, it constitutes illegal access. The module system uses module descriptors (module-info.java) to explicitly declare exported and opened packages; by default, undeclared packages are invisible to external modules, including via reflection.
For example, if module A does not export the package com.example.internal, and module B uses reflection to invoke setAccessible(true) to access a private field in that package, illegal access is triggered. This mechanism strengthens encapsulation, preventing unauthorized code from intruding into internal implementations.
Specific Triggering Scenarios and Runtime Behavior
Detection and warnings for illegal reflective access are performed by the JVM at runtime. Key triggering conditions include:
- Cross-module reflective access to unopened packages: For instance, module C reflectively accessing non-public members in an unopened package of module D.
- Use of internal JDK APIs: Application code using reflection to call internal JDK APIs, such as classes in the
sun.miscpackage.
To facilitate smooth migration, Java 9 introduced the --illegal-access launch option, with a default value of permit. In this mode, the first illegal access issues a warning, and subsequent operations are logged but do not repeat the warning. The warning format is as follows:
WARNING: Illegal reflective access by $PERPETRATOR to $VICTIMHere, $PERPETRATOR is the class invoking reflection and its code source, and $VICTIM describes the accessed member. For example, the Talend component case in the reference article, which accessed the java.net.URL.factory field, triggered a warning due to cross-module access to an unopened API.
Interaction Mechanism Between Module System and Reflection Permissions
Java 9 imposes module-aware restrictions on the AccessibleObject.setAccessible method. A successful call requires meeting any of the following conditions:
- The calling class and the accessed class are in the same module.
- The accessed member is public, and its class's package is exported to the calling module.
- The accessed member is protected static, its class's package is exported to the calling module, and the calling class is a subclass of it.
- The accessed class's package is opened (opens) to the calling module.
This mechanism ensures that reflection operations align with module declarations, with any undeclared access deemed illegal.
Practical Guide to Detecting and Resolving Illegal Reflective Access
To eliminate warnings and ensure future compatibility, the following steps are recommended:
- Use
--illegal-access=denymode for detection: Add this parameter at runtime to force failures on illegal access, precisely identifying problem points. - Analyze dependencies with the jdeps tool: Run
jdeps --jdk-internalsto scan the application, identify static dependencies on JDK internal APIs, and replace them with standard APIs. - Correct module declarations: Add
opensdirectives in module descriptors to open necessary packages to specific modules, or use the--add-openslaunch parameter for temporary opening. - Migrate to standard APIs: As shown in the Talend case from the reference article, update library versions that depend on internal APIs or switch to Oracle JDK to avoid implementation-specific issues.
For instance, addressing the Talend warning could involve upgrading component libraries or adjusting module configurations to eliminate illegal access to java.net.URL.factory.
Conclusion and Outlook
The illegal reflective access mechanism is a key security feature in Java's modularization journey, enforcing explicit module boundaries for developers. By understanding its principles and adopting systematic detection methods, applications can achieve enhanced robustness and future compatibility. As the module system matures, related toolchains will continue to optimize, supporting developers in a smooth transition to a fully encapsulated Java ecosystem.