Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Analyze Classes in Java 11 failing with illegal-access=deny and create add-opens parameters #28596

Closed
Tracked by #27993
spbolton opened this issue May 17, 2024 · 6 comments · Fixed by #28619
Closed
Tracked by #27993

Comments

@spbolton
Copy link
Contributor

spbolton commented May 17, 2024

Java 21 is much more strict with changes to the ability to access internal classes and reflection of objects in general. Using reflection any code used to be able to freely change the accessibility of a method so a private method can be externally accessed. This is done with the setAccessible(true) method e.g.

method = providerAPI.getClass().getDeclaredMethod("getProvidersForRegion", new Class[] {String.class});
                method.setAccessible(true);

For a while using this has thrown a warning in the logs and the behavior could be altered with --ilegal-access= flag passed when starting up. In java 17 and above this option is removed and deny is the new default which causes errors in any code making use of this.

The ability to add reflective access does still exist but it needs to be explicitly allowed for each module using --add-opens on the command line. Adding this should mostly be thought of as a temporary measure in most cases we should not be attempting to modify the access of internal classes.

  1. Change to --illegal-access=warn or debug to insure that every occurrence of illegal access is logged.
  2. Analyze full logs from a CI build run to find unique classes causing problems and identify cause, e.g. XStream.
  3. Create a possible set of --add-opens that should cover all the found cases
  4. Test run full ci build with --illegal-access=deny
  5. Add Logging to identify a full list of classes we are trying to serialize/deserialize through ObjectInputStream, ObjectOutputStream and XStream to help identify where we are trying to serialize classes we should not be.
  6. Create a plan to define the changes that should be made to remove invalid Object serialization for the affected classes. e.g. Timezone, ConcurrentHashMap, or setting fields as transient.
@spbolton
Copy link
Contributor Author

Use ChatGPT to create an initial list of opens from analyzed classes including the classes it covers. Note these are only classes reached through all runs and testing in the ci build including integration and postman tests it is possible there could be more we are not hitting.

--add-opens java.management/com.sun.jmx.mbeanserver=ALL-UNNAMED
com.sun.jmx.mbeanserver.JmxMBeanServer.instantiator
com.sun.jmx.mbeanserver.JmxMBeanServer.mBeanServerDelegateObject
com.sun.jmx.mbeanserver.JmxMBeanServer.mbsInterceptor
com.sun.jmx.mbeanserver.JmxMBeanServer.outerShell
com.sun.jmx.mbeanserver.JmxMBeanServer.secureClr
--add-opens java.base/java.lang.ref=ALL-UNNAMED
java.lang.ref.Reference.discovered
java.lang.ref.Reference.next
java.lang.ref.Reference.queue
java.lang.ref.Reference.referent
--add-opens java.base/java.lang.reflect=ALL-UNNAMED
java.lang.reflect.AccessibleObject.securityCheckCache
java.lang.reflect.Constructor.annotations
java.lang.reflect.Constructor.clazz
java.lang.reflect.Constructor.constructorAccessor
java.lang.reflect.Constructor.exceptionTypes
java.lang.reflect.Constructor.genericInfo
java.lang.reflect.Constructor.parameterAnnotations
java.lang.reflect.Constructor.parameterTypes
java.lang.reflect.Constructor.root
java.lang.reflect.Constructor.signature
java.lang.reflect.Executable.declaredAnnotations
java.lang.reflect.Executable.parameters
--add-opens java.base/java.net=ALL-UNNAMED
java.net.URLClassLoader.ucp
--add-opens java.base/java.nio=ALL-UNNAMED
java.nio.ByteBuffer.hb
--add-opens java.base/java.nio.charset=ALL-UNNAMED
java.nio.charset.Charset.aliasSet
java.nio.charset.Charset.aliases
java.nio.charset.Charset.name
java.nio.charset.CharsetDecoder.charset
java.nio.charset.CharsetDecoder.malformedInputAction
java.nio.charset.CharsetDecoder.replacement
java.nio.charset.CharsetDecoder.unmappableCharacterAction
java.nio.charset.CharsetEncoder.cachedDecoder
java.nio.charset.CharsetEncoder.charset
java.nio.charset.CharsetEncoder.malformedInputAction
java.nio.charset.CharsetEncoder.replacement
java.nio.charset.CharsetEncoder.unmappableCharacterAction
java.nio.charset.CodingErrorAction.name
--add-opens java.base/java.time=ALL-UNNAMED
java.time.LocalDateTime.date
java.time.LocalDateTime.time
java.time.ZoneOffset.id
java.time.ZoneRegion.id
java.time.ZoneRegion.rules
--add-opens java.base/java.time.zone=ALL-UNNAMED
java.time.zone.ZoneRules.lastRules
java.time.zone.ZoneRules.lastRulesCache
java.time.zone.ZoneRules.savingsInstantTransitions
java.time.zone.ZoneRules.savingsLocalTransitions
java.time.zone.ZoneRules.standardOffsets
java.time.zone.ZoneRules.standardTransitions
java.time.zone.ZoneRules.wallOffsets
--add-opens java.base/java.util=ALL-UNNAMED
java.util.AbstractMap.keySet
java.util.AbstractMap.values
java.util.ArrayList.elementData
java.util.concurrent.ConcurrentHashMap$CollectionView.map
java.util.concurrent.ConcurrentHashMap$KeySetView.value
java.util.concurrent.ConcurrentHashMap$Node.key
java.util.concurrent.ConcurrentHashMap$Node.next
java.util.concurrent.ConcurrentHashMap$Node.val
java.util.concurrent.ConcurrentHashMap.counterCells
java.util.concurrent.ConcurrentHashMap.entrySet
java.util.concurrent.ConcurrentHashMap.keySet
java.util.concurrent.ConcurrentHashMap.nextTable
java.util.concurrent.ConcurrentHashMap.table
java.util.concurrent.ConcurrentHashMap.values
java.util.concurrent.locks.AbstractOwnableSynchronizer.exclusiveOwnerThread
java.util.concurrent.locks.AbstractOwnableSynchronizer.serialVersionUID
java.util.concurrent.locks.AbstractQueuedSynchronizer.HEAD
java.util.concurrent.locks.AbstractQueuedSynchronizer.SPIN_FOR_TIMEOUT_THRESHOLD
java.util.concurrent.locks.AbstractQueuedSynchronizer.STATE
java.util.concurrent.locks.AbstractQueuedSynchronizer.TAIL
java.util.concurrent.locks.AbstractQueuedSynchronizer.head
java.util.concurrent.locks.AbstractQueuedSynchronizer.serialVersionUID
java.util.concurrent.locks.AbstractQueuedSynchronizer.state
java.util.concurrent.locks.AbstractQueuedSynchronizer.state[\n]"
java.util.concurrent.locks.AbstractQueuedSynchronizer.tail
java.util.concurrent.locks.ReentrantLock$NonfairSync.serialVersionUID
java.util.concurrent.locks.ReentrantLock$Sync.serialVersionUID
java.util.concurrent.locks.ReentrantLock.serialVersionUID
java.util.concurrent.locks.ReentrantLock.serialVersionUID[\n]"
java.util.concurrent.locks.ReentrantLock.sync
java.util.concurrent.locks.ReentrantLock.sync[\n]"
java.util.regex.Pattern$Node.next
java.util.regex.Pattern$SliceNode.buffer
java.util.regex.Pattern.buffer
java.util.regex.Pattern.groupNodes
java.util.regex.Pattern.matchRoot
java.util.regex.Pattern.namedGroups
java.util.regex.Pattern.normalizedPattern
java.util.regex.Pattern.pattern
java.util.regex.Pattern.predicate
java.util.regex.Pattern.root
java.util.regex.Pattern.temp
java.util.regex.Pattern.topClosureNodes
--add-opens java.base/javax.crypto.spec=ALL-UNNAMED
javax.crypto.spec.SecretKeySpec.algorithm
javax.crypto.spec.SecretKeySpec.key
--add-opens java.management/javax.management=ALL-UNNAMED
javax.management.ObjectName._ca_array
javax.management.ObjectName._canonicalName
javax.management.ObjectName._kp_array
javax.management.ObjectName._propertyList
--add-opens java.base/sun.nio.cs=ALL-UNNAMED
sun.nio.cs.StreamDecoder.bb
sun.nio.cs.StreamDecoder.ch
sun.nio.cs.StreamDecoder.cs
sun.nio.cs.StreamDecoder.decoder
sun.nio.cs.StreamDecoder.in
sun.nio.cs.StreamEncoder.bb
sun.nio.cs.StreamEncoder.ch
sun.nio.cs.StreamEncoder.cs
sun.nio.cs.StreamEncoder.encoder
sun.nio.cs.StreamEncoder.lcb
sun.nio.cs.StreamEncoder.out
sun.nio.cs.UTF_8$Encoder.sgp
--add-opens java.base/sun.util.calendar=ALL-UNNAMED
sun.util.calendar.CalendarDate.era
sun.util.calendar.CalendarDate.locale
sun.util.calendar.CalendarDate.zoneinfo
sun.util.calendar.ZoneInfo.ABBR_MASK
sun.util.calendar.ZoneInfo.DST_MASK
sun.util.calendar.ZoneInfo.DST_NSHIFT
sun.util.calendar.ZoneInfo.OFFSET_MASK
sun.util.calendar.ZoneInfo.STANDARD_TIME
sun.util.calendar.ZoneInfo.TRANSITION_NSHIFT
sun.util.calendar.ZoneInfo.UTC_TIME
sun.util.calendar.ZoneInfo.WALL_TIME
sun.util.calendar.ZoneInfo.checksum
sun.util.calendar.ZoneInfo.dirty
sun.util.calendar.ZoneInfo.dstSavings
sun.util.calendar.ZoneInfo.lastRule
sun.util.calendar.ZoneInfo.offsets
sun.util.calendar.ZoneInfo.rawOffset
sun.util.calendar.ZoneInfo.rawOffsetDiff
sun.util.calendar.ZoneInfo.serialVersionUID
sun.util.calendar.ZoneInfo.simpleTimeZoneParams
sun.util.calendar.ZoneInfo.transitions
sun.util.calendar.ZoneInfo.willGMTOffsetChange
sun.util.calendar.ZoneInfo.readObject(java.io.ObjectInputStream)
--add-opens java.base/sun.util.locale=ALL-UNNAMED
sun.util.locale.BaseLocale.language
sun.util.locale.BaseLocale.region
sun.util.locale.BaseLocale.script
sun.util.locale.BaseLocale.variant
--add-opens java.base/sun.net.dns=ALL-UNNAMED
sun.net.dns.ResolverConfiguration.nameservers()
sun.net.dns.ResolverConfiguration.open()
sun.net.dns.ResolverConfiguration.searchlist()

@nollymar
Copy link
Contributor

nollymar commented Jun 5, 2024

Note to QA:
Should focus on any issues with bundles due to the serialization and deserialization and errors in logs indicating there is illegal access to internal classes. Serialization during caching would also be a concern area and reporting of cache sizes.

Besides, please export a starter (Settings > Maintenance > Download Starter ZIP File) and use the downloaded file to start up the server again. Check the logs for any serialization/deserialization issue

@nollymar nollymar reopened this Jun 5, 2024
@nollymar nollymar added the Merged label Jun 5, 2024
@dcolina dcolina self-assigned this Jun 5, 2024
@dcolina
Copy link
Contributor

dcolina commented Jun 11, 2024

Internal QA: Needs work.

After some tests we have noticed there are some errors during the Nightly build process:

19_Nightly Test _ Run Postman Tests - default

2024-06-11T03:54:26.2664723Z DOTCMS:03:54:26.265  INFO  provider.CacheSizingUtil - Unable to use the Unsafe.class to size cache objects, falling back to serialization:java.lang.RuntimeException: java.lang.RuntimeException: java.lang.RuntimeException: java.lang.RuntimeException: java.lang.RuntimeException: java.lang.RuntimeException: java.lang.RuntimeException: java.lang.RuntimeException: java.lang.RuntimeException: java.lang.RuntimeException: java.lang.reflect.InaccessibleObjectException: Unable to make field private final java.util.ArrayList jdk.internal.loader.URLClassPath.path accessible: module java.base does not "opens jdk.internal.loader" to unnamed module @67c23ad0 (every 60000 millis)

21_Nightly CLI Build _ Build native image on Linux

WARNING: Illegal reflective access by io.netty.util.internal.ReflectionUtil (file:/home/runner/work/core/core/tools/dotcms-cli/cli/target/dotcms-cli-1.0.0-SNAPSHOT-native-image-source-jar/lib/io.netty.netty-common-4.1.100.Final.jar) to constructor java.nio.DirectByteBuffer(long,int)

22_Nightly CLI Build _ Build native image on macOS-Intel

WARNING: Illegal reflective access by io.netty.util.internal.ReflectionUtil (file:/home/runner/work/core/core/tools/dotcms-cli/cli/target/dotcms-cli-1.0.0-SNAPSHOT-native-image-source-jar/lib/io.netty.netty-common-4.1.100.Final.jar) to constructor java.nio.DirectByteBuffer(long,int)

23_Nightly CLI Build _ Build native image on macOS-Silicon

WARNING: Illegal reflective access by io.netty.util.internal.ReflectionUtil (file:/home/runner/work/core/core/tools/dotcms-cli/cli/target/dotcms-cli-1.0.0-SNAPSHOT-native-image-source-jar/lib/io.netty.netty-common-4.1.100.Final.jar) to constructor java.nio.DirectByteBuffer(long,int)

@dcolina dcolina removed their assignment Jun 11, 2024
@spbolton
Copy link
Contributor Author

Warnings in the CLI should not be part of the scope of this ticket. We have not modified the illegal access paramters for the CLI, any warnings here were there before and only warnings on Java 11. Upgrading Quarkus to 3.5+ to a Java 21 supported version should resolve these issues and should be handled in that issue.

@dcolina
Copy link
Contributor

dcolina commented Jun 13, 2024

Taking into account the comment of @spbolton we tagged this card as Internal QA: Passed.

We have been able to download and upload a starter without catching any error related to an Illegal reflective access.

@bryanboza
Copy link
Member

Fixed, tested generating a new starter and using that to start a new instance and this is working as expected

Tested on trunk [ _75b3f8a ]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Done
Development

Successfully merging a pull request may close this issue.

4 participants