dev@glassfish.java.net

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

From: Sivakumar Thyagarajan <Sivakumar.Thyagarajan_at_Sun.COM>
Date: Tue, 08 May 2007 21:39:15 +0530

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.
>