Re: [aspectj-users] How to ensure AspectJ aspects are LTW'ed by Wildfly's modules?

2017-10-26 Thread Andy Clement
> I suspected that AJ just uses whatever classloader is provided to it.

Yes, exactly. Because we don’t want to get into tricks around classloaders. I 
am a bit rusty but I think for weaving a particular type you can see the entry 
point in the type Aj is driven every time something is loaded once you’ve 
registered the agent:

public byte[] preProcess(String className, byte[] bytes, ClassLoader 
loader, ProtectionDomain protectionDomain) {

This is invoked by the ClassFileTransformer 
(java.lang.instrument.ClassFileTransformer) implementation in AspectJ called 
ClassPreProcessorAgentAdapter

The class file transformer is passed the loader and the bytes for a particular 
class. From the loader we determine the weaver instance which gives us the 
context to weave the bytes.  If that loader does not provide visibility to 
something, the weaver instance for that loader will not be able to see it. In 
your case if it is this module loader, and it is not delegating class/resource 
lookups to a parent then AspectJ will not find anything outside the module.  
I’d suspect there is a way to have common modules but I’ve no idea how wildfly 
allows that.

> So given that the AJ Weaver doesn't find the classes, I figure that WF is 
> doing something with/to it. 

Yep, me too.

>  Do you know if there are any docs or whitepapers I can read up on how the 
> classloader/instrumentation cycle works?  I couldn't find enough clarity on 
> the Oracle site.

Search up ClassFileTransformer but honestly, I might be wrong, but I don’t 
think that has much to do with it here. It is entirely down to how visibility 
from that loader should be setup in wildfly.  Write some code that has nothing 
to do with aspects and don’t attach the agent. Something like this in your 
application:

 Class.forName(“some type from aspects.jar”,false, 
this.getClass().getClassLoader()); - can that access them? 

If it can what about:

this.getClass().getClassLoader().getResourceAsStream(…class file reference…) - 
can that see them too?

If those are true then AspectJ ought to be able to see them.

> I haven't tried posting on StackOverflow yet figuring that I would likely get 
> a more targeted response from here or the wildfly-dev forums. 

Folks like scoring points answering questions on stackoverflow - you might get 
a good answer :)

cheers,
Andy


> On Oct 26, 2017, at 2:23 PM, Eric B  wrote:
> 
> I did try with my aspect.jar on the bootclasspath with -Xbootclasspath/a (I 
> would be surprised if  /a or a /p would make a difference).  Didn't make any 
> difference.
> 
> I haven't tried posting on StackOverflow yet figuring that I would likely get 
> a more targeted response from here or the wildfly-dev forums.  But to date, 
> it's tough to reconcile information from the two independent camps. :)
> I suspected that AJ just uses whatever classloader is provided to it.  That's 
> kind of what it looked like to me.  But I couldn't/don't understand how the 
> Agent bootstraps though.  From what I can tell, its the base JVM's 
> classloader that calls the Agent premain, and instructs it to instrument the 
> classes.  In which case, I would expect any visibility of that classloader to 
> extend to AJ as well.
> 
> So given that the AJ Weaver doesn't find the classes, I figure that WF is 
> doing something with/to it.  But in that case, I dont understand at all how 
> the JVM's instrumentation works; I guess I'm confused where in the cycle the 
> instrumentation is called when loading classes.  Do you know if there are any 
> docs or whitepapers I can read up on how the classloader/instrumentation 
> cycle works?  I couldn't find enough clarity on the Oracle site.
> 
> Thanks,
> 
> Eric
> 
> On Thu, Oct 26, 2017 at 3:07 PM, Andy Clement  > wrote:
> Did you try your aspect jar on the bootclasspath ? (Just wondering if that 
> might help).
> 
> AspectJ deliberately avoids getting involved in class loader shenanigans 
> because it gets too complicated, hence relying on the delegation model in 
> place for the system it is being used with.  However you make a ‘common jar’ 
> available to all the individual module loaders in wildfly should work for 
> AspectJ, unless they are handling delegation for classes differently to 
> delegation for resource access. I don’t feel this is a new problem though, I 
> feel it has come up again and again over the years - surely somebody solved 
> it by now Did you try stack overflow? Sorry i don’t have any concrete 
> answers.
>  
> cheers,
> Andy
> 
> 
>> On Oct 26, 2017, at 11:37 AM, Eric B > > wrote:
>> 
>> Thanks for the info.  I've been digging through AJ and WF code some more to 
>> try to figure this out, but am still not sure how the classloader is 
>> working.  I'm starting Wildfly using the following arguments:
>> 
>> 

Re: [aspectj-users] How to ensure AspectJ aspects are LTW'ed by Wildfly's modules?

2017-10-26 Thread Eric B
I did try with my aspect.jar on the bootclasspath with -Xbootclasspath/a (I
would be surprised if  /a or a /p would make a difference).  Didn't make
any difference.

I haven't tried posting on StackOverflow yet figuring that I would likely
get a more targeted response from here or the wildfly-dev forums.  But to
date, it's tough to reconcile information from the two independent camps. :)
I suspected that AJ just uses whatever classloader is provided to it.
That's kind of what it looked like to me.  But I couldn't/don't understand
how the Agent bootstraps though.  From what I can tell, its the base JVM's
classloader that calls the Agent premain, and instructs it to instrument
the classes.  In which case, I would expect any visibility of that
classloader to extend to AJ as well.

So given that the AJ Weaver doesn't find the classes, I figure that WF is
doing something with/to it.  But in that case, I dont understand at all how
the JVM's instrumentation works; I guess I'm confused where in the cycle
the instrumentation is called when loading classes.  Do you know if there
are any docs or whitepapers I can read up on how the
classloader/instrumentation cycle works?  I couldn't find enough clarity on
the Oracle site.

Thanks,

Eric

On Thu, Oct 26, 2017 at 3:07 PM, Andy Clement 
wrote:

> Did you try your aspect jar on the bootclasspath ? (Just wondering if that
> might help).
>
> AspectJ deliberately avoids getting involved in class loader shenanigans
> because it gets too complicated, hence relying on the delegation model in
> place for the system it is being used with.  However you make a ‘common
> jar’ available to all the individual module loaders in wildfly should work
> for AspectJ, unless they are handling delegation for classes differently to
> delegation for resource access. I don’t feel this is a new problem though,
> I feel it has come up again and again over the years - surely somebody
> solved it by now Did you try stack overflow? Sorry i don’t have any
> concrete answers.
>
> cheers,
> Andy
>
>
> On Oct 26, 2017, at 11:37 AM, Eric B  wrote:
>
> Thanks for the info.  I've been digging through AJ and WF code some more
> to try to figure this out, but am still not sure how the classloader is
> working.  I'm starting Wildfly using the following arguments:
>
> -Djboss.modules.system.pkgs=org.jboss.byteman,org.aspectj,te
> st.aspectj,org.jboss.logmanager
> -javaagent:c:/dev/tmp/jboss-eap-7.0.0/modules/system/layers/
> base/org/aspectj/main/aspectjweaver-1.8.10.jar
> -Dorg.aspectj.weaver.showWeaveInfo=true"
> -Dorg.aspectj.weaver.loadtime.configuration=file:c:/tmp/poc/aop.xml
> -cp C:/dev/Projects/jms/mixed-arch/ear-app/aspectj/target/aspect
> j-0.0.1-SNAPSHOT.jar
>
>
> So in it, I've defined an additional classpath pointing to my aspectj.jar
> file.  My /tmp/poc/aop.xml contains the aspect definition of "
> test.aspectj.TestAspect".
> I can now see that the AJ agent is looking for test.aspectj.TestAspect
> class.  But it still isn't able to find it; I get the following errors
> thrown my the AspectJ Weaver:
>
> 2017-10-26 12:11:39,889 ERROR [stderr] (MSC service thread 1-7)
> [ModuleClassLoader@336f62a1] info register aspect test.aspectj.TestAspect
> 2017-10-26 12:11:54,632 ERROR [stderr] (MSC service thread 1-7)
> [ModuleClassLoader@336f62a1] error The specified aspect
> 'test.aspectj.TestAspect' cannot be found
>
> I've confirmed that my class (test.aspectj.TestAspect) is indeed in the
> aspectj-0.0.1-SNAPSHOT.jar.
>
> So I get the impression that the aspectj-SNAPSHOT jar is not being made
> visible to the individual module classloaders.  I've tried to debug the
> weaver, and can see that it does indeed do the following:
>
> private URL toURL(String className) {
> URL url = (URL) nameMap.get(className);
> if (url == null) {
> String classFile = className.replace('.', '/');
> url = loaderRef.getClassLoader().getResource(classFile + ".class");
> nameMap.put(className, url);
> }
> return url;
> }
>
> where the loaderRef.getClassLoader() looks like it is the classloader that
> is passed to the ClassFileTransformer.transform() method (
> https://docs.oracle.com/javase/7/docs/api/java/lang/instrum
> ent/ClassFileTransformer.html).  But I'm not sure where/how to continue
> digging from here.  Which classloader is this?  Is this the base java
> classloader?  If Wildfly defines its own classloader (not sure if it does),
> will it be used instead?  On the other hand, if the base java classloader
> is passed, why is the classloader not able to find my
> test.aspectj.TestAspect class if it is in the jar that is part of my -cp
> arguments?
>
>
> Thanks,
>
> Eric
>
> On Mon, Oct 23, 2017 at 1:45 PM, Andy Clement 
> wrote:
>
>> Yes, it is a bit specific to wildfly but I can talk to what AspectJ
>> does.  I will also call out to an old article I wrote on debugging LTW:
>> 

Re: [aspectj-users] How to ensure AspectJ aspects are LTW'ed by Wildfly's modules?

2017-10-26 Thread Eric B
Thanks for the info.  I've been digging through AJ and WF code some more to
try to figure this out, but am still not sure how the classloader is
working.  I'm starting Wildfly using the following arguments:

-Djboss.modules.system.pkgs=org.jboss.byteman,org.aspectj,te
st.aspectj,org.jboss.logmanager
-javaagent:c:/dev/tmp/jboss-eap-7.0.0/modules/system/layers/
base/org/aspectj/main/aspectjweaver-1.8.10.jar
-Dorg.aspectj.weaver.showWeaveInfo=true"
-Dorg.aspectj.weaver.loadtime.configuration=file:c:/tmp/poc/aop.xml
-cp C:/dev/Projects/jms/mixed-arch/ear-app/aspectj/target/aspect
j-0.0.1-SNAPSHOT.jar


So in it, I've defined an additional classpath pointing to my aspectj.jar
file.  My /tmp/poc/aop.xml contains the aspect definition of "
test.aspectj.TestAspect".
I can now see that the AJ agent is looking for test.aspectj.TestAspect
class.  But it still isn't able to find it; I get the following errors
thrown my the AspectJ Weaver:

2017-10-26 12:11:39,889 ERROR [stderr] (MSC service thread 1-7)
[ModuleClassLoader@336f62a1] info register aspect test.aspectj.TestAspect
2017-10-26 12:11:54,632 ERROR [stderr] (MSC service thread 1-7)
[ModuleClassLoader@336f62a1] error The specified aspect
'test.aspectj.TestAspect' cannot be found

I've confirmed that my class (test.aspectj.TestAspect) is indeed in the
aspectj-0.0.1-SNAPSHOT.jar.

So I get the impression that the aspectj-SNAPSHOT jar is not being made
visible to the individual module classloaders.  I've tried to debug the
weaver, and can see that it does indeed do the following:

private URL toURL(String className) {
URL url = (URL) nameMap.get(className);
if (url == null) {
String classFile = className.replace('.', '/');
url = loaderRef.getClassLoader().getResource(classFile + ".class");
nameMap.put(className, url);
}
return url;
}

where the loaderRef.getClassLoader() looks like it is the classloader that
is passed to the ClassFileTransformer.transform() method (
https://docs.oracle.com/javase/7/docs/api/java/lang/instrum
ent/ClassFileTransformer.html).  But I'm not sure where/how to continue
digging from here.  Which classloader is this?  Is this the base java
classloader?  If Wildfly defines its own classloader (not sure if it does),
will it be used instead?  On the other hand, if the base java classloader
is passed, why is the classloader not able to find my
test.aspectj.TestAspect class if it is in the jar that is part of my -cp
arguments?


Thanks,

Eric

On Mon, Oct 23, 2017 at 1:45 PM, Andy Clement 
wrote:

> Yes, it is a bit specific to wildfly but I can talk to what AspectJ does.
> I will also call out to an old article I wrote on debugging LTW:
> http://andrewclement.blogspot.ca/2009/02/load-time-weaving-basics.html (might
> be useful).
>
> In the source for ClassLoaderWeavingAdaptor you will see three options for
> files we look for:
>
> META-INF/aop.xml  — the regular one
> META-INF/aop-ajc.xml — another option, useful in case you are using
> -outxml to generate the XML and don’t want to damage some user config you
> are maintaining (keep user stuff in aop-ajc.xml)
> org/aspectj/aop.xml — for OSGi usage but not specific to OSGi, can be used
> in other scenarios.
>
> Also in the same class you’ll see:
>
> *private* *final* *static* String *AOP_XML* = Constants.*AOP_USER_XML* +
> ";" + Constants.*AOP_AJC_XML* + ";" + Constants.*AOP_OSGI_XML*;
> String resourcePath = System.getProperty("org.aspectj.weaver.loadtime.
> configuration", *AOP_XML*);
>
> So you can override those 3 places and give it the path to something else
> if you want to by specifying that property. If the thing you provide starts
> with file then it will actually load direct from there:
>
> *if* (nextDefinition.startsWith("file:")) {
> *try* {
> String fpath = *new* URL(nextDefinition).getFile();
> File configFile = *new* File(fpath);
>
> If you just run default then it will be making calls to getClassLoader().
> getResources(name); for those three variants above. So you are at the
> mercy of whatever the class loader is allowing you to see.
>
> cheers,
> Andy
>
> On Oct 21, 2017, at 7:19 PM, Eric B  wrote:
>
> So this is probably more of a Wildfly question than an AspectJ question as
> such, and I have already asked the Wildfly team about it, but I thought I
> would try to get additional clarity from the AJ pros to understand exactly
> how the LTW agent works.
>
> My use case is that I want to use use AspectJ to advise some core classes
> in Wildfly/undertow.  Specifically, I'm trying to advise some of the
> Undertow HttpSession methods to get some more detailed logging when
> Sessions are created/expire/etc.
>
> To that extent, I've added AspectJ as a -javaagent which is launched on
> startup of Wildfly.  I had to follow some of the steps listed at:
> https://github.com/ChienChingLee/How-to-launch-
> Wildfly-9.0-with-AspectJ-1.8-LTW.  But it works; I can see that the AJ
> weaver is loaded and present.
>
> My problem now has to do with