Bug 60688

Summary: Tomcat should skip or handle module-info.class when scanning for annotations
Product: Tomcat 9 Reporter: Evgenij Ryazanov <katzyn>
Component: CatalinaAssignee: Tomcat Developers Mailing List <dev>
Status: RESOLVED FIXED    
Severity: minor    
Priority: P2    
Version: unspecified   
Target Milestone: -----   
Hardware: All   
OS: All   

Description Evgenij Ryazanov 2017-02-04 08:08:13 UTC
Libraries compatible with Java 8 or older may also contain module-info.class compiled for Java 9. Tomcat logs the following message for such libraries:

SEVERE: Unable to process Jar entry [module-info.class] from Jar [file:...../javax.json-1.1.0-M1.jar] for annotations
org.apache.tomcat.util.bcel.classfile.ClassFormatException: Invalid byte tag in constant pool: 19
at org.apache.tomcat.util.bcel.classfile.Constant.readConstant(Constant.java:97)
at org.apache.tomcat.util.bcel.classfile.ConstantPool.<init>(ConstantPool.java:54)
at org.apache.tomcat.util.bcel.classfile.ClassParser.readConstantPool(ClassParser.java:174)
at org.apache.tomcat.util.bcel.classfile.ClassParser.parse(ClassParser.java:83)
at org.apache.catalina.startup.ContextConfig.processAnnotationsStream(ContextConfig.java:2053)
at org.apache.catalina.startup.ContextConfig.processAnnotationsJar(ContextConfig.java:2000)
at org.apache.catalina.startup.ContextConfig.processAnnotationsUrl(ContextConfig.java:1970)
at org.apache.catalina.startup.ContextConfig.processAnnotations(ContextConfig.java:1923)
at org.apache.catalina.startup.ContextConfig.webConfig(ContextConfig.java:1163)
at org.apache.catalina.startup.ContextConfig.configureStart(ContextConfig.java:775)
at org.apache.catalina.startup.ContextConfig.lifecycleEvent(ContextConfig.java:299)
at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:94)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5087)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1419)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1409)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Comment 1 Konstantin Kolinko 2017-02-04 10:57:52 UTC
It is not that "Tomcat should skip or ..". It is that the underlying byte code parsing library (Apache Commons BCEL) does not know what is the meaning of entries with code "19" in a constant pool.

It knows what "18" means (CONSTANT_InvokeDynamic), bot not about "19".

http://svn.apache.org/viewvc/commons/proper/bcel/tags/BCEL_6_0/src/main/java/org/apache/bcel/classfile/Constant.java?view=markup#l127

http://svn.apache.org/viewvc/commons/proper/bcel/tags/BCEL_6_0/src/main/java/org/apache/bcel/Const.java?view=markup#l280


This needs
- a reference to a class file format specification (JVM specification) for the actual meaning of that code and

I expect the specs to be published here, but there is none for Java 9 yet:
http://docs.oracle.com/javase/specs/

- a bug report against BCEL library.

http://commons.apache.org/proper/commons-bcel/
Comment 2 Konstantin Kolinko 2017-02-04 11:05:06 UTC
> 
> This needs
> - a reference to a class file format specification (JVM specification) for
> the actual meaning of that code and
> 
> I expect the specs to be published here, but there is none for Java 9 yet:
> http://docs.oracle.com/javase/specs/
> 
> - a bug report against BCEL library.
> 
> http://commons.apache.org/proper/commons-bcel/


Although Tomcat code can be updated independently of BCEL, we must know what the code "19" means and thus how many bytes to skip (for the simple case if it can be ignored).

http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/bcel/classfile/Constant.java?revision=1757132&view=markup#l59
Comment 3 Evgenij Ryazanov 2017-02-04 12:20:22 UTC
19 is CONSTANT_Module and 20 is CONSTANT_Package.

I don't see a reason to scan module-info for annotations at all. @WebServlet, @WebFilter, or @WebListener is not expected here anyway.
Comment 4 Mark Thomas 2017-02-06 15:20:23 UTC
This comes under general Java 9 support.

At the moment Java 9 support is a moving target so it is only being implemented in trunk (9.0.x). Once Java 9 stabilises, expect to see support back-ported to the other Tomcat versions.

The proposal for these new constants is here:
http://cr.openjdk.java.net/~mr/jigsaw/spec/lang-vm.html

Looks like we just need to skip 2 bytes. The change needs to be implemented in Commons BCEL first and then back-ported to Tomcat.
Comment 5 Mark Thomas 2017-02-13 20:50:21 UTC
BCEL updated and back-port complete.

Fixed in:
- trunk for 9.0.0.M18 onwards
- 8.5.x for 8.5.12 onwards
- 8.0.x for 8.0.42 onwards
- 7.0.x for 7.0.76 onwards