You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tomcat.apache.org by Austin Jones <aj...@avadynehealth.com> on 2015/03/21 23:19:43 UTC

ClassNotFoundError on context unload

I'm having an issue with Tomcat 8.0.12 when undeploying contexts.  I have
autoDeploy turned off, and am pushing WARs+context.xmls through the Tomcat
manager's deploy command.

I have several ServletContextListeners that handle proper context
shutdown.  The ones that cause the issue look like this:

@Override
public synchronized void contextInitialized( ServletContextEvent event ) {
if( enabled ) {
MyClass.initialize();
}
}

@Override
public synchronized void contextDestroyed( ServletContextEvent event ) {
MyClass.release();
}

If the 'enabled' flag is not set, and MyClass was not loaded anywhere else
in the app, the webapp ClassLoader tries to load the class while the
context is shutting down.  It throws this exception:
 java.lang.NoClassDefFoundError: some/package/MyClass
        at
some.package.MyListener.contextDestroyed(SingletonCleaner.java:na)
        at
org.apache.catalina.core.StandardContext.listenerStop(StandardContext.java:4792)
        at
org.apache.catalina.core.StandardContext.stopInternal(StandardContext.java:5392)
        at
org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:232)
        at
org.apache.catalina.core.StandardContext.reload(StandardContext.java:3768)
        at
org.apache.catalina.startup.HostConfig.reload(HostConfig.java:1306)
        at
org.apache.catalina.startup.HostConfig.checkResources(HostConfig.java:1238)
        at
org.apache.catalina.startup.HostConfig.check(HostConfig.java:1493)
        at sun.reflect.GeneratedMethodAccessor574.invoke(Unknown Source)
        at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:483)
        at
org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:300)
        at
com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
--
Caused by: java.lang.ClassNotFoundException: some.package.MyClass
        at
org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1320)
        at
org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1173)
        ... 45 more

I set WebappClassLoader logging levels to FINE, and got this output:
21-Mar-2015 14:59:46.493 FINE [localhost-startStop-1]
org.apache.catalina.loader.WebappClassLoader.loadClass
loadClass(some.package.MyClass, false)
21-Mar-2015 14:59:46.493 FINE [localhost-startStop-1]
org.apache.catalina.loader.WebappClassLoader.findClass
findClass(some.package.MyClass)

Any ideas why the class loader is throwing the errors?

Re: ClassNotFoundError on context unload

Posted by Austin Jones <aj...@avadynehealth.com>.
Hi Mark,
Sorry for the ambiguous 'unload' language, I suppose the tomcat language
would be 'context stop'.  The issue occurs when deploying the WAR using the
Tomcat Manager interface (*not *by dropping the WAR in /webapps).

You should be able to reproduce the issue with these steps:

   1. Build the ClassNotFoundGenerator WAR from
   https://github.com/austinjones/ClassNotFoundGenerator/
   2. Make this HTTP request to the Tomcat Manager:
    /manager/text/deploy?war=path/to/ClassNotFoundGenerator.war&version=&config=path/to/context.xml&path=/ClassNotFoundGenerator&update=true
   3. After the application is fully deployed, make the HTTP request again.

   4. The TestcaseContextListener.contextDestroyed handler fires.  The
   ClassNotFoundError is caught by Tomcat, and logged to localhost.log.

Thank you for your help on this!  Let me know if I can clarify any further.

On Mon, Mar 23, 2015 at 12:50 AM, Mark Thomas <ma...@apache.org> wrote:
>
> It isn't clear (yet) that there is a problem.
>
> > Should the ClassLoader fall back to the
> > compressed WAR?  Should the DocBase be deleted after the context is
> stopped?
>
> The subject uses "unload". That concept is not one used in the Tomcat
> docs or code.
>
> You stated in your first message that autoDeploy was disabled.
>
> It isn't clear what the "unload" is, what is triggering it and what
> changes (if any) you have made to either the WAR or the exploded
> directory. Some details on what is triggering this issue would go a long
> way to helping figuring out what is going on and if there is a bug here
> or not.
>
> Mark
>
> >
> > On Sun, Mar 22, 2015 at 2:26 PM, Austin Jones <aj...@avadynehealth.com>
> wrote:
> >
> >> I was able to reproduce the issue in a simple testcase application:
> >> https://github.com/austinjones/ClassNotFoundGenerator/
> >>
> >> On Sun, Mar 22, 2015 at 1:45 PM, Austin Jones <aj...@avadynehealth.com>
> >> wrote:
> >>
> >>> I put 8.0.20 on a testing machine, and saw the same issue.
> >>>
> >>> On Sun, Mar 22, 2015 at 12:15 PM, Christopher Schultz <
> >>> chris@christopherschultz.net> wrote:
> >>>
> > Austin,
> >
> > On 3/21/15 6:19 PM, Austin Jones wrote:
> >>>>>> I'm having an issue with Tomcat 8.0.12 when undeploying contexts.
> >>>>>> I have autoDeploy turned off, and am pushing WARs+context.xmls
> >>>>>> through the Tomcat manager's deploy command.
> >>>>>>
> >>>>>> I have several ServletContextListeners that handle proper context
> >>>>>> shutdown.  The ones that cause the issue look like this:
> >>>>>>
> >>>>>> @Override public synchronized void contextInitialized(
> >>>>>> ServletContextEvent event ) { if( enabled ) {
> >>>>>> MyClass.initialize(); } }
> >>>>>>
> >>>>>> @Override public synchronized void contextDestroyed(
> >>>>>> ServletContextEvent event ) { MyClass.release(); }
> >>>>>>
> >>>>>> If the 'enabled' flag is not set, and MyClass was not loaded
> >>>>>> anywhere else in the app, the webapp ClassLoader tries to load the
> >>>>>> class while the context is shutting down.  It throws this
> >>>>>> exception: java.lang.NoClassDefFoundError: some/package/MyClass at
> >>>>>> some.package.MyListener.contextDestroyed(SingletonCleaner.java:na)
> >>>>>> at
> >>>>>>
> >
> org.apache.catalina.core.StandardContext.listenerStop(StandardContext.java:4792)
> >>>>>>
> >>>>>>
> > at
> >>>>>>
> >
> org.apache.catalina.core.StandardContext.stopInternal(StandardContext.java:5392)
> >>>>>>
> >>>>>>
> > at
> >>>>>> org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:232)
> >>>>>>
> >>>>>>
> > at
> >>>>>>
> >
> org.apache.catalina.core.StandardContext.reload(StandardContext.java:3768)
> >>>>>>
> >>>>>>
> > at
> >>>>>> org.apache.catalina.startup.HostConfig.reload(HostConfig.java:1306)
> >>>>>>
> >>>>>>
> > at
> >>>>>>
> >
> org.apache.catalina.startup.HostConfig.checkResources(HostConfig.java:1238)
> >>>>>>
> >>>>>>
> > at
> >>>>>> org.apache.catalina.startup.HostConfig.check(HostConfig.java:1493)
> >>>>>> at sun.reflect.GeneratedMethodAccessor574.invoke(Unknown Source)
> >>>>>> at
> >>>>>>
> >
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
> >>>>>>
> >>>>>>
> > at java.lang.reflect.Method.invoke(Method.java:483)
> >>>>>> at
> >>>>>>
> >
> org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:300)
> >>>>>>
> >>>>>>
> > at
> >>>>>>
> >
> com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
> >>>>>>
> >>>>>>
> >>>>
> >>>> ---------------------------------------------------------------------
> >>>> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
> >>>> For additional commands, e-mail: users-help@tomcat.apache.org
> >>>>
> >>>
> >
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: users-help@tomcat.apache.org
>

Re: ClassNotFoundError on context unload

Posted by Mark Thomas <ma...@apache.org>.
On 23/03/2015 02:11, Austin Jones wrote:
> After a bit of debugging, I found the issue.  The stack traces below are on
> 8.0.12-src.
> 
> The bug occurs at this stack:
> 
>> StandardContext.reload() line: 3779
>> HostConfig.reload(HostConfig$DeployedApplication) line: 1306
>> HostConfig.checkResources(HostConfig$DeployedApplication) line: 1238
>> HostConfig.check(String) line: 1493
> 
> 
> HostConfig.checkResources(DeployedApplication) runs through the branch:
> 
>> if (app.hasDescriptor && resource.getName().toLowerCase(
>> Locale.ENGLISH).endsWith(".war")) { ... }
> 
> 
> It calls ExpandWar.delete( docBaseFile ), which is the unpacked webapp
> directory.
> 
> Then, checkResources calls reload(app) - which invokes the context
> listener.
> 
> The ClassLoader eventually gets down to this stack:
> 
>> DirResourceSet.getResource(String) line: 100
> 
> StandardRoot.getResourceInternal(String, boolean) line: 280
>> Cache.getResource(String, boolean) line: 65
>> StandardRoot.getResource(String, boolean, boolean) line: 216
>> StandardRoot.getClassLoaderResource(String) line: 225
>> WebappClassLoader.findResourceInternal(String, String) line: 2556
>> WebappClassLoader.findClassInternal(String) line: 2410
>> WebappClassLoader.findClass(String) line: 880
>> WebappClassLoader.loadClass(String, boolean) line: 1290
>> WebappClassLoader.loadClass(String) line: 1173
>> TestcaseContextListener.contextDestroyed(ServletContextEvent) line: 23
>> StandardContext.listenerStop() line: 4792
>> StandardContext.stopInternal() line: 5392
>> StandardContext(LifecycleBase).stop() line: 232
>> StandardContext.reload() line: 3768
>> HostConfig.reload(HostConfig$DeployedApplication) line: 1306
>> HostConfig.checkResources(HostConfig$DeployedApplication) line: 1238
>> HostConfig.check(String) line: 1493
> 
> 
> Unfortunately, checkResources just deleted the base directory.  The
> ClassLoader is looking for
> /WEB-INF/classes/com/avadyne/ThisClassNotFound.class, but that path no
> longer exists.  Most of the functions in the stack return null,
> and findClassInternal(String) throws the ClassNotFoundError at line 906.
> 
> OK, how should this be fixed?

It isn't clear (yet) that there is a problem.

> Should the ClassLoader fall back to the
> compressed WAR?  Should the DocBase be deleted after the context is stopped?

The subject uses "unload". That concept is not one used in the Tomcat
docs or code.

You stated in your first message that autoDeploy was disabled.

It isn't clear what the "unload" is, what is triggering it and what
changes (if any) you have made to either the WAR or the exploded
directory. Some details on what is triggering this issue would go a long
way to helping figuring out what is going on and if there is a bug here
or not.

Mark

> 
> On Sun, Mar 22, 2015 at 2:26 PM, Austin Jones <aj...@avadynehealth.com> wrote:
> 
>> I was able to reproduce the issue in a simple testcase application:
>> https://github.com/austinjones/ClassNotFoundGenerator/
>>
>> On Sun, Mar 22, 2015 at 1:45 PM, Austin Jones <aj...@avadynehealth.com>
>> wrote:
>>
>>> I put 8.0.20 on a testing machine, and saw the same issue.
>>>
>>> On Sun, Mar 22, 2015 at 12:15 PM, Christopher Schultz <
>>> chris@christopherschultz.net> wrote:
>>>
> Austin,
> 
> On 3/21/15 6:19 PM, Austin Jones wrote:
>>>>>> I'm having an issue with Tomcat 8.0.12 when undeploying contexts.
>>>>>> I have autoDeploy turned off, and am pushing WARs+context.xmls
>>>>>> through the Tomcat manager's deploy command.
>>>>>>
>>>>>> I have several ServletContextListeners that handle proper context
>>>>>> shutdown.  The ones that cause the issue look like this:
>>>>>>
>>>>>> @Override public synchronized void contextInitialized(
>>>>>> ServletContextEvent event ) { if( enabled ) {
>>>>>> MyClass.initialize(); } }
>>>>>>
>>>>>> @Override public synchronized void contextDestroyed(
>>>>>> ServletContextEvent event ) { MyClass.release(); }
>>>>>>
>>>>>> If the 'enabled' flag is not set, and MyClass was not loaded
>>>>>> anywhere else in the app, the webapp ClassLoader tries to load the
>>>>>> class while the context is shutting down.  It throws this
>>>>>> exception: java.lang.NoClassDefFoundError: some/package/MyClass at
>>>>>> some.package.MyListener.contextDestroyed(SingletonCleaner.java:na)
>>>>>> at
>>>>>>
> org.apache.catalina.core.StandardContext.listenerStop(StandardContext.java:4792)
>>>>>>
>>>>>>
> at
>>>>>>
> org.apache.catalina.core.StandardContext.stopInternal(StandardContext.java:5392)
>>>>>>
>>>>>>
> at
>>>>>> org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:232)
>>>>>>
>>>>>>
> at
>>>>>>
> org.apache.catalina.core.StandardContext.reload(StandardContext.java:3768)
>>>>>>
>>>>>>
> at
>>>>>> org.apache.catalina.startup.HostConfig.reload(HostConfig.java:1306)
>>>>>>
>>>>>>
> at
>>>>>>
> org.apache.catalina.startup.HostConfig.checkResources(HostConfig.java:1238)
>>>>>>
>>>>>>
> at
>>>>>> org.apache.catalina.startup.HostConfig.check(HostConfig.java:1493)
>>>>>> at sun.reflect.GeneratedMethodAccessor574.invoke(Unknown Source)
>>>>>> at
>>>>>>
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
>>>>>>
>>>>>>
> at java.lang.reflect.Method.invoke(Method.java:483)
>>>>>> at
>>>>>>
> org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:300)
>>>>>>
>>>>>>
> at
>>>>>>
> com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
>>>>>>
>>>>>>
>>>>
>>>> ---------------------------------------------------------------------
>>>> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
>>>> For additional commands, e-mail: users-help@tomcat.apache.org
>>>>
>>>
> 


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: ClassNotFoundError on context unload

Posted by Austin Jones <aj...@avadynehealth.com>.
>
> Please file a bug in Bugzilla for this. If you're feeling
> enterprising, go ahead and attach a WAR (including source) that can
> reproduce the issue.

Submitted as bug 57772
<https://bz.apache.org/bugzilla/show_bug.cgi?id=57772>.  The example WAR is
on github, and the steps to reproduce should be easy to follow.

I suppose your code could try { ... } catch (NoClassDefFoundError) but
> if course that's a stupid hack that should not be necessary. But,
> it'll get the job done until a patch is available for Tomcat.

Yeah, I did that for my generic initialization layer, so other components
could stop if one failed.

This is a part of Tomcat's code with which I have little familiarity,

Ha, same here.

Thanks for your investigation, and your explanation.

[it] helps me get my brain around it and will also help whoever
> will end up fixing this (not likely me, due to said lack of familiarity).

No problem.  Thank you for your help, Chris!

Re: ClassNotFoundError on context unload

Posted by Christopher Schultz <ch...@christopherschultz.net>.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

Austin,

On 3/26/15 7:33 PM, Austin Jones wrote:
> I believe I figured this part out in the debugger.  When the 
> WebappClassLoader attempts to load the class, the .class file (and
> the entire exploded directory) is not on the disk.  First, let me
> quote a few frames of the ClassNotFoundError stack trace (once
> again, 8.0.20).
> 
> java.lang.NoClassDefFoundError: com/avadyne/ThisClassNotFound ... 
> at 
> org.apache.catalina.core.StandardContext.reload(StandardContext.java:3739)
>
> 
at org.apache.catalina.startup.HostConfig.reload(HostConfig.java:1304)
> at 
> org.apache.catalina.startup.HostConfig.checkResources(HostConfig.java:1236)
>
> 
...
> 
> HostConfig.checkResources:1231 deletes the exploded directory 
> HostConfig.checkResources:1236 calls into StandardContext.reload 
> StandardContext.reload:3739 eventually invokes the
> ServletContextListeners

That sounds like an oops to me.

> Once the contextDestroyed listeners are executed, the .class file
> doesn't exist (HostConfig.checkResources deleted it).

It's odd that the class needs to be loaded on shutdown, but I think
it's a valid use case that should definitely work.

> I have walked (in the debugger) all the way from
> HostConfig.checkResources to the
> SevletContextListener/WebappClassLoader.loadClass call, and there 
> doesn't seem to be any other code that causes trouble.
> 
> It is definitely unsafe for HostConfig.checkResources to delete
> the unpacked directory before the context is stopped.  However, 
> WebappClassLoader is correct to throw a ClassNotFoundError, since
> the class really doesn't exist on disk.

Okay, so it sounds like this is really just an incorrect
order-of-operations problem.

>> Now, Tomcat 8 uses a more complicated resource-loading framework 
>> than previous Tomcats, and it's possible that the
>> resource-loading framework is being taken down earlier than your
>> code is running, which would make certain classes /libraries
>> inaccessible. I haven't read enough code to know if that's the
>> case or not. IMO it shouldn't be the case, and probably isn't
>> because the smarter Tomcat devs tend to think about things like
>> that before coding them ;)
>> 
>> IIRC, during ServletContextListener.contextDestroyed, the 
>> WebappClassLoader should be fully-functional. That is, it
>> shouldn't have complained about anything.
> 
> I wouldn't blame anyone for not noticing this bug.  And, I dream of
> a fully functional ClassLoader :D
> 
> The bug requires very specific conditions. Deploy a WAR through the
> Tomcat manager, and configure it to explode the war, and create a
> listener that references a class on shutdown that was never
> referenced prior...

Please file a bug in Bugzilla for this. If you're feeling
enterprising, go ahead and attach a WAR (including source) that can
reproduce the issue.

> Unfortunately, the impact (uncaught java.lang.Error leaving
> uncleaned resources/threads) is pretty severe.  It is also
> unavoidable if you need to execute lots of code in the shutdown
> handler, or you need to wait for Threads to stop.  I need to do
> both...

I suppose your code could try { ... } catch (NoClassDefFoundError) but
if course that's a stupid hack that should not be necessary. But,
it'll get the job done until a patch is available for Tomcat.

>> In my first example, the ClassNotFoundError is thrown when
>>> enabled=false. When enabled=true, the error doesn't occur.
>> When you say enabled=true, you mean that's what's showing in the 
>> Manager's web interface?
> 
> Don't worry too much about the enabled flag, it doesn't have
> anything to do with the actual issue.  I was trying to explain why
> a class wouldn't be loaded during contextInitialized (in this case
> - when initialization is conditional).
> 
>> The "new" WebappClassLoader shouldn't even be involved, yet,
>> since the shutdown is evidently not completing successfully, so
>> the reload never actually gets to the "load" part.
> 
> Well, yes and no.  The WebappClassLoader which throws the 
> ClassNotFoundError is definitely the one on the 'stop' side of the
> reload. I can tell from the cached classes.

Right, that's exactly what I would have expected.

> The ClassNotFoundError gets caught and logged by 
> StandardContext.listenerStop(), which catches Throwable.  Tomcat
> completes the reload without any issue.
> 
>> When you do the reload(), are you shutting-down a
>> properly-running web application, or one that failed to load
>> properly in the first place?
> 
> Yes, the app is up and running just fine.  All servlets/listeners
> are mounted, and no errors were reported during startup.
> 
>> I actually have reworked my app's top-level initialization layer
>> to
>>> preload classes on startup.  I am considering preloading all 
>>> classes in WEB-INF/classes at server startup.  Unfortunately,
>>> my init layer needs to call into code deeper in the
>>> application, which may call into bundled JARs (WEB-INF/lib).
>>> Including JARs, that would be a lot of code to preload.
> 
> 
> 
>> It also shouldn't be necessary. I think something else weird
>> might be going on.
> 
> It's a temporary workaround, but it works OK.  I get occasional
> NPEs from the ClassLoader when it needs to load from JARs in
> WEB-INF/lib, but I can live with that until the Tomcat code is
> fixed.  Actually, Guava's ClassPath API made preloading
> surprisingly easy.

Log the bug; I'm sure it's relatively easy to fix.

Thanks for your investigation, and your explanation. This is a part of
Tomcat's code with which I have little familiarity, so explaining
everything helps me get my brain around it and will also help whoever
will end up fixing this (not likely me, due to said lack of familiarity).

- -chris
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1
Comment: GPGTools - http://gpgtools.org

iQIcBAEBCAAGBQJVFVncAAoJEBzwKT+lPKRYfEYP/isWOdc8vnCwzbVLVvvEX3Ps
RnpLBOkyHyuyXPfcsYK3/Z99Sjkr2CKG5qURBut2YtequkAFvKD2GkA5mPkXvb6t
4RTu/TPIuRiOb9Z3O2g3sEYjz1lILlpXpW9rcPi3emb5c0QKUVJDtS1mZZBxkDzO
7A9FUW7Mue0thWwaHRVUqiKooVBX44s0VcAzh68LG2dhL7R6MiB9HrIka1sDKi/V
d25gKXSqLh6E2GBlQ9NygqY/D9hjkP/mTz9LbuPid5WHD28bvBX+JId8pVVLwiOp
iX2uVP6pcUXAQiHhdGGZjxM2u9FB6vDF1Mu2f8C38fLVsQ7sFsdA3SrIS2bJR62b
HOFCLqG6qbKvhzAGRBOBhjDzX0pxw2sJvxUTaL9AS2PStYetso6WKz8e24bCdjWz
WPlFzIYY7wqymx4anabyjkEG9OhXCCMiIdP6bGnj9+5BQGL5Uqi0s1rhiLzreEbB
8CdgBVjSYhunP7N3nqA5ntYVvkg1oZGQXiKbxnLwrnoV8JCVbo6mr4P8zZV8VvVr
rni7LviSlHtMrURitCN39A2s5Xg/rnZg2uQSfTCbPKUmxugEB1u15TxefLwbd3+I
kHrWOf5XOtRmKAGCiKvWJYLZbqgZhah//lXzcdo0jv5WiWt32JjvqL3ciEHuunJo
7FoKJQYPiE/dAT6PLX0c
=ZWGK
-----END PGP SIGNATURE-----

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: ClassNotFoundError on context unload

Posted by Austin Jones <aj...@avadynehealth.com>.
Hi Chris,
I know what is going on here (it is quite clear in the debugger).  I'll
take you through it one step at a time in this email, but the issue is
complicated, so I'll try to be thorough.

Would you be willing to try the newly-minted 8.0.21, or 8.0.20, to see

if it makes a difference?

Yes, I would!  I just tested/debugged in 8.0.20, and the issue still
occurs.  I don't see 8.0.21 on the tomcat download site, so I checked out
trunk, and the code I believe is responsible for this bug (I'll explain
below) hasn't been modified since 8.0.20.

Are there any other log messages in either your application's log, the
> localhost_*.log, or catalina.out that come *before* this
> ClassNotFoundException?

Nope.

In your original message, did you post the full and complete stack trace?

I believe so, but I might as well post updated versions from 8.0.20.
26-Mar-2015 14:38:46.838 SEVERE [http-nio-8443-exec-5]
org.apache.catalina.core.StandardContext.listenerStop Exception sending
context destroyed event to listener instance of class
com.avadyne.TestcaseContextListener
 java.lang.NoClassDefFoundError: com/avadyne/ThisClassNotFound
at
com.avadyne.TestcaseContextListener.contextDestroyed(TestcaseContextListener.java:27)
at
org.apache.catalina.core.StandardContext.listenerStop(StandardContext.java:4775)
at
org.apache.catalina.core.StandardContext.stopInternal(StandardContext.java:5385)
at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:232)
at
org.apache.catalina.core.StandardContext.reload(StandardContext.java:3739)
at org.apache.catalina.startup.HostConfig.reload(HostConfig.java:1304)
at
org.apache.catalina.startup.HostConfig.checkResources(HostConfig.java:1236)
at org.apache.catalina.startup.HostConfig.check(HostConfig.java:1491)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at
org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:300)
at
com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801)
at
org.apache.catalina.manager.ManagerServlet.check(ManagerServlet.java:1460)
at
org.apache.catalina.manager.ManagerServlet.deploy(ManagerServlet.java:906)
at org.apache.catalina.manager.ManagerServlet.doGet(ManagerServlet.java:344)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:618)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:725)
at
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291)
at
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at
org.apache.catalina.filters.SetCharacterEncodingFilter.doFilter(SetCharacterEncodingFilter.java:108)
at
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at
org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
at
org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
at
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:613)
at
org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142)
at
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
at
org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:610)
at
org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
at
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:516)
at
org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1086)
at
org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:659)
at
org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:223)
at
org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1558)
at
org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1515)
at
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at
org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.ClassNotFoundException: com.avadyne.ThisClassNotFound
at
org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1305)
at
org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1157)
... 45 more

Here is the stack where the ClassLoader gives up on loading the class
(8.0.20).  The WebResourceSet it would have used to load the class from (in
the method StandardRoot.getResourceInternal) is a DirResourceSet pointed to
the exploded directory path - e.g.
/path/to/tomcat/webapps/ClassNotFoundGenerator/.  I can see it in the
debugger in the allResources member variable.  The path it generates in
DirResourceSet.getResource
is /path/to/tomcat/webapps/ClassNotFoundGenerator/WEB-INF/classes/com/avadyne/ThisClassNotFound.class
- the path is correct.  The file doesn't exist, and it returns a new
EmptyResource(root, path, f).

Daemon Thread [http-nio-8443-exec-31] (Suspended)
owns: WebappClassLoader  (id=3483)
owns: TestcaseContextListener  (id=3488)
owns: StandardContext  (id=3324)
owns: HostConfig  (id=3323)
owns: SecureNioChannel  (id=3313)
StandardRoot.getResourceInternal(String, boolean) line: 302
Cache.getResource(String, boolean) line: 65
StandardRoot.getResource(String, boolean, boolean) line: 216
StandardRoot.getClassLoaderResource(String) line: 225
WebappClassLoader(WebappClassLoaderBase).findResourceInternal(String,
String) line: 2548
WebappClassLoader(WebappClassLoaderBase).findClassInternal(String) line:
2405
WebappClassLoader(WebappClassLoaderBase).findClass(String) line: 854
WebappClassLoader(WebappClassLoaderBase).loadClass(String, boolean) line:
1274
WebappClassLoader(WebappClassLoaderBase).loadClass(String) line: 1157
TestcaseContextListener.contextDestroyed(ServletContextEvent) line: 27
StandardContext.listenerStop() line: 4775
StandardContext.stopInternal() line: 5385
StandardContext(LifecycleBase).stop() line: 232
StandardContext.reload() line: 3739
HostConfig.reload(HostConfig$DeployedApplication) line: 1304
HostConfig.checkResources(HostConfig$DeployedApplication) line: 1236
HostConfig.check(String) line: 1491
NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not
available [native method]
NativeMethodAccessorImpl.invoke(Object, Object[]) line: 62
DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43
Method.invoke(Object, Object...) line: 483
BaseModelMBean.invoke(String, Object[], String[]) line: 300
DefaultMBeanServerInterceptor.invoke(ObjectName, String, Object[],
String[]) line: 819
JmxMBeanServer.invoke(ObjectName, String, Object[], String[]) line: 801
ManagerServlet.check(String) line: 1460
ManagerServlet.deploy(PrintWriter, String, ContextName, String, boolean,
StringManager) line: 906
ManagerServlet.doGet(HttpServletRequest, HttpServletResponse) line: 344
ManagerServlet(HttpServlet).service(HttpServletRequest,
HttpServletResponse) line: 618
ManagerServlet(HttpServlet).service(ServletRequest, ServletResponse) line:
725
ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse)
line: 291
ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 206
WsFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 52
ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse)
line: 239
ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 206
SetCharacterEncodingFilter.doFilter(ServletRequest, ServletResponse,
FilterChain) line: 108
ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse)
line: 239
ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 206
StandardWrapperValve.invoke(Request, Response) line: 219
StandardContextValve.invoke(Request, Response) line: 106
BasicAuthenticator(AuthenticatorBase).invoke(Request, Response) line: 613
StandardHostValve.invoke(Request, Response) line: 142
ErrorReportValve.invoke(Request, Response) line: 79
AccessLogValve(AbstractAccessLogValve).invoke(Request, Response) line: 610
StandardEngineValve.invoke(Request, Response) line: 88
CoyoteAdapter.service(Request, Response) line: 516
Http11NioProcessor(AbstractHttp11Processor).process(SocketWrapper<S>) line:
1086
Http11NioProtocol$Http11ConnectionHandler(AbstractProtocol$AbstractConnectionHandler).process(SocketWrapper<S>,
SocketStatus) line: 659
Http11NioProtocol$Http11ConnectionHandler.process(SocketWrapper<NioChannel>,
SocketStatus) line: 223
NioEndpoint$SocketProcessor.doRun(SelectionKey, NioEndpoint$KeyAttachment)
line: 1558
NioEndpoint$SocketProcessor.run() line: 1515
ThreadPoolExecutor(ThreadPoolExecutor).runWorker(ThreadPoolExecutor$Worker)
line: 1142
ThreadPoolExecutor$Worker.run() line: 617
TaskThread$WrappingRunnable.run() line: 61
TaskThread(Thread).run() line: 745

Taking a look at Tomcat 8 trunk, this code has undergone a large
> refactoring since 8.0.12 so the line numbers aren't correct relative
> to your stack trace. I looked in 8.0.12 and the line in question
> (WebappClassLoader.java:1320) is at the end of the loadClass method,
> when all options for loading the class have been exhausted. It just
> gives up and says "sorry, I can't find the class".

Yes, that is what I saw in the debugger on 8.0.12.  It goes all the way
down to findClass, findClassInternal and findResourceInternal before giving
up.  8.0.12 takes a slightly different path than 8.0.20, but 8.0.20 still
fails to find the class and throws a ClassNotFoundError.

It's possible that Tomcat's reload process first notifies the
> WebappClassLoader that it shouldn't load any new classes during
> shutdown, but that sounds like it would be a recipe for disaster --
> the kind of disaster that you are experiencing, here.

That would trigger a ClassNotFoundError in
WebappClassLoader.checkStateForClassLoading or
checkStateForResourceLoading, right?  I can see in the debugger the
loadClass(String,boolean) method continues after
checkStateForClassLoading.  I have a better explanation, though, so keep
reading :)

In this case, I would expect that the class is actually missing. Are
> you sure it's there? Where is it located?

At first I was thinking that WCL was objecting to loading the class,
> but it's not: it's actually not finding it.

I believe I figured this part out in the debugger.  When the
WebappClassLoader attempts to load the class, the .class file (and the
entire exploded directory) is not on the disk.  First, let me quote a few
frames of the ClassNotFoundError stack trace (once again, 8.0.20).

 java.lang.NoClassDefFoundError: com/avadyne/ThisClassNotFound
...
  at
org.apache.catalina.core.StandardContext.reload(StandardContext.java:3739)
at org.apache.catalina.startup.HostConfig.reload(HostConfig.java:1304)
at
org.apache.catalina.startup.HostConfig.checkResources(HostConfig.java:1236)
...

HostConfig.checkResources:1231 deletes the exploded directory
HostConfig.checkResources:1236 calls into StandardContext.reload
StandardContext.reload:3739 eventually invokes the ServletContextListeners

Once the contextDestroyed listeners are executed, the .class file doesn't
exist (HostConfig.checkResources deleted it).

I have walked (in the debugger) all the way from HostConfig.checkResources
to the SevletContextListener/WebappClassLoader.loadClass call, and there
doesn't seem to be any other code that causes trouble.

It is definitely unsafe for HostConfig.checkResources to delete the
unpacked directory before the context is stopped.  However,
WebappClassLoader is correct to throw a ClassNotFoundError, since the class
really doesn't exist on disk.

Now, Tomcat 8 uses a more
> complicated resource-loading framework than previous Tomcats, and it's
> possible that the resource-loading framework is being taken down
> earlier than your code is running, which would make certain classes
> /libraries inaccessible. I haven't read enough code to know if that's
> the case or not. IMO it shouldn't be the case, and probably isn't
> because the smarter Tomcat devs tend to think about things like that
> before coding them ;)



Okay. IIRC, during ServletContextListener.contextDestroyed, the
> WebappClassLoader should be fully-functional. That is, it shouldn't
> have complained about anything.

I wouldn't blame anyone for not noticing this bug.  And, I dream of a fully
functional ClassLoader :D

The bug requires very specific conditions. Deploy a WAR through the Tomcat
manager, and configure it to explode the war, and create a listener that
references a class on shutdown that was never referenced prior...

Unfortunately, the impact (uncaught java.lang.Error leaving uncleaned
resources/threads) is pretty severe.  It is also unavoidable if you need to
execute lots of code in the shutdown handler, or you need to wait for
Threads to stop.  I need to do both...

> In my first example, the ClassNotFoundError is thrown when
> > enabled=false. When enabled=true, the error doesn't occur.
> When you say enabled=true, you mean that's what's showing in the
> Manager's web interface?

Don't worry too much about the enabled flag, it doesn't have anything to do
with the actual issue.  I was trying to explain why a class wouldn't be
loaded during contextInitialized (in this case - when initialization is
conditional).

The "new" WebappClassLoader shouldn't even be involved, yet, since the
> shutdown is evidently not completing successfully, so the reload never
> actually gets to the "load" part.

Well, yes and no.  The WebappClassLoader which throws the
ClassNotFoundError is definitely the one on the 'stop' side of the reload.
I can tell from the cached classes.

The ClassNotFoundError gets caught and logged by
StandardContext.listenerStop(), which catches Throwable.  Tomcat completes
the reload without any issue.

When you do the reload(), are you shutting-down a properly-running web
> application, or one that failed to load properly in the first place?

Yes, the app is up and running just fine.  All servlets/listeners are
mounted, and no errors were reported during startup.

> I actually have reworked my app's top-level initialization layer to
> > preload classes on startup.  I am considering preloading all
> > classes in WEB-INF/classes at server startup.  Unfortunately, my
> > init layer needs to call into code deeper in the application, which
> > may call into bundled JARs (WEB-INF/lib).  Including JARs, that
> > would be a lot of code to preload.



It also shouldn't be necessary. I think something else weird might be
> going on.

It's a temporary workaround, but it works OK.  I get occasional NPEs from
the ClassLoader when it needs to load from JARs in WEB-INF/lib, but I can
live with that until the Tomcat code is fixed.  Actually, Guava's ClassPath
API made preloading surprisingly easy.

Re: ClassNotFoundError on context unload

Posted by Christopher Schultz <ch...@christopherschultz.net>.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

Austin,

On 3/23/15 2:54 PM, Austin Jones wrote:
> Hi Chris,
> 
>> If MyClass had been loaded at initialization time (like your
>> sample code shows), it should not have needed to be loaded back
>> off the disk for shutdown.
> 
> In my first example, the ClassNotFoundError is thrown when
> enabled=false. When enabled=true, the error doesn't occur.

When you say enabled=true, you mean that's what's showing in the
Manager's web interface?

>> Is it possible that MyClass is referencing another class 
>> (MyOtherClass) during shutdown that was never referenced during
>> startup?
> 
> In my production code, yes, that is the issue.

Okay. IIRC, during ServletContextListener.contextDestroyed, the
WebappClassLoader should be fully-functional. That is, it shouldn't
have complained about anything.

A reload() operation should be first stopping everything, then
disabling and discarding the WebappClassLoader for the "old" web
application, then creating a new WebappClassLoader and launching the
"new" copy of the web application using that new WebappClassLoader.

The "new" WebappClassLoader shouldn't even be involved, yet, since the
shutdown is evidently not completing successfully, so the reload never
actually gets to the "load" part.

It's possible that Tomcat's reload process first notifies the
WebappClassLoader that it shouldn't load any new classes during
shutdown, but that sounds like it would be a recipe for disaster --
the kind of disaster that you are experiencing, here.

> I actually have reworked my app's top-level initialization layer to
> preload classes on startup.  I am considering preloading all
> classes in WEB-INF/classes at server startup.  Unfortunately, my
> init layer needs to call into code deeper in the application, which
> may call into bundled JARs (WEB-INF/lib).  Including JARs, that
> would be a lot of code to preload.

It also shouldn't be necessary. I think something else weird might be
going on.

When you do the reload(), are you shutting-down a properly-running web
application, or one that failed to load properly in the first place?

Are there any other log messages in either your application's log, the
localhost_*.log, or catalina.out that come *before* this
ClassNotFoundException?

In your original message, did you post the full and complete stack trace?

Taking a look at Tomcat 8 trunk, this code has undergone a large
refactoring since 8.0.12 so the line numbers aren't correct relative
to your stack trace. I looked in 8.0.12 and the line in question
(WebappClassLoader.java:1320) is at the end of the loadClass method,
when all options for loading the class have been exhausted. It just
gives up and says "sorry, I can't find the class".

In this case, I would expect that the class is actually missing. Are
you sure it's there? Where is it located?

At first I was thinking that WCL was objecting to loading the class,
but it's not: it's actually not finding it. Now, Tomcat 8 uses a more
complicated resource-loading framework than previous Tomcats, and it's
possible that the resource-loading framework is being taken down
earlier than your code is running, which would make certain classes
/libraries inaccessible. I haven't read enough code to know if that's
the case or not. IMO it shouldn't be the case, and probably isn't
because the smarter Tomcat devs tend to think about things like that
before coding them ;)

After all that...

Would you be willing to try the newly-minted 8.0.21, or 8.0.20, to see
if it makes a difference?

- -chris
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1
Comment: GPGTools - http://gpgtools.org

iQIcBAEBCAAGBQJVEwfwAAoJEBzwKT+lPKRYlD8P/0MaHgu+5Q+VwehiP8BxMQ3g
JNNtu/+QQb2Rgzi3SjYwV8JzS3qmvEqcT0Fq+0bA6QOOL0Ae2IbrY/PVCWMz0Riz
2QjTsPG28SrmzsgVh/EiNxVnFBx/OzkQEfcvnjwQjYMgzH42mri3J2bk9MJ8i/mw
MwKEADFVJMwmadtb1ctl1QV2Kb0aK2dJm6rZ7O2Hyd/9YOuASxrtB7aB9UVAbqZ5
ZSfn70JIcCDgCxDbsg9nFmDxEewCj4V5V2mjqq73V6ZfPszzjZNmvWeZnqJb/7Et
fpw62W+MuRdsYhoidbwNaiXF1cDOneUi5l/Ci5UEZwP4YtAt3LnFaFnKQIVIEyl0
7UbCdczXF3EofrhhWgChg89UvmIIODfGLkvZeErXFfJveHQwK180ObD1iocIBLDH
cOnFGcJwm8P0/e/pRbzJsXfdwaCBSM2EGYLyhKHSJouD+YGUKIh1rVCvoZlqoRzs
+sZW1aOW6AKveU1qr2ugu3ZkgLxUKttDtCbecdnyzb5OdTpV4aWiJlqbiHCv8zd5
wFRFdB5jvDc8UfQGFELMBzhJo6q1YK9hgMbQNKXYqNT3+nKr9O+GhZGF96yieiT7
0ow4x4a31OHbieqhMNpQQ6gMtcV4ylwClLoqdKdIHV1xcEXaRKJAho36V/0RUkhE
EtS3voWtAVpfDUeZ5ijh
=IG7C
-----END PGP SIGNATURE-----

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: ClassNotFoundError on context unload

Posted by Austin Jones <aj...@avadynehealth.com>.
Hi Chris,

> If MyClass had been loaded at initialization time (like your sample
> code shows), it should not have needed to be loaded back off the disk
> for shutdown.

In my first example, the ClassNotFoundError is thrown when enabled=false.
When enabled=true, the error doesn't occur.

Is it possible that MyClass is referencing another class
> (MyOtherClass) during shutdown that was never referenced during startup?

In my production code, yes, that is the issue.

I actually have reworked my app's top-level initialization layer to preload
classes on startup.  I am considering preloading all classes in
WEB-INF/classes at server startup.  Unfortunately, my init layer needs to
call into code deeper in the application, which may call into bundled JARs
(WEB-INF/lib).  Including JARs, that would be a lot of code to preload.

On Mon, Mar 23, 2015 at 7:19 AM, Christopher Schultz <
chris@christopherschultz.net> wrote:

> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA256
>
> Austin,
>
> On 3/22/15 10:11 PM, Austin Jones wrote:
> > After a bit of debugging, I found the issue.  The stack traces
> > below are on 8.0.12-src.
> >
> > The bug occurs at this stack:
> >
> >> StandardContext.reload() line: 3779
> >> HostConfig.reload(HostConfig$DeployedApplication) line: 1306
> >> HostConfig.checkResources(HostConfig$DeployedApplication) line:
> >> 1238 HostConfig.check(String) line: 1493
> >
> >
> > HostConfig.checkResources(DeployedApplication) runs through the
> > branch:
> >
> >> if (app.hasDescriptor && resource.getName().toLowerCase(
> >> Locale.ENGLISH).endsWith(".war")) { ... }
> >
> >
> > It calls ExpandWar.delete( docBaseFile ), which is the unpacked
> > webapp directory.
> >
> > Then, checkResources calls reload(app) - which invokes the context
> > listener.
> >
> > The ClassLoader eventually gets down to this stack:
> >
> >> DirResourceSet.getResource(String) line: 100
> >
> > StandardRoot.getResourceInternal(String, boolean) line: 280
> >> Cache.getResource(String, boolean) line: 65
> >> StandardRoot.getResource(String, boolean, boolean) line: 216
> >> StandardRoot.getClassLoaderResource(String) line: 225
> >> WebappClassLoader.findResourceInternal(String, String) line:
> >> 2556 WebappClassLoader.findClassInternal(String) line: 2410
> >> WebappClassLoader.findClass(String) line: 880
> >> WebappClassLoader.loadClass(String, boolean) line: 1290
> >> WebappClassLoader.loadClass(String) line: 1173
> >> TestcaseContextListener.contextDestroyed(ServletContextEvent)
> >> line: 23 StandardContext.listenerStop() line: 4792
> >> StandardContext.stopInternal() line: 5392
> >> StandardContext(LifecycleBase).stop() line: 232
> >> StandardContext.reload() line: 3768
> >> HostConfig.reload(HostConfig$DeployedApplication) line: 1306
> >> HostConfig.checkResources(HostConfig$DeployedApplication) line:
> >> 1238 HostConfig.check(String) line: 1493
> >
> >
> > Unfortunately, checkResources just deleted the base directory.
> > The ClassLoader is looking for
> > /WEB-INF/classes/com/avadyne/ThisClassNotFound.class, but that path
> > no longer exists.  Most of the functions in the stack return null,
> > and findClassInternal(String) throws the ClassNotFoundError at line
> > 906.
> >
> > OK, how should this be fixed?  Should the ClassLoader fall back to
> > the compressed WAR?  Should the DocBase be deleted after the
> > context is stopped?
>
> If MyClass had been loaded at initialization time (like your sample
> code shows), it should not have needed to be loaded back off the disk
> for shutdown.
>
> Is it possible that MyClass is referencing another class
> (MyOtherClass) during shutdown that was never referenced during startup?
>
> - -chris
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v1
> Comment: GPGTools - http://gpgtools.org
>
> iQIcBAEBCAAGBQJVECDbAAoJEBzwKT+lPKRYWvUP/1EI5C6OzLOpo7kfknDZuoOK
> bjZiGsVjijiIbaFvVIJnhzXuwE6AW+xGeYOk+VlhxmnkPE2CFk/IH4ACRhN8unqr
> THWn7XS6OqFP2pixIkZoD0JPqlGXJmOSuJuHm/9LhsxCemMV0ZiZo9pFbQrgDDyt
> gpHGC7JNRPzLuf6b9xXIKdsDaKIPgeUCUF4TFlkD8t88214hVGszi8Iqa8oUuYuM
> VKHlufsmzQajjHRkNEZvc8yMOhCP/LJdhsX4GWjW1zcun/4fLHFWKU5eMQkHb5CK
> VXCS/XsTw8vnuTbI/CQ5QiloOWeong6uK1RtDoKg73quvBNXdjn8kApV01nPMNnr
> HWaCZJvtlcmjmfDDnI6NJilTR3y4K1zHR0uYuE6EtqxT4s0lkuBq5752Bq9KcNSo
> WzVKtxsxDkl+Kx60iqHFEu4/VJF4FahB4DHNOwnHXDOGrdpSGj4JrN4PrAd79ZEI
> 5dZEhg4bozEpoenXQ9Qs5KRKNUzJpC9ZIems5OgbFpHjiHqizc+dR9/kH9DdaVk+
> AcLI3JtCO5OBrxLyJ1qqnrsIpREJ/qnLpvO4+iX/ImOX+eCTOEmdUoDecjZDeUeP
> dMarqycbwLLZKABseAIRA8ut2XnpAaGf0NLPI5SWdMDp2uPbSG1+PIIjxeUFeLX5
> fQ6a+Q79kJAbgnwzrCvA
> =g8G/
> -----END PGP SIGNATURE-----
>

Re: ClassNotFoundError on context unload

Posted by Christopher Schultz <ch...@christopherschultz.net>.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

Austin,

On 3/22/15 10:11 PM, Austin Jones wrote:
> After a bit of debugging, I found the issue.  The stack traces
> below are on 8.0.12-src.
> 
> The bug occurs at this stack:
> 
>> StandardContext.reload() line: 3779 
>> HostConfig.reload(HostConfig$DeployedApplication) line: 1306 
>> HostConfig.checkResources(HostConfig$DeployedApplication) line:
>> 1238 HostConfig.check(String) line: 1493
> 
> 
> HostConfig.checkResources(DeployedApplication) runs through the
> branch:
> 
>> if (app.hasDescriptor && resource.getName().toLowerCase( 
>> Locale.ENGLISH).endsWith(".war")) { ... }
> 
> 
> It calls ExpandWar.delete( docBaseFile ), which is the unpacked
> webapp directory.
> 
> Then, checkResources calls reload(app) - which invokes the context 
> listener.
> 
> The ClassLoader eventually gets down to this stack:
> 
>> DirResourceSet.getResource(String) line: 100
> 
> StandardRoot.getResourceInternal(String, boolean) line: 280
>> Cache.getResource(String, boolean) line: 65 
>> StandardRoot.getResource(String, boolean, boolean) line: 216 
>> StandardRoot.getClassLoaderResource(String) line: 225 
>> WebappClassLoader.findResourceInternal(String, String) line:
>> 2556 WebappClassLoader.findClassInternal(String) line: 2410 
>> WebappClassLoader.findClass(String) line: 880 
>> WebappClassLoader.loadClass(String, boolean) line: 1290 
>> WebappClassLoader.loadClass(String) line: 1173 
>> TestcaseContextListener.contextDestroyed(ServletContextEvent)
>> line: 23 StandardContext.listenerStop() line: 4792 
>> StandardContext.stopInternal() line: 5392 
>> StandardContext(LifecycleBase).stop() line: 232 
>> StandardContext.reload() line: 3768 
>> HostConfig.reload(HostConfig$DeployedApplication) line: 1306 
>> HostConfig.checkResources(HostConfig$DeployedApplication) line:
>> 1238 HostConfig.check(String) line: 1493
> 
> 
> Unfortunately, checkResources just deleted the base directory.
> The ClassLoader is looking for 
> /WEB-INF/classes/com/avadyne/ThisClassNotFound.class, but that path
> no longer exists.  Most of the functions in the stack return null, 
> and findClassInternal(String) throws the ClassNotFoundError at line
> 906.
> 
> OK, how should this be fixed?  Should the ClassLoader fall back to
> the compressed WAR?  Should the DocBase be deleted after the
> context is stopped?

If MyClass had been loaded at initialization time (like your sample
code shows), it should not have needed to be loaded back off the disk
for shutdown.

Is it possible that MyClass is referencing another class
(MyOtherClass) during shutdown that was never referenced during startup?

- -chris
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1
Comment: GPGTools - http://gpgtools.org

iQIcBAEBCAAGBQJVECDbAAoJEBzwKT+lPKRYWvUP/1EI5C6OzLOpo7kfknDZuoOK
bjZiGsVjijiIbaFvVIJnhzXuwE6AW+xGeYOk+VlhxmnkPE2CFk/IH4ACRhN8unqr
THWn7XS6OqFP2pixIkZoD0JPqlGXJmOSuJuHm/9LhsxCemMV0ZiZo9pFbQrgDDyt
gpHGC7JNRPzLuf6b9xXIKdsDaKIPgeUCUF4TFlkD8t88214hVGszi8Iqa8oUuYuM
VKHlufsmzQajjHRkNEZvc8yMOhCP/LJdhsX4GWjW1zcun/4fLHFWKU5eMQkHb5CK
VXCS/XsTw8vnuTbI/CQ5QiloOWeong6uK1RtDoKg73quvBNXdjn8kApV01nPMNnr
HWaCZJvtlcmjmfDDnI6NJilTR3y4K1zHR0uYuE6EtqxT4s0lkuBq5752Bq9KcNSo
WzVKtxsxDkl+Kx60iqHFEu4/VJF4FahB4DHNOwnHXDOGrdpSGj4JrN4PrAd79ZEI
5dZEhg4bozEpoenXQ9Qs5KRKNUzJpC9ZIems5OgbFpHjiHqizc+dR9/kH9DdaVk+
AcLI3JtCO5OBrxLyJ1qqnrsIpREJ/qnLpvO4+iX/ImOX+eCTOEmdUoDecjZDeUeP
dMarqycbwLLZKABseAIRA8ut2XnpAaGf0NLPI5SWdMDp2uPbSG1+PIIjxeUFeLX5
fQ6a+Q79kJAbgnwzrCvA
=g8G/
-----END PGP SIGNATURE-----

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: ClassNotFoundError on context unload

Posted by Austin Jones <aj...@avadynehealth.com>.
After a bit of debugging, I found the issue.  The stack traces below are on
8.0.12-src.

The bug occurs at this stack:

> StandardContext.reload() line: 3779
> HostConfig.reload(HostConfig$DeployedApplication) line: 1306
> HostConfig.checkResources(HostConfig$DeployedApplication) line: 1238
> HostConfig.check(String) line: 1493


HostConfig.checkResources(DeployedApplication) runs through the branch:

> if (app.hasDescriptor && resource.getName().toLowerCase(
> Locale.ENGLISH).endsWith(".war")) { ... }


It calls ExpandWar.delete( docBaseFile ), which is the unpacked webapp
directory.

Then, checkResources calls reload(app) - which invokes the context
listener.

The ClassLoader eventually gets down to this stack:

> DirResourceSet.getResource(String) line: 100

StandardRoot.getResourceInternal(String, boolean) line: 280
> Cache.getResource(String, boolean) line: 65
> StandardRoot.getResource(String, boolean, boolean) line: 216
> StandardRoot.getClassLoaderResource(String) line: 225
> WebappClassLoader.findResourceInternal(String, String) line: 2556
> WebappClassLoader.findClassInternal(String) line: 2410
> WebappClassLoader.findClass(String) line: 880
> WebappClassLoader.loadClass(String, boolean) line: 1290
> WebappClassLoader.loadClass(String) line: 1173
> TestcaseContextListener.contextDestroyed(ServletContextEvent) line: 23
> StandardContext.listenerStop() line: 4792
> StandardContext.stopInternal() line: 5392
> StandardContext(LifecycleBase).stop() line: 232
> StandardContext.reload() line: 3768
> HostConfig.reload(HostConfig$DeployedApplication) line: 1306
> HostConfig.checkResources(HostConfig$DeployedApplication) line: 1238
> HostConfig.check(String) line: 1493


Unfortunately, checkResources just deleted the base directory.  The
ClassLoader is looking for
/WEB-INF/classes/com/avadyne/ThisClassNotFound.class, but that path no
longer exists.  Most of the functions in the stack return null,
and findClassInternal(String) throws the ClassNotFoundError at line 906.

OK, how should this be fixed?  Should the ClassLoader fall back to the
compressed WAR?  Should the DocBase be deleted after the context is stopped?

On Sun, Mar 22, 2015 at 2:26 PM, Austin Jones <aj...@avadynehealth.com> wrote:

> I was able to reproduce the issue in a simple testcase application:
> https://github.com/austinjones/ClassNotFoundGenerator/
>
> On Sun, Mar 22, 2015 at 1:45 PM, Austin Jones <aj...@avadynehealth.com>
> wrote:
>
>> I put 8.0.20 on a testing machine, and saw the same issue.
>>
>> On Sun, Mar 22, 2015 at 12:15 PM, Christopher Schultz <
>> chris@christopherschultz.net> wrote:
>>
>>> -----BEGIN PGP SIGNED MESSAGE-----
>>> Hash: SHA256
>>>
>>> Austin,
>>>
>>> On 3/21/15 6:19 PM, Austin Jones wrote:
>>> > I'm having an issue with Tomcat 8.0.12 when undeploying contexts.
>>> > I have autoDeploy turned off, and am pushing WARs+context.xmls
>>> > through the Tomcat manager's deploy command.
>>> >
>>> > I have several ServletContextListeners that handle proper context
>>> > shutdown.  The ones that cause the issue look like this:
>>> >
>>> > @Override public synchronized void contextInitialized(
>>> > ServletContextEvent event ) { if( enabled ) {
>>> > MyClass.initialize(); } }
>>> >
>>> > @Override public synchronized void contextDestroyed(
>>> > ServletContextEvent event ) { MyClass.release(); }
>>> >
>>> > If the 'enabled' flag is not set, and MyClass was not loaded
>>> > anywhere else in the app, the webapp ClassLoader tries to load the
>>> > class while the context is shutting down.  It throws this
>>> > exception: java.lang.NoClassDefFoundError: some/package/MyClass at
>>> > some.package.MyListener.contextDestroyed(SingletonCleaner.java:na)
>>> > at
>>> >
>>> org.apache.catalina.core.StandardContext.listenerStop(StandardContext.java:4792)
>>> >
>>> >
>>> at
>>> >
>>> org.apache.catalina.core.StandardContext.stopInternal(StandardContext.java:5392)
>>> >
>>> >
>>> at
>>> > org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:232)
>>> >
>>> >
>>> at
>>> >
>>> org.apache.catalina.core.StandardContext.reload(StandardContext.java:3768)
>>> >
>>> >
>>> at
>>> > org.apache.catalina.startup.HostConfig.reload(HostConfig.java:1306)
>>> >
>>> >
>>> at
>>> >
>>> org.apache.catalina.startup.HostConfig.checkResources(HostConfig.java:1238)
>>> >
>>> >
>>> at
>>> > org.apache.catalina.startup.HostConfig.check(HostConfig.java:1493)
>>> > at sun.reflect.GeneratedMethodAccessor574.invoke(Unknown Source)
>>> > at
>>> >
>>> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
>>> >
>>> >
>>> at java.lang.reflect.Method.invoke(Method.java:483)
>>> > at
>>> >
>>> org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:300)
>>> >
>>> >
>>> at
>>> >
>>> com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
>>> >
>>> >
>>> - --
>>> > Caused by: java.lang.ClassNotFoundException: some.package.MyClass
>>> > at
>>> >
>>> org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1320)
>>> >
>>> >
>>> at
>>> >
>>> org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1173)
>>> >
>>> >
>>> ... 45 more
>>> >
>>> > I set WebappClassLoader logging levels to FINE, and got this
>>> > output: 21-Mar-2015 14:59:46.493 FINE [localhost-startStop-1]
>>> > org.apache.catalina.loader.WebappClassLoader.loadClass
>>> > loadClass(some.package.MyClass, false) 21-Mar-2015 14:59:46.493
>>> > FINE [localhost-startStop-1]
>>> > org.apache.catalina.loader.WebappClassLoader.findClass
>>> > findClass(some.package.MyClass)
>>> >
>>> > Any ideas why the class loader is throwing the errors?
>>>
>>> Could you try again with the latest 8.0.20? There was a change in
>>> 8.0.18 that /might/ impact your situation:
>>> https://bz.apache.org/bugzilla/show_bug.cgi?id=57446
>>>
>>> - -chris
>>> -----BEGIN PGP SIGNATURE-----
>>> Version: GnuPG v1
>>> Comment: GPGTools - http://gpgtools.org
>>>
>>> iQIcBAEBCAAGBQJVDxTQAAoJEBzwKT+lPKRYG3UP/1WvGcySKDtqMZMoTVH5H3mW
>>> EHZiaZubtiaReAxw6z11yLijMU2TI8a7mwYz5fi34M7AQ7nke3R9Mm3p3oojfJY6
>>> jLVSTfe2fKYAK5rAdCNnuY2K/VVtpGR+q/KYLbsPkuIQYclamHtGbFuFxmUMm73O
>>> NQ0QdXreyPQrdeoY8sNz01Dx8nAgI+3YNAbv1TKSbXbh4qfLnoLNePBoqfu0azqC
>>> B0/rNw6ovzYcPo9BYplwK23BjxDa+P9F7wOxxSk8nf3tEpksnRC2EsUNL9kbGtDx
>>> TV/7xl8Ln3DpONzETGCLbrf5W6Cj1MkAiSBk5iOmbTQdCvetpQNB5D57ZLBiFMy7
>>> CEQrpWK9rQhmklmElxsmO0UvU/BLPoUtbv5BbJNnm3cYVgChgRrSpVVDtv8l33iF
>>> dAQCTXqtyHl46tR7lbkoeNO9/YHtJJQ93Rmw3wF+UlloXi7pRjJE1NHEbbzllUIj
>>> ddE8eqjP20ZkOrNa0I6vuk8Z6Tkf4aqIkvjMtnfyMb+9lImF33Y4PWsLRO8rvUmS
>>> CgNWebKGfNVoHrMJpSh/BOf1mkKkTE38hBUyRSZ66VMbTS0mAMr5nqnNfrKTm5b/
>>> nr9K0rcvusvs9sQyjBNEMg761ZGWcPGYWtQZNnyMHL5KmI4NF8OeSSlUO8V1Yvv7
>>> At0sF5VE58lDPP/VTDts
>>> =GVSN
>>> -----END PGP SIGNATURE-----
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
>>> For additional commands, e-mail: users-help@tomcat.apache.org
>>>
>>

Re: ClassNotFoundError on context unload

Posted by Austin Jones <aj...@avadynehealth.com>.
I was able to reproduce the issue in a simple testcase application:
https://github.com/austinjones/ClassNotFoundGenerator/

On Sun, Mar 22, 2015 at 1:45 PM, Austin Jones <aj...@avadynehealth.com> wrote:

> I put 8.0.20 on a testing machine, and saw the same issue.
>
> On Sun, Mar 22, 2015 at 12:15 PM, Christopher Schultz <
> chris@christopherschultz.net> wrote:
>
>> -----BEGIN PGP SIGNED MESSAGE-----
>> Hash: SHA256
>>
>> Austin,
>>
>> On 3/21/15 6:19 PM, Austin Jones wrote:
>> > I'm having an issue with Tomcat 8.0.12 when undeploying contexts.
>> > I have autoDeploy turned off, and am pushing WARs+context.xmls
>> > through the Tomcat manager's deploy command.
>> >
>> > I have several ServletContextListeners that handle proper context
>> > shutdown.  The ones that cause the issue look like this:
>> >
>> > @Override public synchronized void contextInitialized(
>> > ServletContextEvent event ) { if( enabled ) {
>> > MyClass.initialize(); } }
>> >
>> > @Override public synchronized void contextDestroyed(
>> > ServletContextEvent event ) { MyClass.release(); }
>> >
>> > If the 'enabled' flag is not set, and MyClass was not loaded
>> > anywhere else in the app, the webapp ClassLoader tries to load the
>> > class while the context is shutting down.  It throws this
>> > exception: java.lang.NoClassDefFoundError: some/package/MyClass at
>> > some.package.MyListener.contextDestroyed(SingletonCleaner.java:na)
>> > at
>> >
>> org.apache.catalina.core.StandardContext.listenerStop(StandardContext.java:4792)
>> >
>> >
>> at
>> >
>> org.apache.catalina.core.StandardContext.stopInternal(StandardContext.java:5392)
>> >
>> >
>> at
>> > org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:232)
>> >
>> >
>> at
>> >
>> org.apache.catalina.core.StandardContext.reload(StandardContext.java:3768)
>> >
>> >
>> at
>> > org.apache.catalina.startup.HostConfig.reload(HostConfig.java:1306)
>> >
>> >
>> at
>> >
>> org.apache.catalina.startup.HostConfig.checkResources(HostConfig.java:1238)
>> >
>> >
>> at
>> > org.apache.catalina.startup.HostConfig.check(HostConfig.java:1493)
>> > at sun.reflect.GeneratedMethodAccessor574.invoke(Unknown Source)
>> > at
>> >
>> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
>> >
>> >
>> at java.lang.reflect.Method.invoke(Method.java:483)
>> > at
>> >
>> org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:300)
>> >
>> >
>> at
>> >
>> com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
>> >
>> >
>> - --
>> > Caused by: java.lang.ClassNotFoundException: some.package.MyClass
>> > at
>> >
>> org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1320)
>> >
>> >
>> at
>> >
>> org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1173)
>> >
>> >
>> ... 45 more
>> >
>> > I set WebappClassLoader logging levels to FINE, and got this
>> > output: 21-Mar-2015 14:59:46.493 FINE [localhost-startStop-1]
>> > org.apache.catalina.loader.WebappClassLoader.loadClass
>> > loadClass(some.package.MyClass, false) 21-Mar-2015 14:59:46.493
>> > FINE [localhost-startStop-1]
>> > org.apache.catalina.loader.WebappClassLoader.findClass
>> > findClass(some.package.MyClass)
>> >
>> > Any ideas why the class loader is throwing the errors?
>>
>> Could you try again with the latest 8.0.20? There was a change in
>> 8.0.18 that /might/ impact your situation:
>> https://bz.apache.org/bugzilla/show_bug.cgi?id=57446
>>
>> - -chris
>> -----BEGIN PGP SIGNATURE-----
>> Version: GnuPG v1
>> Comment: GPGTools - http://gpgtools.org
>>
>> iQIcBAEBCAAGBQJVDxTQAAoJEBzwKT+lPKRYG3UP/1WvGcySKDtqMZMoTVH5H3mW
>> EHZiaZubtiaReAxw6z11yLijMU2TI8a7mwYz5fi34M7AQ7nke3R9Mm3p3oojfJY6
>> jLVSTfe2fKYAK5rAdCNnuY2K/VVtpGR+q/KYLbsPkuIQYclamHtGbFuFxmUMm73O
>> NQ0QdXreyPQrdeoY8sNz01Dx8nAgI+3YNAbv1TKSbXbh4qfLnoLNePBoqfu0azqC
>> B0/rNw6ovzYcPo9BYplwK23BjxDa+P9F7wOxxSk8nf3tEpksnRC2EsUNL9kbGtDx
>> TV/7xl8Ln3DpONzETGCLbrf5W6Cj1MkAiSBk5iOmbTQdCvetpQNB5D57ZLBiFMy7
>> CEQrpWK9rQhmklmElxsmO0UvU/BLPoUtbv5BbJNnm3cYVgChgRrSpVVDtv8l33iF
>> dAQCTXqtyHl46tR7lbkoeNO9/YHtJJQ93Rmw3wF+UlloXi7pRjJE1NHEbbzllUIj
>> ddE8eqjP20ZkOrNa0I6vuk8Z6Tkf4aqIkvjMtnfyMb+9lImF33Y4PWsLRO8rvUmS
>> CgNWebKGfNVoHrMJpSh/BOf1mkKkTE38hBUyRSZ66VMbTS0mAMr5nqnNfrKTm5b/
>> nr9K0rcvusvs9sQyjBNEMg761ZGWcPGYWtQZNnyMHL5KmI4NF8OeSSlUO8V1Yvv7
>> At0sF5VE58lDPP/VTDts
>> =GVSN
>> -----END PGP SIGNATURE-----
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
>> For additional commands, e-mail: users-help@tomcat.apache.org
>>
>>
>
>
> --
> *Austin Jones*
> Senior Designer
>
> *(619) 819-8844 x1040 <%28619%29%20819-8844%20x1040> Office*
> *(619) 819-8840 <%28619%29%20819-8840> Fax*
> *(619) 977-0927 <%28619%29%20977-0927> Mobile*
>
>
> *3131 Camino Del Rio North, Suite 1500San Diego, CA 92108*
>
>  [image: Avadyne Health]
>
> http://www.avadynehealth.com
>
> Benchmark Revenue Management has merged with Avadyne Health! Visit our
> website to learn more about this exciting synthesis, bringing
> technology-enabled services to healthcare revenue cycle management.
>
> *CONFIDENTIALITY NOTICE: This e-mail communication, including any
> attachments, is covered by the Electronic Communication Privacy Act of 1986
> (18 U.S.C. sections 2510-21) and may contain information protected by the
> federal regulations under the Health Insurance Portability and
> Accountability Act of 1996 (45 C. F. R. Parts 160-164) or other
> confidential information. If you are not the intended recipient (or
> authorized to receive for the recipient), you are hereby notified that any
> review, disclosure, dissemination, distribution or copying of this
> communication is strictly prohibited. If you have received this
> communication in error, please delete or destroy all copies of this
> communication and any attachments.*
>



-- 
*Austin Jones*
Senior Designer

*(619) 819-8844 x1040 Office*
*(619) 819-8840 Fax*
*(619) 977-0927 Mobile*


*3131 Camino Del Rio North, Suite 1500San Diego, CA 92108*

 [image: Avadyne Health]

http://www.avadynehealth.com

Benchmark Revenue Management has merged with Avadyne Health! Visit our
website to learn more about this exciting synthesis, bringing
technology-enabled services to healthcare revenue cycle management.

*CONFIDENTIALITY NOTICE: This e-mail communication, including any
attachments, is covered by the Electronic Communication Privacy Act of 1986
(18 U.S.C. sections 2510-21) and may contain information protected by the
federal regulations under the Health Insurance Portability and
Accountability Act of 1996 (45 C. F. R. Parts 160-164) or other
confidential information. If you are not the intended recipient (or
authorized to receive for the recipient), you are hereby notified that any
review, disclosure, dissemination, distribution or copying of this
communication is strictly prohibited. If you have received this
communication in error, please delete or destroy all copies of this
communication and any attachments.*

Re: ClassNotFoundError on context unload

Posted by Austin Jones <aj...@avadynehealth.com>.
I put 8.0.20 on a testing machine, and saw the same issue.

On Sun, Mar 22, 2015 at 12:15 PM, Christopher Schultz <
chris@christopherschultz.net> wrote:

> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA256
>
> Austin,
>
> On 3/21/15 6:19 PM, Austin Jones wrote:
> > I'm having an issue with Tomcat 8.0.12 when undeploying contexts.
> > I have autoDeploy turned off, and am pushing WARs+context.xmls
> > through the Tomcat manager's deploy command.
> >
> > I have several ServletContextListeners that handle proper context
> > shutdown.  The ones that cause the issue look like this:
> >
> > @Override public synchronized void contextInitialized(
> > ServletContextEvent event ) { if( enabled ) {
> > MyClass.initialize(); } }
> >
> > @Override public synchronized void contextDestroyed(
> > ServletContextEvent event ) { MyClass.release(); }
> >
> > If the 'enabled' flag is not set, and MyClass was not loaded
> > anywhere else in the app, the webapp ClassLoader tries to load the
> > class while the context is shutting down.  It throws this
> > exception: java.lang.NoClassDefFoundError: some/package/MyClass at
> > some.package.MyListener.contextDestroyed(SingletonCleaner.java:na)
> > at
> >
> org.apache.catalina.core.StandardContext.listenerStop(StandardContext.java:4792)
> >
> >
> at
> >
> org.apache.catalina.core.StandardContext.stopInternal(StandardContext.java:5392)
> >
> >
> at
> > org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:232)
> >
> >
> at
> >
> org.apache.catalina.core.StandardContext.reload(StandardContext.java:3768)
> >
> >
> at
> > org.apache.catalina.startup.HostConfig.reload(HostConfig.java:1306)
> >
> >
> at
> >
> org.apache.catalina.startup.HostConfig.checkResources(HostConfig.java:1238)
> >
> >
> at
> > org.apache.catalina.startup.HostConfig.check(HostConfig.java:1493)
> > at sun.reflect.GeneratedMethodAccessor574.invoke(Unknown Source)
> > at
> >
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
> >
> >
> at java.lang.reflect.Method.invoke(Method.java:483)
> > at
> >
> org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:300)
> >
> >
> at
> >
> com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
> >
> >
> - --
> > Caused by: java.lang.ClassNotFoundException: some.package.MyClass
> > at
> >
> org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1320)
> >
> >
> at
> >
> org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1173)
> >
> >
> ... 45 more
> >
> > I set WebappClassLoader logging levels to FINE, and got this
> > output: 21-Mar-2015 14:59:46.493 FINE [localhost-startStop-1]
> > org.apache.catalina.loader.WebappClassLoader.loadClass
> > loadClass(some.package.MyClass, false) 21-Mar-2015 14:59:46.493
> > FINE [localhost-startStop-1]
> > org.apache.catalina.loader.WebappClassLoader.findClass
> > findClass(some.package.MyClass)
> >
> > Any ideas why the class loader is throwing the errors?
>
> Could you try again with the latest 8.0.20? There was a change in
> 8.0.18 that /might/ impact your situation:
> https://bz.apache.org/bugzilla/show_bug.cgi?id=57446
>
> - -chris
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v1
> Comment: GPGTools - http://gpgtools.org
>
> iQIcBAEBCAAGBQJVDxTQAAoJEBzwKT+lPKRYG3UP/1WvGcySKDtqMZMoTVH5H3mW
> EHZiaZubtiaReAxw6z11yLijMU2TI8a7mwYz5fi34M7AQ7nke3R9Mm3p3oojfJY6
> jLVSTfe2fKYAK5rAdCNnuY2K/VVtpGR+q/KYLbsPkuIQYclamHtGbFuFxmUMm73O
> NQ0QdXreyPQrdeoY8sNz01Dx8nAgI+3YNAbv1TKSbXbh4qfLnoLNePBoqfu0azqC
> B0/rNw6ovzYcPo9BYplwK23BjxDa+P9F7wOxxSk8nf3tEpksnRC2EsUNL9kbGtDx
> TV/7xl8Ln3DpONzETGCLbrf5W6Cj1MkAiSBk5iOmbTQdCvetpQNB5D57ZLBiFMy7
> CEQrpWK9rQhmklmElxsmO0UvU/BLPoUtbv5BbJNnm3cYVgChgRrSpVVDtv8l33iF
> dAQCTXqtyHl46tR7lbkoeNO9/YHtJJQ93Rmw3wF+UlloXi7pRjJE1NHEbbzllUIj
> ddE8eqjP20ZkOrNa0I6vuk8Z6Tkf4aqIkvjMtnfyMb+9lImF33Y4PWsLRO8rvUmS
> CgNWebKGfNVoHrMJpSh/BOf1mkKkTE38hBUyRSZ66VMbTS0mAMr5nqnNfrKTm5b/
> nr9K0rcvusvs9sQyjBNEMg761ZGWcPGYWtQZNnyMHL5KmI4NF8OeSSlUO8V1Yvv7
> At0sF5VE58lDPP/VTDts
> =GVSN
> -----END PGP SIGNATURE-----
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: users-help@tomcat.apache.org
>
>


-- 
*Austin Jones*
Senior Designer

*(619) 819-8844 x1040 Office*
*(619) 819-8840 Fax*
*(619) 977-0927 Mobile*


*3131 Camino Del Rio North, Suite 1500San Diego, CA 92108*

 [image: Avadyne Health]

http://www.avadynehealth.com

Benchmark Revenue Management has merged with Avadyne Health! Visit our
website to learn more about this exciting synthesis, bringing
technology-enabled services to healthcare revenue cycle management.

*CONFIDENTIALITY NOTICE: This e-mail communication, including any
attachments, is covered by the Electronic Communication Privacy Act of 1986
(18 U.S.C. sections 2510-21) and may contain information protected by the
federal regulations under the Health Insurance Portability and
Accountability Act of 1996 (45 C. F. R. Parts 160-164) or other
confidential information. If you are not the intended recipient (or
authorized to receive for the recipient), you are hereby notified that any
review, disclosure, dissemination, distribution or copying of this
communication is strictly prohibited. If you have received this
communication in error, please delete or destroy all copies of this
communication and any attachments.*

Re: ClassNotFoundError on context unload

Posted by Christopher Schultz <ch...@christopherschultz.net>.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

Austin,

On 3/21/15 6:19 PM, Austin Jones wrote:
> I'm having an issue with Tomcat 8.0.12 when undeploying contexts.
> I have autoDeploy turned off, and am pushing WARs+context.xmls
> through the Tomcat manager's deploy command.
> 
> I have several ServletContextListeners that handle proper context 
> shutdown.  The ones that cause the issue look like this:
> 
> @Override public synchronized void contextInitialized(
> ServletContextEvent event ) { if( enabled ) { 
> MyClass.initialize(); } }
> 
> @Override public synchronized void contextDestroyed(
> ServletContextEvent event ) { MyClass.release(); }
> 
> If the 'enabled' flag is not set, and MyClass was not loaded
> anywhere else in the app, the webapp ClassLoader tries to load the
> class while the context is shutting down.  It throws this
> exception: java.lang.NoClassDefFoundError: some/package/MyClass at 
> some.package.MyListener.contextDestroyed(SingletonCleaner.java:na) 
> at 
> org.apache.catalina.core.StandardContext.listenerStop(StandardContext.java:4792)
>
> 
at
> org.apache.catalina.core.StandardContext.stopInternal(StandardContext.java:5392)
>
> 
at
> org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:232)
>
> 
at
> org.apache.catalina.core.StandardContext.reload(StandardContext.java:3768)
>
> 
at
> org.apache.catalina.startup.HostConfig.reload(HostConfig.java:1306)
>
> 
at
> org.apache.catalina.startup.HostConfig.checkResources(HostConfig.java:1238)
>
> 
at
> org.apache.catalina.startup.HostConfig.check(HostConfig.java:1493) 
> at sun.reflect.GeneratedMethodAccessor574.invoke(Unknown Source) 
> at 
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
>
> 
at java.lang.reflect.Method.invoke(Method.java:483)
> at 
> org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:300)
>
> 
at
> com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
>
> 
- --
> Caused by: java.lang.ClassNotFoundException: some.package.MyClass 
> at 
> org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1320)
>
> 
at
> org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1173)
>
> 
... 45 more
> 
> I set WebappClassLoader logging levels to FINE, and got this
> output: 21-Mar-2015 14:59:46.493 FINE [localhost-startStop-1] 
> org.apache.catalina.loader.WebappClassLoader.loadClass 
> loadClass(some.package.MyClass, false) 21-Mar-2015 14:59:46.493
> FINE [localhost-startStop-1] 
> org.apache.catalina.loader.WebappClassLoader.findClass 
> findClass(some.package.MyClass)
> 
> Any ideas why the class loader is throwing the errors?

Could you try again with the latest 8.0.20? There was a change in
8.0.18 that /might/ impact your situation:
https://bz.apache.org/bugzilla/show_bug.cgi?id=57446

- -chris
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1
Comment: GPGTools - http://gpgtools.org

iQIcBAEBCAAGBQJVDxTQAAoJEBzwKT+lPKRYG3UP/1WvGcySKDtqMZMoTVH5H3mW
EHZiaZubtiaReAxw6z11yLijMU2TI8a7mwYz5fi34M7AQ7nke3R9Mm3p3oojfJY6
jLVSTfe2fKYAK5rAdCNnuY2K/VVtpGR+q/KYLbsPkuIQYclamHtGbFuFxmUMm73O
NQ0QdXreyPQrdeoY8sNz01Dx8nAgI+3YNAbv1TKSbXbh4qfLnoLNePBoqfu0azqC
B0/rNw6ovzYcPo9BYplwK23BjxDa+P9F7wOxxSk8nf3tEpksnRC2EsUNL9kbGtDx
TV/7xl8Ln3DpONzETGCLbrf5W6Cj1MkAiSBk5iOmbTQdCvetpQNB5D57ZLBiFMy7
CEQrpWK9rQhmklmElxsmO0UvU/BLPoUtbv5BbJNnm3cYVgChgRrSpVVDtv8l33iF
dAQCTXqtyHl46tR7lbkoeNO9/YHtJJQ93Rmw3wF+UlloXi7pRjJE1NHEbbzllUIj
ddE8eqjP20ZkOrNa0I6vuk8Z6Tkf4aqIkvjMtnfyMb+9lImF33Y4PWsLRO8rvUmS
CgNWebKGfNVoHrMJpSh/BOf1mkKkTE38hBUyRSZ66VMbTS0mAMr5nqnNfrKTm5b/
nr9K0rcvusvs9sQyjBNEMg761ZGWcPGYWtQZNnyMHL5KmI4NF8OeSSlUO8V1Yvv7
At0sF5VE58lDPP/VTDts
=GVSN
-----END PGP SIGNATURE-----

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org