Search code examples
javaclassloaderprofilerpayaraglassfish-5

class MyClass cannot be cast to class MyClass (MyClass is in unnamed module of loader org.glassfish.[...].WebappClassLoader@1)


Why this error sometimes in deploy phase appens in Glassfish / Payara application server? I can guess that the application server is trying to use two different classes of two different classloaders but is there a way to prevent it to do this behavior?

I tried to lookup some source online whitout finding nothing.

Edit : this happens on the same application in time of redeploy. It gets solved by a restart of the application server but obliviously this is not a solution

java.lang.ClassCastException: class com.MyClass cannot be cast to class com.MyClass (com.MyClass is in unnamed module of loader org.glassfish.web.loader.WebappClassLoader@1, com.MyClass is in unnamed module of loader org.glassfish.web.loader.WebappClassLoader@2)

Last Edit, after the great response of Stephen C. What are the tools to undestand why Payara/GC doesn't destroy the old object?


Solution

  • I can guess that the application server is trying to use two different classes of two different classloaders but is there a way to prevent it to do this behavior?

    Yes, that's what I think is happening. If identical .class files are loaded by different classloaders, the resulting runtime types are different and cannot by cast.

    There are three ways to avoid this:

    1. Don't pass or share these objects between different webapps.

    2. Move the JARs that define the classes that need to be shared into the web container's shared library area ... so that they are loaded by the webcontainer's classloader rather than the webapp classloader(s).

    3. If the classes need to be loaded by multiple webapp classloaders (e.g. because the have the same name but different implementations) you may need to rearchitect your application so that the classes implement a common interface that is loaded by a single classloader. If your webapp code then only casts to the shared interface, you won't run into this problem.


    What if the web app is the same? (so when the application redeploy the same app)

    If that is the case, then it sounds like the problem is that your webapp's shutdown code is not doing the right thing. Java objects created by the earlier deployment of the webapp are leaking into the later one.

    • Check that something is not caching application objects.
    • Check that application objects are not hiding in session state or thread-locals, or something like that.