From user-return-4729-apmail-geronimo-user-archive=geronimo.apache.org@geronimo.apache.org Thu Sep 14 23:04:14 2006 Return-Path: Delivered-To: apmail-geronimo-user-archive@www.apache.org Received: (qmail 42882 invoked from network); 14 Sep 2006 23:04:14 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur.apache.org with SMTP; 14 Sep 2006 23:04:14 -0000 Received: (qmail 33609 invoked by uid 500); 14 Sep 2006 23:04:08 -0000 Delivered-To: apmail-geronimo-user-archive@geronimo.apache.org Received: (qmail 33588 invoked by uid 500); 14 Sep 2006 23:04:08 -0000 Mailing-List: contact user-help@geronimo.apache.org; run by ezmlm Precedence: bulk list-help: list-unsubscribe: List-Post: Reply-To: user@geronimo.apache.org List-Id: Delivered-To: mailing list user@geronimo.apache.org Delivered-To: moderator for user@geronimo.apache.org Received: (qmail 9376 invoked by uid 99); 14 Sep 2006 22:44:27 -0000 X-ASF-Spam-Status: No, hits=0.5 required=10.0 tests=DNS_FROM_RFC_ABUSE,HTML_MESSAGE,SPF_PASS X-Spam-Check-By: apache.org Received-SPF: pass (hermes.apache.org: domain of shan.karthic@gmail.com designates 66.249.92.170 as permitted sender) DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=beta; d=gmail.com; h=received:message-id:date:from:to:subject:mime-version:content-type; b=TZu/VhiRZyfIWV+30VW7hjS9LKO/+/Rs4aBJl97erpJLk0uH82Wy/7JbSuwgFS+RhL3Li8Zvz0u4u7NGDMKlB0VQSjLss7ddzi8sV4InRFOE1RyUMIVFUkJZjdd5oSrv+XsYPNV/QIDO3P4OLMa6TzmIay3yNweC/cP0Lw9cS6s= Message-ID: Date: Thu, 14 Sep 2006 18:43:04 -0400 From: "Shan Karthic" To: user@geronimo.apache.org Subject: Re: Classloader Hierarchy and hidden-classes MIME-Version: 1.0 Content-Type: multipart/alternative; boundary="----=_Part_112966_6159803.1158273784993" X-Virus-Checked: Checked by ClamAV on apache.org X-Spam-Rating: minotaur.apache.org 1.6.2 0/1000/N ------=_Part_112966_6159803.1158273784993 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Content-Disposition: inline >> David Jencks wrote: >> >> I'm getting confused by your description, and looking at the code in >> trunk what I think you're saying doesn't look too likely... so I'm >> pretty sure I'm confused about something here and misunderstanding >> what you are saying. I regret that I was not clear about the problem. >> Could you outline what you are seeing in terms of a class org.foo.X >> that is present in 3 classloaders: >> cl1 >> parent of >> cl2 >> parent of >> cl3 >> where cl2 or cl3 has org.foo in hidden classes and either cl2 or cl3 >> or maybe both have inverse classloading turned on? >> Seems like maybe we need some test cases to make sure what we think >> is happening, is actually happening. The hidden-classes fragement is org.apache.commons.logging org.apache.log4j org.apache.geronimo.kernel.log 1) If I have org.foo hidden from cl2 (EAR/app level classloader) and not from cl3 (WAR classloader) and no inverse-classloading, the org.foo classes loaded by cl1 or above are visible to the application. Following is what I get, if I have the above hidden-classes specified in geronimo-application.xml and not in geronimo-web.xml. AppLogManager is a singleton in an utility jar in the application and is accessed from other utilities, EJBs and WAR in the application. In this case, I am instantiating it from the controller servlet and accessing it. The code segment that prints the messages shown below is Class l_clsClass = ...; // ClassLoader l_clrLoader = l_clsClass.getClassLoader(); int i = 0; System.out.println("###" + l_clsClass.getName() + "###"); while (l_clrLoader != null) { System.out.println("\t\t\tClass loader @ " + i + " is " + l_clrLoader); if (l_clrLoader.getParent() != null && l_clrLoader.equals(l_clrLoader.getParent())) { break; } l_clrLoader = l_clrLoader.getParent(); ++i; } I am printing this trace from a method inside AppLogManager. Class is first set to getClass(), and then m_lfyFactory.getClass() (where m_lfyFactory is declared to be of type commons-logging LogFactory and is initialized with LogFactory.getFactory(), and then m_lfyFactory.getInstance(...) which returns an object of type commons-logging Log. ###com.foo.bar.logging.AppLogManager### Class loader @ 0 is [ org.apache.geronimo.kernel.classloader.JarFileClassLoaderid=default/App/1158265787982/car] Class loader @ 1 is sun.misc.Launcher$AppClassLoader@e80a59 Class loader @ 2 is sun.misc.Launcher$ExtClassLoader@9f2a0b ###org.apache.geronimo.kernel.log.GeronimoLogFactory### Class loader @ 0 is sun.misc.Launcher$AppClassLoader@e80a59 Class loader @ 1 is sun.misc.Launcher$ExtClassLoader@9f2a0b ###org.apache.geronimo.kernel.log.GeronimoLog### Class loader @ 0 is sun.misc.Launcher$AppClassLoader@e80a59 Class loader @ 1 is sun.misc.Launcher$ExtClassLoader@9f2a0b As you can see, the application sees classes from org.apache.geronimo.kernel.log loaded by the server. 2) When I had org.foo hidden from both cl2 (EAR/app level classloader) and cl3 (WAR classloader) and no inverse-classloading, there used to be a mixup between classes loaded by cl2 and cl3. I am no longer able to reproduce it. I have to retrace all my tries over the last couple of days to see what I had done to get that. Most probably I messed up the classpath while trying various combinations. Currently the behaviour is similar to 1. Earlier, I used to have messages that said log4j.Appender was loaded by EAR/app classloader while log4j.DailyRollingFileAppender was loaded by WAR classloader. 3) If I have org.foo hidden from both cl2 (EAR/app level classloader) and cl3 (WAR classloader) and inverse class loading at WAR level, then all the classes are loaded at WAR level and logging works the way I want it. ###com.foo.bar.logging.AppLogManager### Class loader @ 0 is [ org.apache.geronimo.kernel.classloader.JarFileClassLoaderid=default/App_AppWeb.war/1158272840771/car] Class loader @ 1 is sun.misc.Launcher$AppClassLoader@e80a59 Class loader @ 2 is sun.misc.Launcher$ExtClassLoader@9f2a0b ###org.apache.commons.logging.impl.LogFactoryImpl### Class loader @ 0 is [ org.apache.geronimo.kernel.classloader.JarFileClassLoaderid=default/App_AppWeb.war/1158272840771/car] Class loader @ 1 is sun.misc.Launcher$AppClassLoader@e80a59 Class loader @ 2 is sun.misc.Launcher$ExtClassLoader@9f2a0b ###org.apache.commons.logging.impl.Log4JLogger### Class loader @ 0 is [ org.apache.geronimo.kernel.classloader.JarFileClassLoaderid=default/App_AppWeb.war/1158272840771/car] Class loader @ 1 is sun.misc.Launcher$AppClassLoader@e80a59 Class loader @ 2 is sun.misc.Launcher$ExtClassLoader@9f2a0b But other utilities at EAR level/EJBs will not see these and will load their own and the class in the utility is no longer a singleton at application level. I am also forced to keep multiple copies of property files at EAR and WAR levels or keep them inside the JAR (which makes it necessary to rebuild the JAR if I want to change some config or property). Is there a way around this? Thanks, Shankar. ------=_Part_112966_6159803.1158273784993 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Content-Disposition: inline
>>  David Jencks wrote:
>>
>> I'm getting confused by your description, and looking at the code in
>> trunk what I think you're saying doesn't look too likely... so I'm
>> pretty sure I'm confused about something here and misunderstanding

>> what you are saying.
I regret that I was not clear about the problem.
>>  Could you outline what you are seeing in terms of a class 
org.foo.X
>> that is present in 3 classloaders:

>> cl1
>> parent of
>> cl2
>> parent of
>> cl3

>> where cl2 or cl3 has org.foo in hidden classes and either cl2 or cl3

>> or maybe both have inverse classloading turned on?

>> Seems like maybe we need some test cases to make sure what we think
>> is happening, is actually happening.
The hidden-classes fragement is
        <sys:hidden-classes>
          <sys:filter> org.apache.commons.logging</sys:filter>
          <sys:filter>org.apache.log4j</sys:filter>
          <sys:filter>org.apache.geronimo.kernel.log</sys:filter>
        </sys:hidden-classes>

1) If I have org.foo hidden from cl2 (EAR/app level classloader) and not from cl3 (WAR classloader) and no inverse-classloading, the org.foo classes loaded by cl1 or above are visible to the application.

Following is what I get, if I have the above hidden-classes specified in geronimo-application.xml and not in geronimo-web.xml.  AppLogManager is a singleton in an utility jar in the application and is accessed from other utilities, EJBs and WAR in the application.  In this case, I am instantiating it from the controller servlet and accessing it.

The code segment that prints the messages shown below is
        Class l_clsClass = ...; //
        ClassLoader l_clrLoader = l_clsClass.getClassLoader();
        int i = 0;

        System.out.println ("###" + l_clsClass.getName() + "###");
        while (l_clrLoader != null) {
            System.out.println("\t\t\tClass loader @ " + i + " is " + l_clrLoader);
            if (l_clrLoader.getParent() != null && l_clrLoader.equals(l_clrLoader.getParent())) {
                break;
            }
            l_clrLoader = l_clrLoader.getParent();
            ++i;
        }

I am printing this trace from a method inside AppLogManager.  Class is first set to getClass(), and then m_lfyFactory.getClass() (where m_lfyFactory is declared to be of type commons-logging LogFactory and is initialized with LogFactory.getFactory(), and then m_lfyFactory.getInstance(...) which returns an object of type commons-logging Log.

    ###com.foo.bar.logging.AppLogManager###
                            Class loader @ 0 is [org.apache.geronimo.kernel.classloader.JarFileClassLoader id=default/App/1158265787982/car]
                            Class loader @ 1 is sun.misc.Launcher$AppClassLoader@e80a59
                            Class loader @ 2 is sun.misc.Launcher$ExtClassLoader@9f2a0b
    ###org.apache.geronimo.kernel.log.GeronimoLogFactory###
                            Class loader @ 0 is sun.misc.Launcher$AppClassLoader@e80a59
                            Class loader @ 1 is sun.misc.Launcher$ExtClassLoader@9f2a0b
    ###org.apache.geronimo.kernel.log.GeronimoLog###
                            Class loader @ 0 is sun.misc.Launcher$AppClassLoader@e80a59
                            Class loader @ 1 is sun.misc.Launcher$ExtClassLoader@9f2a0b

As you can see, the application sees classes from org.apache.geronimo.kernel.log loaded by the server.

2) When I had org.foo hidden from both cl2 (EAR/app level classloader) and cl3 (WAR classloader) and no inverse-classloading, there used to be a mixup between classes loaded by cl2 and cl3.  I am no longer able to reproduce it.  I have to retrace all my tries over the last couple of days to see what I had done to get that.  Most probably I messed up the classpath while trying various combinations.

Currently the behaviour is similar to 1.  Earlier, I used to have messages that said log4j.Appender was loaded by EAR/app classloader while log4j.DailyRollingFileAppender was loaded by WAR classloader.

3) If I have org.foo hidden from both cl2 (EAR/app level classloader) and cl3 (WAR classloader) and inverse class loading at WAR level, then all the classes are loaded at WAR level and logging works the way I want it.

###com.foo.bar.logging.AppLogManager###
                        Class loader @ 0 is [org.apache.geronimo.kernel.classloader.JarFileClassLoader id=default/App_AppWeb.war/1158272840771/car]
                        Class loader @ 1 is sun.misc.Launcher$AppClassLoader@e80a59
                        Class loader @ 2 is sun.misc.Launcher$ExtClassLoader@9f2a0b
###org.apache.commons.logging.impl.LogFactoryImpl###
                        Class loader @ 0 is [org.apache.geronimo.kernel.classloader.JarFileClassLoader id=default/App_AppWeb.war/1158272840771/car]
                        Class loader @ 1 is sun.misc.Launcher$AppClassLoader@e80a59
                        Class loader @ 2 is sun.misc.Launcher$ExtClassLoader@9f2a0b
###org.apache.commons.logging.impl.Log4JLogger###
                        Class loader @ 0 is [org.apache.geronimo.kernel.classloader.JarFileClassLoader id=default/App_AppWeb.war/1158272840771/car]
                        Class loader @ 1 is sun.misc.Launcher$AppClassLoader@e80a59
                        Class loader @ 2 is sun.misc.Launcher$ExtClassLoader@9f2a0b

But other utilities at EAR level/EJBs will not see these and will load their own and the class in the utility is no longer a singleton at application level.  I am also forced to keep multiple copies of property files at EAR and WAR levels or keep them inside the JAR (which makes it necessary to rebuild the JAR if I want to change some config or property).

Is there a way around this?

Thanks,
Shankar.
------=_Part_112966_6159803.1158273784993--