Provides solutions to reflective access issues appeared in Java 9
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
src
.gitignore
LICENSE
README.adoc
pom.xml

README.adoc

Java 9 Reflection Utils

Overview

The Reflection API is used to be a powerful Java feature which is able to grant a full access to internals of any Java object at the run time, including access to the private fields and methods. Although such access obviously breaks the encapsulation principle, it is still very helpful and used in a lot of Java frameworks and libraries. For a major part of them, the reflection is irreplaceable.

However, Java 9 brings restrictions over the usage of reflection, when applied to internal parts of JDK and other modules. In practice, you may encounter warnings like this:

WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by X to field Y
WARNING: Please consider reporting this to the maintainers of Z
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release

Or, in worse cases, you may encounter exceptions like this:

java.lang.IllegalAccessException: class X cannot access class Y (in module Z) because module Z does not export X to unnamed module @32e6e9c3

Ideally, these "illegal" accesses shall be changed to something else, but it is not always possible. And that’s exactly why the "Java 9 Reflection Utils" library is created: to solve these issues without removing reflection from your code!

Download

In Maven projects, just add the following dependency:

  <dependency>
    <groupId>com.gilecode.yagson</groupId>
    <artifactId>j9-reflection-utils</artifactId>
    <version>[1.0,)</version>
  </dependency>

Otherwise, download the latest release at GitHub and add j9-reflection-utils-version.jar to the application classpath.

How to use

Making accessible reflective operations in your code

If you have an "illegal" reflective operation in your code, which causes a warning or an exception, all you need is to make a reflection target (Field, Method or Constructor) accessible using the ReflectionAccessor instance provided by the ReflectionAccessUtils factory:

  ReflectionAccessor accessor = ReflectionAccessUtils.getReflectionAccessor();
  Field target = someClass.getDeclaredField("someField");
  // DO NOT USE setAccessible(), replace with makeAccessible()!
  // target.setAccessible(true);
  accessor.makeAccessible(target);

After makeAccessible, the reflective operations on a target, such as a field get/set, a method or constructor invocation, works with no warnings or exceptions, similar to how it was before Java 9.

Suppressing warnings for reflective operations in third-party code

If the reflective operations which causes warnings are located in a third-party library, you usually cannot change them by yourself. However, ReflectionAccessUtils provides a convenient way to suppress the warnings printed for such operations. Just call

  ReflectionAccessUtils.suppressIllegalReflectiveAccessWarnings();

somewhere at your code before the first call to that third-party library, and no warning will be printed.

Note

This call only suppresses warnings! If there is an IllegalAccessException thrown from a third-party library, you may need to use other ways to fix it.

System requirements

The library works on Java 7 or later. When run on Java 7 or Java 8, the implementation of a makeAccessible method just invokes basic setAccessible(true), and the suppressIllegalReflectiveAccessWarnings method just does nothing.

License

Licensed under the Apache License, Version 2.0