Even if your programs do not use modules, you cannot escape the modular world when using Java 9 and beyond. Even if the application code resides on the class path in an unnamed module and all packages are exported and opened, it interacts with the Java platform, which is modularized.
Up to Java 11, the default behavior is to permit illegal module access but to display a warning on the console for the first instance of each offense. In a future version of Java, the default behavior will change, and illegal access with be denied. In order to give you time to prepare for that change, you should test your applications with the –illegal-access flag. There are four possible settings:
- –illegal-access=permit is the Java 9 default behavior, printing a message for the first instance of illegal access.
- –illegal-access=warn prints a message for each illegal access.
- –illegal-access=debug prints a message and stack trace for each illegal access.
- –illegal-access=deny is the future default behavior, denying all illegal access.
Now is the time to test with –illegal-access=deny so you can be ready when that behavior becomes the default.
Consider an application that uses an internal API that is no longer accessible, such as com.sun.rowset.CachedRowSetImpl. The best remedy is to change the implementation. (As of Java 7, you can get a cached row set from a RowSetProvider.) But suppose you don’t have access to the source code.
In that case, start the application with the –add-exports flag. Specify the module and the package that you want to export, and the module to which you want to export the package, which in our case is the unnamed module.
java –illegal-access=deny –add-exports java.sql.rowset/com.sun.rowset=ALL_UNNAMED \
Now, suppose your application uses reflection to access private fields or methods. Reflection inside the unnamed module is OK, but it is no longer possible to reflectively access non-public members of the Java platform classes. For example, some libraries that dynamically generate Java classes call the protected CtassLoader.defineCtass method through reflection. If an application uses such a library, add the flag
When adding all those command-line options to get a legacy app to work, you may well end up with the command line from hell. To better manage multiple options, you can put them in one or more files specified with an @ prefix. For example,
java @options1 @options2 -jar MyProg.java
where the files options1 and options2 contain options for the java command. There are a few syntax rules for the options files:
- Separate options with spaces, tabs, or newlines.
- Use double quotes around arguments that include spaces, such as “Program Fites“.
- A line ending in a \ is merged with the next line.
- Backslashes must be escaped, such as C:\\Users\\Fred.
- Comment lines start with #.
Source: Horstmann Cay S. (2019), Core Java. Volume II – Advanced Features, Pearson; 11th edition.