6

How can I throw an exception for an illegal reflective access warning? For example, consider the following code:

import org.apache.commons.lang3.builder.*;

class Test {
    public static void main(String[] args) {
        System.out.println(ReflectionToStringBuilder.toString(Boolean.TRUE));
    }
}

This code prints the following warning to System.err:

WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.apache.commons.lang3.builder.ReflectionToStringBuilder (file:/Users/brianschack/eclipse-workspace/User%20Libraries/com
mons-lang3-3.7/commons-lang3-3.7.jar) to field java.lang.Boolean.value
WARNING: Please consider reporting this to the maintainers of org.apache.commons.lang3.builder.ReflectionToStringBuilder
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

Boolean.TRUE is such a simple value that I don't really need ReflectionToStringBuilder. But more complex types (such as HashMap) print the same warning. I chose Boolean.TRUE in order to simplify this example.

When I searched for this warning message, I found suggestions to report it to the package maintainer, avoid the warning, or disable it altogether (JDK9: An illegal reflective access operation has occurred. org.python.core.PySystemState).

I would like to throw an exception for the warning in order to get a stack trace of where the illegal access occurred. Then I could change the code to avoid the illegal access that caused the warning. I would also like to make a unit test that would check for the warning in the future.

I tried to test for printing to System.err according to the StackOverflow question, JUnit test for System.out.println(). This involves setting System.err to a ByteArrayOutputStream and then examining the contents. But unfortunately, according to How to hide warning “Illegal reflective access” in java 9 without JVM argument?, the IllegalAccessLogger gets a reference to System.err during JVM bootstrap before I can change it.

I also tried closing System.err, but it seems that printing to a closed stream silently fails instead of throwing an exception. Notice that the output for the following code does not contain the string "err-2":

Code:

class Test {
    public static void main(String[] args) {
        System.out.println("Start");
        System.err.println("err-1");
        System.err.close();
        System.err.println("err-2");
        System.out.println("End");
    }
}

Output:

Start
err-1
End
Brian Schack
  • 300
  • 3
  • 14
  • 1
    I opened an issue in the Apache Commons issue tracker: https://issues.apache.org/jira/browse/LANG-1383 – Brian Schack Mar 02 '18 at 21:25
  • 3
    `--illegal-access=deny` will cause the expected IllegalAccessException or InaccessibleObjectException to be thrown. If you just want the stack traces then `--illegal-access=debug` is what you are looking for. – Alan Bateman Mar 03 '18 at 13:58
  • @AlanBateman Thank you, I will try this command-line argument! – Brian Schack Mar 06 '18 at 17:44

1 Answers1

2
  1. Open the Eclipse development environment.
  2. Choose Run menu –> Run Configurations... –> Java Application –> (your configuration) –> Arguments.
  3. In the VM arguments text box, type "--illegal-access=deny" [0].
  4. Click the Apply button.
  5. Click the Run button.
  6. Illegal access will throw the java.lang.reflect.InaccessibleObjectException [1].

[0] http://mail.openjdk.java.net/pipermail/jigsaw-dev/2017-May/012673.html

[1] http://docs.oracle.com/javase/9/docs/api/java/lang/reflect/InaccessibleObjectException.html

Brian Schack
  • 300
  • 3
  • 14
  • Keep in mind to set all of the other settings when creating a configuration. I'm used to running it straight w/out the config. Looking through the settings I had to set the JRE, directory, Main type, compiler version etc. – Dale Jun 26 '18 at 05:51