Upcoming Java 17 Migration for Ignition 8.1

Hi Module Authors,

We are planning a bump to Java 17 in our main 8.1.x version branch. While for most of you this will have zero impact (outside of some great new language features) it might impact some modules in very serious ways. The main change which I wanted to make you all aware of is that the JDK internals are now Strongly Encapsulated by Default as of Java 16. Module authors should audit their modules for any issues they may cause due to Reflection into the JDK internals.

How to identify issues

there are some helpful tools to identify if you will be impacted:

  • Audit your code for setAccessible(true) usage for calls within non-public areas of the JDK.
  • Inspect your dependencies for java 9+ Module Path compatibility and any exceptions that must be required with --add-opens or -add-exports arguments. Upgrade the dependencies which have added support or removed their implementations which break strong encapsulation of the JDK.
  • Set --illegal-access=deny on your current builds to show what will fail when you eventually compile with java 17
  • Add the JVM argument -Dsun.reflect.debugModuleAccessChecks when running your module on a NIGHTLY gateway with java 17 once available. This will log exceptions due to encapsulation even if the exception is ignored/swallowed in code.

The Ignition platform and modules all still run on the classpath, meaning they are “unnamed modules”. This means that module access within the Ignition API’s (and even non-public) won’t break with this change, though diving into Ignition's internal implementations is not recommended anyways.

What to do if you can’t fix your Reflection into non-public JDK classes

Ignition will include a mechanism for dealing with this:

Gateway

Users will have to add --add-opens and --add-exports JVM arguments to their Ignition.conf. Currently (changes may occur as this migration is in active development) the following defaults are already included:

--add-opens=java.base/java.lang=ALL-UNNAMED
--add-opens=java.base/java.util=ALL-UNNAMED

Any additional arguments will need to be communicated by you (the module author) to end users to ensure these values are added to their ignition.conf

Vision Clients and Designers

Ignition already supplies a default set of Opens and Exports for launching clients/designers to the “unnamed” modules. These values may change over time, and they are visible in lib/runtime/client-opens.conf and lib/runtime/client-exports.conf. These files should not be modified as Ignition Upgrades will overwrite any changes here. Files with matching names and formats can be created by end users (at the direction of you, the module authors as necessary) in the data directory. These will persist across upgrades and will not be modified by I.A.

Currently the defaults are as follows:

client-opens.conf

java.base/java.lang
java.base/java.util
java.desktop/java.awt
java.desktop/java.awt.event
java.desktop/javax.swing
java.desktop/javax.swing.tree
java.desktop/javax.swing.plaf.basic
java.desktop/javax.swing.plaf.synth
java.desktop/javax.swing
java.desktop/javax.swing.tree

client-exports.conf

java.base/sun.security.action
java.desktop/com.apple.eawt
java.desktop/com.sun.awt
java.desktop/com.sun.java.swing.plaf.windows
java.desktop/sun.awt
java.desktop/sun.awt.image
java.desktop/sun.awt.shell
java.desktop/sun.awt.windows
java.desktop/sun.swing
java.desktop/sun.swing.plaf.synth
java.desktop/sun.swing.table
java.desktop/sun.print

To see the other changes which might impact your module, please refer to the Java 17 Migration Guide available from Oracle.

NOTE: These changes are in active development, but I wanted to make you all aware ahead of time in case you are impacted. the timetable for this is tentatively somewhere around 8.1.33

JJ Coffman

5 Likes

FWIW, with this added to ignition.conf:

wrapper.java.additional.15=--illegal-access=warn

I get this from v8.1.28:

# grep access wrapper.log 
2023/07/12 12:59:57.336 | WARNING: Illegal reflective access by com.inductiveautomation.ignition.gateway.modules.ModuleManagerImpl (file:/usr/share/ignition/lib/core/gateway/gateway-8.1.28.jar) to field java.lang.ClassLoader.usr_paths
2023/07/12 12:59:57.437 | WARNING: Illegal reflective access by com.inductiveautomation.ignition.gateway.util.IgnitionSocketImplFactory (file:/usr/share/ignition/lib/core/gateway/gateway-8.1.28.jar) to constructor java.net.SocksSocketImpl()
2023/07/12 12:59:57.437 | WARNING: Illegal reflective access by com.inductiveautomation.ignition.gateway.util.IgnitionSocketImplFactory (file:/usr/share/ignition/lib/core/gateway/gateway-8.1.28.jar) to field java.net.AbstractPlainSocketImpl.timeout
2023/07/12 12:59:57.538 | WARNING: Illegal reflective access by com.inductiveautomation.ignition.gateway.util.IgnitionSocketImplFactory (file:/usr/share/ignition/lib/core/gateway/gateway-8.1.28.jar) to constructor java.net.SocksSocketImpl()
2023/07/12 12:59:57.538 | WARNING: Illegal reflective access by com.inductiveautomation.ignition.gateway.util.IgnitionSocketImplFactory (file:/usr/share/ignition/lib/core/gateway/gateway-8.1.28.jar) to field java.net.AbstractPlainSocketImpl.timeout
2023/07/12 12:59:57.538 | WARNING: Illegal reflective access by com.inductiveautomation.ignition.gateway.util.IgnitionSocketImplFactory (file:/usr/share/ignition/lib/core/gateway/gateway-8.1.28.jar) to constructor java.net.SocksSocketImpl()
2023/07/12 12:59:57.538 | WARNING: Illegal reflective access by com.inductiveautomation.ignition.gateway.util.IgnitionSocketImplFactory (file:/usr/share/ignition/lib/core/gateway/gateway-8.1.28.jar) to field java.net.AbstractPlainSocketImpl.timeout
2023/07/12 13:00:05.456 | WARNING: Illegal reflective access by com.automation_pros.streamer.rpc.FieldClassBuilder (file:/usr/share/ignition/data/jar-cache/com.automation_pros.streamer/__3216193305__streamer-Common.jar) to method java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int)
2023/07/12 13:00:17.198 | WARNING: Illegal reflective access by com.inductiveautomation.ignition.gateway.util.IgnitionSocketImplFactory (file:/usr/share/ignition/lib/core/gateway/gateway-8.1.28.jar) to constructor java.net.SocksSocketImpl()
2023/07/12 13:00:17.198 | WARNING: Illegal reflective access by com.inductiveautomation.ignition.gateway.util.IgnitionSocketImplFactory (file:/usr/share/ignition/lib/core/gateway/gateway-8.1.28.jar) to field java.net.AbstractPlainSocketImpl.timeout
2023/07/12 13:00:17.198 | WARNING: Illegal reflective access by com.inductiveautomation.ignition.gateway.util.IgnitionSocketImplFactory (file:/usr/share/ignition/lib/core/gateway/gateway-8.1.28.jar) to constructor java.net.SocksSocketImpl()
2023/07/12 13:00:17.198 | WARNING: Illegal reflective access by com.inductiveautomation.ignition.gateway.util.IgnitionSocketImplFactory (file:/usr/share/ignition/lib/core/gateway/gateway-8.1.28.jar) to field java.net.AbstractPlainSocketImpl.timeout
2023/07/12 13:00:17.599 | WARNING: Illegal reflective access by com.inductiveautomation.ignition.gateway.util.IgnitionSocketImplFactory (file:/usr/share/ignition/lib/core/gateway/gateway-8.1.28.jar) to constructor java.net.SocksSocketImpl()
2023/07/12 13:00:17.599 | WARNING: Illegal reflective access by com.inductiveautomation.ignition.gateway.util.IgnitionSocketImplFactory (file:/usr/share/ignition/lib/core/gateway/gateway-8.1.28.jar) to field java.net.AbstractPlainSocketImpl.timeout
2023/07/12 13:00:17.599 | WARNING: Illegal reflective access by com.inductiveautomation.ignition.gateway.util.IgnitionSocketImplFactory (file:/usr/share/ignition/lib/core/gateway/gateway-8.1.28.jar) to constructor java.net.SocksSocketImpl()
2023/07/12 13:00:17.599 | WARNING: Illegal reflective access by com.inductiveautomation.ignition.gateway.util.IgnitionSocketImplFactory (file:/usr/share/ignition/lib/core/gateway/gateway-8.1.28.jar) to field java.net.AbstractPlainSocketImpl.timeout

It looks like I'm ok on java.lang.ClassLoader due to your default?

Yes, those issues should be covered by our defaults.

1 Like

Java 17 includes foreign function interface (ffi) will I be able to use these flags and how?
--enable-native-access=ALL-UNNAMED --add-modules jdk.incubator.foreign
or will this not be possible?

What about the next Java LTS Java 21? Plans?

Java 21 will probably happen some time in Ignition 8.3.

@jcoffman should be able to answer the other question - sounds like you can add them to ignition.conf somewhere?

Hi @tom.prodehl,

You can add the --enable-native-access=ALL-UNNAMED flag in ignition.conf or within the launchers' jvm arguments section. The jdk.incubator.foreign module (along with jdk.incubator.vector for the curious) is already included within our JRE and will not need to be added.

As far as Java 21 is concerned I don't think there are plans to bump the 8.1 branch to it, but I would expect it to be a part of 8.3 due to its release schedule.

Hope that helps,
JJ Coffman

1 Like

Has anybody looked at using the loom virtual threads yet? It sounds like that's going to be massive for you guys...

2 Likes

Very interesting. Especially how it hooks into Linux's (relatively) new io_uring infrastructure. Could be a very big win on Linux.

Haven't looked at running the gateway with it (yet), but we're definitely excited about it internally, yeah :slight_smile:

6 Likes

The Java 17 Upgrade was merged and will be available in the 9/8/2023 Nightly of 8.1.33.

8 Likes