japkit icon indicating copy to clipboard operation
japkit copied to clipboard

Fix WARNING: Illegal reflective access by javax.el.BeanELResolver with JDK 11

Open stefanocke opened this issue 7 years ago • 16 comments

When comiling japkit examples wit JDK 11 and javac:

WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by javax.el.BeanELResolver (file:/C:/java/maven/repository/org/apache/tomcat/embed/tomcat-embed-el/8.5.8/tomcat-embed-el-8.5.8.jar) to method com.sun.tools.javac.code.Symbol$TypeSymbol.asType()
WARNING: Please consider reporting this to the maintainers of javax.el.BeanELResolver
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

stefanocke avatar Jul 15 '18 08:07 stefanocke

To prepare for future JDKs, this warning should be fixed.

stefanocke avatar Jul 15 '18 08:07 stefanocke

And when using Groovy: WARNING: An illegal reflective access operation has occurred WARNING: Illegal reflective access by org.codehaus.groovy.reflection.CachedClass$3$1 (file:/C:/java/maven/repository/org/codehaus/groovy/groovy-all/2.4.7/groovy-all-2.4.7-indy.jar) to method java.lang.Object.finalize() WARNING: Please consider reporting this to the maintainers of org.codehaus.groovy.reflection.CachedClass$3$1

stefanocke avatar Jul 21 '18 09:07 stefanocke

And when using Groovy: WARNING: An illegal reflective access operation has occurred WARNING: Illegal reflective access by org.codehaus.groovy.reflection.CachedClass$3$1 (file:/C:/java/maven/repository/org/codehaus/groovy/groovy-all/2.4.7/groovy-all-2.4.7-indy.jar) to method java.lang.Object.finalize() WARNING: Please consider reporting this to the maintainers of org.codehaus.groovy.reflection.CachedClass$3$1

this issue is fixed in groovy-all 3.0.0-beta-1, newest version is 3.0.0-beta-2 https://issues.apache.org/jira/browse/GROOVY-8339

vkennke avatar Jul 16 '19 11:07 vkennke

When passing --illegal-access=debug (or warn) as VM parameter to the build of japkit-examples, further illegal access messages are revealed from / to;

  • javax.el.BeanELResolver to com.sun.tools.javac.code, com.sun.tools.javac.util
  • org.codehaus.groovy.reflection.CachedClass to java.lang, java.util, com.sun.tools.javac.code, com.sun.tools.javac.util
  • de.japkit.services.ElementsExtensions to com.sun.tools.javac.code (propbably in getValueWithErrorHandling)

stefanocke avatar Sep 28 '19 12:09 stefanocke

Example Stacktrace (with--illegal-access=deny ):

[ERROR] java.lang.IllegalAccessException: class javax.el.BeanELResolver cannot access class com.sun.tools.javac.util.List (in module jdk.compiler) because module jdk.compiler does not export com.sun.tools.javac.util to unnamed module @41f686af, cause: class javax.el.BeanELResolver cannot access class com.sun.tools.javac.util.List (in module jdk.compiler) because module jdk.compiler does not export com.sun.tools.javac.util to unnamed module @41f686af 
  		java.base/jdk.internal.reflect.Reflection.newIllegalAccessException(Reflection.java:361)
  				java.base/java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:591)
  				java.base/java.lang.reflect.Method.invoke(Method.java:558)
  				javax.el.BeanELResolver.invoke(BeanELResolver.java:158)
  				javax.el.CompositeELResolver.invoke(CompositeELResolver.java:79)
  				javax.el.CompositeELResolver.invoke(CompositeELResolver.java:79)
  				de.japkit.el.javael3.JapkitELResolver.invoke(JapkitELResolver.java:145)
  				org.apache.el.parser.AstValue.getValue(AstValue.java:159)
  				org.apache.el.parser.AstDeferredExpression.getValue(AstDeferredExpression.java:43)
  				org.apache.el.parser.AstCompositeExpression.getValue(AstCompositeExpression.java:49)
  				org.apache.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:190)
  				de.japkit.el.javael3.JavaEL3Provider.eval(JavaEL3Provider.java:36)
  				de.japkit.el.ELSupport.eval(ELSupport.java:329)

stefanocke avatar Sep 28 '19 12:09 stefanocke

  • With jdt, there are no warnings related to accessing the compiler API.
  • Most of the warnings are groovy related then

stefanocke avatar Sep 28 '19 12:09 stefanocke

For juel (java el 2), there are warnings with both compilers, for example: Illegal reflective access by javax.el.BeanELResolver (file:/C:/java/maven/repository/de/odysseus/juel/juel-api/2.2.6/juel-api-2.2.6.jar) to method java.util.Collections$UnmodifiableList.get(int)

stefanocke avatar Sep 28 '19 13:09 stefanocke

Adding the following JVM params for the Maven build makes the javac related warnings disappear:

--add-exports jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED
--add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED

Still no sure, who has to fix something in the long term. Japkit? maven-compiler-plugin? tomcat-embed-el? javac? (since it is working with jdt, it is more likely javac ...)

The solution above is from https://stackoverflow.com/questions/46773519/accessing-com-sun-tools-javac-util-from-java-9. There it is also suggested:

In the longer run, the safe way to be dealing with such situation is to move away from using these internal APIs of the JDK. One can make use of the jdk.compiler module's APIs as a replacement to the com.sun.tools.javac package.

However, japkit does not use com.sun.tools.javac directly, but just the annotation processing API...

stefanocke avatar Sep 28 '19 13:09 stefanocke

Previously, the --add-exports had been added as JVM params to the JVM that runs the Maven Build. That works, since this is the "runtime" for the japkit annotation processor. It does, however, not work to pass --add-exports to the compiler plugin in, since this is obviously an option for the code to be compiled, but not for running the annoatation processor.

stefanocke avatar Sep 28 '19 14:09 stefanocke

From Maven documentation:

...you can define JVM configuration via ${maven.projectBasedir}/.mvn/jvm.config file which means you can define the options for your build on a per project base

When creating this file with the following content, the javac related warnings disappear:

--add-exports jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED
--add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED

Still sounds like a workaround...

And Java 8 build does not work anymore then. See: https://blog.codefx.org/tools/maven-on-java-9/#Applying-Java-9-Flags-To-Maven-Process

stefanocke avatar Sep 28 '19 14:09 stefanocke

Here is a similar JDK bug for an annotation processor. https://bugs.openjdk.java.net/browse/JDK-8153060 However, the solution was to remove the reflective access...

https://github.com/javaee/metro-jax-ws/commit/90e1cb788b6866891757259e366f14477220348f#diff-32f859368099474565b05c3c29e230a3

And there is code like this: Class.forName("com.sun.tools.javac.processing.JavacProcessingEnvironment", false, cl)

So, it is quite obvious here that the reflective access in "on" com.sun.tools.javac.

Is it possible to "convince" the JVM that we reflect on java.lang.model and not on com.sun.tools.javac... ? Does it make any difference?

stefanocke avatar Sep 29 '19 10:09 stefanocke

I submitted a bug / enhancement for tomcat-embed-el to look for the interfaces if a type declaring a method is not exported by its module:

https://bz.apache.org/bugzilla/show_bug.cgi?id=63781

stefanocke avatar Sep 29 '19 12:09 stefanocke

Regarding: Illegal reflective access by de.japkit.services.ElementsExtensions (file:/C:/java/maven/repository/com/github/japkit/japkit-annotation-processor/1.20-SNAPSHOT/japkit-annotation-processor-1.20-SNAPSHOT.jar) to field com.sun.tools.javac.code.Attribute$UnresolvedClass.classType

This is caused by:

if(av?.class.canonicalName.equals("com.sun.tools.javac.code.Attribute.UnresolvedClass")){
			//Javac >= 8
			val errorType = try { 
				(av.class.getField("classType").get(av) as TypeMirror)
			} catch (Exception e){
				...
			}		
			return errorType
		}

This could probably be avoided by examining the AST of the AnnotationValue instead by com.sun.source.util.Trees.getTree(Element e, AnnotationMirror a, AnnotationValue v)

However, this is not available before JDK 9. So it must be deciced whether to increase JDK level of japkit before fixing this bug or implementing some JDK8-backward-compatible approach, which only uses AST, if com.sun.source.util.Trees is available.

Besides, the Trees-API could also help with ErrorTypes, especially with TypesRegistry guessTypeNameFromToString() and also with getting a FQN for the error type by scanning the import statements of the CompilationUnit.

stefanocke avatar Oct 04 '19 16:10 stefanocke

The AST of Annotation Value of type Class<?> is a MemberSelectTree where the identifier is "class" and the expression is the name of the class (potentially another MemberSelectTree if the class name is partially or fully qualified).

Trees.getTree does also work if the AnnotationValue is within an array.

stefanocke avatar Oct 04 '19 17:10 stefanocke

I have not seen those warnigns anymore wiht japkit 2.0, based on Java 17, Groovy 5, Tomcat EL 10.x But I have to check in more detail to be sure.

stefanocke avatar Aug 13 '23 13:08 stefanocke

Regarding: Illegal reflective access by de.japkit.services.ElementsExtensions (file:/C:/java/maven/repository/com/github/japkit/japkit-annotation-processor/1.20-SNAPSHOT/japkit-annotation-processor-1.20-SNAPSHOT.jar) to field com.sun.tools.javac.code.Attribute$UnresolvedClass.classType

This is caused by:

if(av?.class.canonicalName.equals("com.sun.tools.javac.code.Attribute.UnresolvedClass")){
			//Javac >= 8
			val errorType = try { 
				(av.class.getField("classType").get(av) as TypeMirror)
			} catch (Exception e){
				...
			}		
			return errorType
		}

This could probably be avoided by examining the AST of the AnnotationValue instead by com.sun.source.util.Trees.getTree(Element e, AnnotationMirror a, AnnotationValue v)

However, this is not available before JDK 9. So it must be deciced whether to increase JDK level of japkit before fixing this bug or implementing some JDK8-backward-compatible approach, which only uses AST, if com.sun.source.util.Trees is available.

Besides, the Trees-API could also help with ErrorTypes, especially with TypesRegistry guessTypeNameFromToString() and also with getting a FQN for the error type by scanning the import statements of the CompilationUnit.

Okay, debugging the build of japkit examples shows that this issue is still there: java.lang.IllegalAccessException: class de.japkit.services.ElementsExtensions cannot access class com.sun.tools.javac.code.Attribute$UnresolvedClass (in module jdk.compiler) because module jdk.compiler does not export com.sun.tools.javac.code to unnamed module @2f95ce11

It seems, that this does not finally lead to an error. It think that is primarily due to the fact that there are no cyclic dependencies between the genreated classes in the examples.

stefanocke avatar Aug 14 '23 07:08 stefanocke