]
Jaikiran Pai commented on WFCORE-4514:
--------------------------------------
Really glad that this helped :)
ProxyMetadataSource breaks contract of
ClassMetadataSource#getDeclaredMethods (resulting in "illegal reflective access
operation" in Java 11)
---------------------------------------------------------------------------------------------------------------------------------------------
Key: WFCORE-4514
URL:
https://issues.jboss.org/browse/WFCORE-4514
Project: WildFly Core
Issue Type: Bug
Components: Server
Affects Versions: 9.0.1.Final
Environment: Java 11
Reporter: Jaikiran Pai
Assignee: Jeff Mesnil
Priority: Major
While investigating this issue reported in the forum thread[1], where the user states
that using Java 11 shows up a warning about illegal reflective access:
{code}
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.jboss.invocation.proxy.AbstractProxyFactory$1
(jar:file:/C:/wildfly-16.0.0.Final/modules/system/layers/base/org/jboss/invocation/main/jboss-invocation-1.5.2.Final.jar!/)
to method java.lang.Object.clone()
WARNING: Please consider reporting this to the maintainers of
org.jboss.invocation.proxy.AbstractProxyFactory$1
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
{code}
I realized that, that issue is in fact triggered by, what I believe, is a bug and a
violation of an (internal) API contract in WildFly.
What seems to be happening is - when the proxy class is being defined for (EJB)
component, in the jboss-invocation library here[2], the implementation there overrides the
component classes' methods. It does that for the entire class hierarchy of the
component class and stops at the Object.class (rightly so) through the use of this
check[3] (currentClass != Object.class). In this implementation, within the loop, it then
calls:
{code}
ClassMetadataSource data = reflectionMetadataSource.getClassMetadata(currentClass);
{code}
which is an API exposed by the
org.jboss.invocation.proxy.reflection.ReflectionMetadataSource interface. The returned
ClassMetadataSource is then used within that loop as follows:
{code}
for (Method method : data.getDeclaredMethods()) {
....
{code}
The getDeclaredMethods() API, exposed by ClassMetadataSource[5] is expected to (only)
return the methods that are declared by that class. Turns out, the implementation in
WildFly[6], for this interface, doesn't honour that contract and instead returns all
methods (including the ones that are in the super class) on that class:
{code}
public Collection<Method> getDeclaredMethods() {
return index.getClassMethods();
}
{code}
The index.getClassMethods() is a call to the ClassReflectionIndex#getClassMethods() whose
implementation[7] walks through the entire class hierarchy and returns all the methods on
that class.
This (unexpected) implemetation of ProxyMetadataSource#getDeclaredMethods()[6] causes the
check in [3] to end up being irrelevant and as a result the code in [2] ends up trying to
take control over methods on the Object class (by calling method.setAccessible(true)[8])
and one such method is the "clone" method. This ultimately results in that
illegal reflective access warning.
Looking at the history of ProxyMetadataSource#getDeclaredMethods() in WildFly, it looks
like the implementation was changed to accomodate/fix this issue
https://issues.jboss.org/browse/WFCORE-579 in this commit
https://github.com/wildfly/wildfly-core/commit/4382f0c28dab2d0494926b8a34....
The previous implementation was returning the correct methods (only the declared ones).
Looking at that JIRA and linked bugzilla to it, I think the original issue might need a
different fix. I haven't yet had a chance to look more into that issue.
Of course, one way to solve the current issue at hand (the illegal reflective access one)
would be to add a check in
jboss-invocation's AbstractProxyFactory similar to this
https://github.com/wildfly/wildfly-core/blob/master/server/src/main/java/...,
but IMO, that would be more of a hack than an actual fix since the API contract violation
in ProxyMetadataSource will still be an issue and can (and probably does) cause some
unexpected problems.
[1]
https://developer.jboss.org/message/989623#989623
[2]
https://github.com/jbossas/jboss-invocation/blob/master/src/main/java/org...
[3]
https://github.com/jbossas/jboss-invocation/blob/master/src/main/java/org...
[4]
https://github.com/jbossas/jboss-invocation/blob/master/src/main/java/org...
[5]
https://github.com/jbossas/jboss-invocation/blob/master/src/main/java/org...
[6]
https://github.com/wildfly/wildfly-core/blob/5391b40b79f72d2a57d4e32234af...
[7]
https://github.com/wildfly/wildfly-core/blob/master/server/src/main/java/...
[8]
https://github.com/jbossas/jboss-invocation/blob/master/src/main/java/org...