dev@glassfish.java.net

Re: ClassNotFoundException for webapps loading classes by System CL specified via "-javaagent:" jvm-option (e.g. AspectJ LTW app)

From: Max Poon <maxpoon_at_dev.java.net>
Date: Thu, 10 May 2007 17:13:18 +0800

Thanks Siva!

Hi Jie, appreciate your comments/advice.

Thanks again
Max

Sivakumar Thyagarajan wrote:
> Hi Max
>
> Thanks for the suggestion below. It does appear fine, however I am not
> an expert in this area. Jie Leng [copied] handles logging and so, Jie
> might be able to help us here.
>
> Thanks
> --Siva.
>
> Max Poon wrote:
>> Hi Sivakumar
>>
>> I just revisit the enclosed issue and think that we can consider the
>> following :-
>>
>> (1) GlassFish starts up with something like :
>>
>> "-Dcom.sun.enterprise.server.logging.manager=com.sun.enterprise.server.logging.ServerLogManager"
>>
>> instead of
>>
>> "-Djava.util.logging.manager=com.sun.enterprise.server.logging.ServerLogManager"
>>
>>
>> (2) GlassFish tries loading what is referenced by
>> "com.sun.enterprise.server.logging.manager", if successful, use it as
>> "java.util.logging.manager"
>>
>> try { cname =
>> System.getProperty("com.sun.enterprise.server.logging.manager");
>> if (cname != null) { Class clz =
>> ClassLoader.getSystemClassLoader().loadClass(cname); manager =
>> (LogManager) clz.newInstance(); } } catch (Exception ex) {
>> System.err.println("Could not load Logmanager \"" + cname +
>> "\""); ex.printStackTrace(); } if (manager == null) {
>> manager = new LogManager(); }
>> So that
>>
>> (a) any application (e.g. AspectJ weaver applications) loaded in
>> System CL (without any visibility to GlassFish's classes) can still
>> use JDK Logging with its own designated LogManager
>>
>> (b) GlassFish can use its own
>> com.sun.enterprise.server.logging.ServerLogManager
>>
>> I guess this involves minimal code changes to GlassFish while solving
>> the enclosed problem we have.
>>
>> What do you think? Which GlassFish sources are needed to be changed?
>>
>> Thanks
>> Max
>>
>>
>> Max Poon wrote:
>>> Hi Sivakumar
>>>
>>> Thanks for your input! I've got it "working" by :
>>>
>>> 1. specifying in domain.xml the <java-config> <jvm-option>
>>>
>>> "-Dorg.aspectj.tracing.factory=org.aspectj.weaver.tools.CommonsTraceFactory"
>>>
>>> - to tell aspectjweaver.jar (loaded in GF's System Class Loader)
>>> to use commons logging instead of GF's default log manager
>>> com.sun.enterprise.server.logging.ServerLogManager which is
>>> loaded in GF's Shared Chain Class Loader and hence not
>>> accessible from GF's System ClassLoader (hence the previously
>>> observed ClassNotFoundException).
>>> 2. adding locations of commons-logging-1.1.jar and log4j-1.2.14.jar
>>> to GF's system classpath
>>> - so that Commons Logging can see Log4j before looking for and
>>> then using JDK1.4 Logging (which then tries to load
>>> com.sun.enterprise.server.logging.ServerLogManager and throws
>>> the ClassNotFoundException, as per testing)
>>>
>>> To summarise, as aspectjweaver.jar has to be specified via
>>> "-javaagent:" jvm option and loaded via System Class Loader, make
>>> the classes in aspectjweaver.jar access alternative logging
>>> accessible from the System Class Loader, instead of GF's default log
>>> manager com.sun.enterprise.server.logging.ServerLogManager.
>>>
>>> This approach may be applicable to other AspectJ applications (with
>>> classes required to be accessed directly by AspectJ's Load-Time
>>> Weaver) running on GlassFish, given that those classes are/can be
>>> packaged in known jar files to be included in GF's System Classpath.
>>>
>>> Not sure whether this is the best approach. Any better
>>> idea/solution/comment much welcome.
>>>
>>> Actually, I have been trying to have GlassBox Inspector running on
>>> GlassFish (v1 & v2), and would like to thank you as well as Ron
>>> Bodkin of GlassBox (cc'ed) for all the input and help.
>>>
>>> Thanks
>>> Max
>>>
>>>
>>> Sivakumar Thyagarajan wrote:
>>>> Hi Max
>>>>
>>>> Responses inline. Thanks.
>>>>
>>>> --Siva.
>>>>
>>>> Max Poon wrote:
>>>>> Hi Sivakumar
>>>>>
>>>>> Thanks! Some comments on your suggestions :
>>>>>
>>>>> 1) Putting required logger classes/jar in web app - This seems
>>>>> not helping as the problem is on accessing classes loaded by the
>>>>> children class loaders (CL) from the System CL (via "-javaagent:"
>>>>> jvm option), not from the Web CL or App CL. Kindly advise if I
>>>>> understand correctly.
>>>>
>>>> Probably I should have been a bit more clearer. I was suggesting
>>>> bundling the LogManager classes along with aspectjweaver.jar you
>>>> specify in the -javaagent option. That way the logManager would
>>>> also be loaded as part of the system classloader and AspectJ
>>>> runtime would be able to load the LogManager.
>>>>
>>>>>
>>>>> 2) I just notice : it seems that Application Class Loader (CL) is
>>>>> involved in the exception causing execution stack:
>>>>>
>>>>> Could not load Logmanager
>>>>> "com.sun.enterprise.server.logging.ServerLogManager"
>>>>> java.lang.ClassNotFoundException:
>>>>> com.sun.enterprise.server.logging.ServerLogManager
>>>>> ...
>>>>> at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
>>>>> at
>>>>> sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:276)
>>>>> at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
>>>>> ...
>>>>> at org.aspectj.weaver.loadtime.Agent.<clinit>(Agent.java:33)*
>>>>>
>>>>> Questions:
>>>>>
>>>>> (a) as the "-javaagent:<aspectjweaver.jar>" jvm option requires
>>>>> loading by System CL, why is AppCL involved?
>>>>
>>>> The name is probably a misnomer [or probably confusing in a J2EE
>>>> appserver context]. It is not ApplicationClassLoader [as in J2EE
>>>> application classloader] but sun.misc.Launcher$AppClassLoader. This
>>>> is the Sun JVM's representation of what is referred to as the
>>>> System classloader.
>>>>
>>>>>
>>>>> (b) if AppCL is used, then GlassFish should be able to load
>>>>> com.sun.enterprise.server.logging.ServerLogManager (in
>>>>> appserv-rt.jar) via delegating up to the Shared Chain CL per
>>>>> GlassFish default behavior. Then, why was the above exception
>>>>> thrown?
>>>>>
>>>>
>>>> Hope the explanation above helps. It is system classloader and so
>>>> the ServerLogManager is not visible to that classloader as it
>>>> loaded below in the hierarchy.
>>>>
>>>>
>>>>> Thanks again!
>>>>> Max
>>>>>
>>>>>
>>>>> Sivakumar Thyagarajan wrote:
>>>>>> Hi Max
>>>>>>
>>>>>> > _Questions
>>>>>> ..
>>>>>> >
>>>>>> > 1. how can we have the classes specified via *-javaagent:*
>>>>>> able to
>>>>>> > load those classes (e.g. in Shared Chain CL) available
>>>>>> lower down
>>>>>> > in the CL hierarchy (coz' it may not be feasible to put
>>>>>> everything
>>>>>> > in System CL) ?
>>>>>>
>>>>>> As you have mentioned already in your analysis, this is because
>>>>>> aspectjweaver loaded by the system classloader cannot see classes
>>>>>> loaded lower in the hierarchy such as the Logging Manager and
>>>>>> AFAIK there is no easy fix for this.
>>>>>>
>>>>>> No easy fix because the static block at
>>>>>> java.util.logging.LogManager tries to load using both the
>>>>>> SystemClassLoader and the Thread context classloader (which at
>>>>>> the time of initialization of the PreMain class is not set to a
>>>>>> classloader that can load the specified loggingmanager) and both
>>>>>> would not be able to load the loggingmanager.
>>>>>>
>>>>>> Unfortunately, while we did the earlier classloader changes in
>>>>>> GlassFish v1, we tried to move our logging manager
>>>>>> [com.sun.enterprise.server.logging.ServerLogManager] higher up in
>>>>>> the hierarchy [to be placed with appserv-launch.jar] but it had
>>>>>> dependencies on a whole lot of other appserv-rt.jar classes and
>>>>>> hence couldn't get this out.
>>>>>>
>>>>>> Possible Workarounds:
>>>>>> - I don't have the soruces for Aj/JDK14Trace. Is there a way to
>>>>>> disable AspectJWeaver logging? ie an option to not have this done
>>>>>> at all
>>>>>>> at java.util.logging.Logger.getLogger(Logger.java:274)
>>>>>>> at
>>>>>>> org.aspectj.weaver.tools.Jdk14Trace.<init>(Jdk14Trace.java:25)
>>>>>>> at
>>>>>>> org.aspectj.weaver.tools.Jdk14TraceFactory.getTrace(Jdk14TraceFactory.java:17)
>>>>>>>
>>>>>>> at org.aspectj.weaver.loadtime.Aj.<clinit>(Aj.java:32)
>>>>>> If yes, we could use that as a temproary workaround
>>>>>>
>>>>>> - AspectJ weaving using WeavingURLClassLoader.
>>>>>>
>>>>>> - use a custom server log Manager. I know this is not supported
>>>>>> but if the custom log manager is bundled with the aspectjweaver
>>>>>> class or specified in the system classpath this would help
>>>>>> aspectjweaver to continue to load.
>>>>>>
>>>>>> If none of these help, someone from the admin team could let us
>>>>>> know if it would be possible to separate out our LoggingManager,
>>>>>> so that this could be moved higher up in the classloader hierarchy.
>>>>>>
>>>>>> > 2. can we override *java.util.logging.manager* within
>>>>>> > context/execution of our web apps (vs that set during
>>>>>> glassfish
>>>>>> > initialisation) so it points to something available with
>>>>>> the web
>>>>>> > apps (e.g. apache commons logging, log4J, etc) ?
>>>>>>
>>>>>> For log4j style configuration for a web app, does this help?
>>>>>> https://glassfish.dev.java.net/servlets/ReadMsg?list=users&msgNo=590
>>>>>>
>>>>>> > Adding to domain.xml the jvm-option :
>>>>>> >
>>>>>> > * -Dcom.sun.aas.useNewClassLoader=false
>>>>>> >
>>>>>> > to try to disable the new Shared Chain Class Loader does not
>>>>>> seem to help.
>>>>>>
>>>>>> This was more of a internal temporary flag we introduced during
>>>>>> GlassFish v1 days. This may be broken. I shall check this. If
>>>>>> this is fixed, this would be a workaround as well :)
>>>>>>
>>>>>> Thanks
>>>>>> --Siva.
>>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe_at_glassfish.dev.java.net
> For additional commands, e-mail: dev-help_at_glassfish.dev.java.net
>
>