Bug 58519 - org.apache.catalina.loader.WebappClassLoaderBase.checkStateForClassLoading throwing java.lang.IllegalStateException: Can't overwrite cause
Summary: org.apache.catalina.loader.WebappClassLoaderBase.checkStateForClassLoading th...
Status: RESOLVED FIXED
Alias: None
Product: Tomcat 8
Classification: Unclassified
Component: Catalina (show other bugs)
Version: 8.0.28
Hardware: PC All
: P2 normal (vote)
Target Milestone: ----
Assignee: Tomcat Developers Mailing List
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2015-10-22 10:49 UTC by Kaszaq
Modified: 2015-10-24 13:57 UTC (History)
1 user (show)



Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Kaszaq 2015-10-22 10:49:42 UTC
Hi,
Recently I had catalina log grow in few seconds to enormous sizes, partially due to problems with mentioned method. Instead of creating and declared ClassNotFoundException it throws "java.lang.IllegalStateException: Can't overwrite cause".

Looking into the code  I found here: http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.23/org/apache/catalina/loader/WebappClassLoaderBase.java#WebappClassLoaderBase.checkStateForClassLoading%28java.lang.String%29

1309    protected void checkStateForClassLoading(String className) throws ClassNotFoundException {
1310        // It is not permitted to load new classes once the web application has
1311        // been stopped.
1312        try {
1313            checkStateForResourceLoading(className);
1314        } catch (IllegalStateException ise) {
1315            ClassNotFoundException cnfe = new ClassNotFoundException();
1316            cnfe.initCause(ise);
1317            throw cnfe;
1318        }
1319    }

I belive the problem is caused by setting initcause on created class when constructor
new ClassNotFoundException()

has explicty stated:

71     public ClassNotFoundException() {
72         super((Throwable)null);  // Disallow initCause
73     }

Which during initCause is producing mentioned exception:

454     public synchronized Throwable initCause(Throwable cause) {
455         if (this.cause != this)
456             throw new IllegalStateException("Can't overwrite cause with " +
457                                             Objects.toString(cause, "a null"), this);
458         if (cause == this)
459             throw new IllegalArgumentException("Self-causation not permitted", this);
460         this.cause = cause;
461         return this;
462     }
Comment 1 Konstantin Kolinko 2015-10-22 11:48:11 UTC
Ack.

1) Tomcat side.

> 1314        } catch (IllegalStateException ise) {
> 1315            ClassNotFoundException cnfe = new ClassNotFoundException();
> 1316            cnfe.initCause(ise);
> 1317            throw cnfe;
> 1318        }

initCause() usually is used for compatibility for 1.3 and earlier versions of java that did not have a Throwable(Throwable cause) constructor. There is no ClassNotFoundException(Throwable) constructor, but there is (String, Throwable) one.

Calling initCause() here is a recent code, introduced in r1596004 (17 months ago) with additional refactoring in r1640087.

> 
> I belive the problem is caused by setting initcause on created class when
> constructor
> new ClassNotFoundException()
> 
> has explicty stated:
> 
> 71     public ClassNotFoundException() {
> 72         super((Throwable)null);  // Disallow initCause
> 73     }

The above nasty trick in JRE is old. E.g. 5u20 already has it...



2) The trigger for this behaviour is a bug in your own web application.

You cannot load classes when the web application (and its class loader) has already been stopped.

If you need help with fixing this bug in your application, ask on the users mailing list. Don't forget to provide version numbers and full stack trace.

http://tomcat.apache.org/lists.html#tomcat-users
http://markmail.org/message/ntwrtxeke4agdexj
Comment 2 Kaszaq 2015-10-22 20:02:06 UTC
No need, thanks. Trigger of this was inside hazelcast library.

Hazelcast that loads class for itself called a function on ClassLoader which was expected to throw ClassNotFoundException in case of any problem. I believe that if ClassLoader would throw expected ClassNotFoundException the problem would not occur.

However I am considering to report this to them as well as RuntimeException from any method should not cause the entire Hazelcast cluster to collapse - which is exactly what have happened because of the bug reported here and badly handling of runtime exceptions in Hazelcast.

The problem was caused by deploy of new version of application when the previous was was not undeployed correctly by Tomcat.
Comment 3 Mark Thomas 2015-10-24 13:57:03 UTC
Thanks for the report.

This has been fixed in trunk and 8.0.x for 8.0.29 onwards.