You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@aries.apache.org by David Bosschaert <da...@gmail.com> on 2011/12/14 12:13:30 UTC

Weaving Hook puzzle

Hi all,

A user was playing with the SPI-Fly stuff and hit an issue, which I
have trouble understanding how it should be fixed, maybe someone has
an idea here... It might be related to the interplay between the OSGi
weaving hook and ASM...

Here's the situation:
* They use some code that at some point uses
javax.sound.sampled.AudioSystem.getAudioFileReaders(). This code goes
through a few hoops and then ends up at sun.misc.Service.providers()
which is similar to java.util.ServiceLoader.load() in that it uses the
TCCL to read resources from META-INF/service (I think its a
sun-proprietary predecessor to ServiceLoader).
* Because in their code they use AudioSystem this is the piece that
can get woven to be surrounded by TCCL settings (by using the
SPI-Consumer: javax.sound.sampled.AudioSystem#getAudioInputStream and
SPI-Provider: javax.sound.sampled.AudioSystem headers).
* However, ASM complains:
java.lang.ClassNotFoundException: javax.sound.sampled.AudioInputStream
	at org.objectweb.asm.ClassWriter.getCommonSuperClass(Unknown Source)
	at org.objectweb.asm.ClassWriter.a(Unknown Source)
	at org.objectweb.asm.Frame.a(Unknown Source)
	at org.objectweb.asm.Frame.a(Unknown Source)
	at org.objectweb.asm.MethodWriter.visitMaxs(Unknown Source)
	at org.objectweb.asm.commons.LocalVariablesSorter.visitMaxs(Unknown Source)
	at org.objectweb.asm.ClassReader.accept(Unknown Source)
	at org.objectweb.asm.ClassReader.accept(Unknown Source)
	at org.apache.aries.spifly.dynamic.ClientWeavingHook.weave(ClientWeavingHook.java:60)
The relevant snippet of weaving hook code [1] is this:
  @Override
  public void weave(WovenClass wovenClass) {
  Bundle consumerBundle = wovenClass.getBundleWiring().getBundle();
  Set<WeavingData> wd = activator.getWeavingData(consumerBundle);
  if (wd != null) {
    activator.log(LogService.LOG_DEBUG, "Weaving class " +
wovenClass.getClassName());

    ClassReader cr = new ClassReader(wovenClass.getBytes());
    ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS |
ClassWriter.COMPUTE_FRAMES);
    TCCLSetterVisitor tsv = new TCCLSetterVisitor(cw,
wovenClass.getClassName(), wd);
    cr.accept(tsv, ClassReader.SKIP_FRAMES); // line 60
* The classloader associated with the BundleRevision does have
visibility to AudioInputStream, I did this while debugging in Eclipse:
    Evaluate: wovenClass.getBundleWiring().getClassLoader().loadClass("javax.sound.sampled.AudioSystem")
	 (java.lang.Class<T>) class javax.sound.sampled.AudioSystem
* The bundle being woven does import javax.sound.sampled

Anyone an idea what could be the issue here? Funny enough I can get
this to work in eclipse's 'dev' mode (a framework launched from within
eclipse), but I think that's because it seeminly implicitly imports
javax.* into all bundles... If I use Felix or Equinox standalone it
fails this way.

Any ideas?

Many thanks,

David

[1] https://svn.apache.org/repos/asf/aries/trunk/spi-fly/spi-fly-dynamic-bundle/src/main/java/org/apache/aries/spifly/dynamic/ClientWeavingHook.java

Re: Weaving Hook puzzle

Posted by Łukasz Dywicki <lu...@code-house.org>.
Hey,
Few weeks ago I started implementing an experimental AspectJ weaving hook which would be compatible with OSGi 4.3. So far I stuck with aspects and calling the aspect weaver, but I would be interested in workin on this too.

Best regards,
Lukasz

> On 16 December 2011 10:39, Timothy Ward <ti...@apache.org> wrote:
>> It might be something to look at putting into a util bundle for weaving,  though probably not the existing util bundle because it would add an ASM dependency.
> 
> Yes, apart from an exception local to the Proxy module I could reuse
> the code as is, so this makes sense!
> I think it's more than 'just a util'. It's a module to make ASM work
> with OSGi 4.3 WeavingHooks, I can see uses cases outside of Aries for
> it too...
> 
> Cheers,
> 
> David


Re: Weaving Hook puzzle

Posted by David Bosschaert <da...@gmail.com>.
On 16 December 2011 10:39, Timothy Ward <ti...@apache.org> wrote:
> It might be something to look at putting into a util bundle for weaving,  though probably not the existing util bundle because it would add an ASM dependency.

Yes, apart from an exception local to the Proxy module I could reuse
the code as is, so this makes sense!
I think it's more than 'just a util'. It's a module to make ASM work
with OSGi 4.3 WeavingHooks, I can see uses cases outside of Aries for
it too...

Cheers,

David

RE: Weaving Hook puzzle

Posted by Timothy Ward <ti...@apache.org>.
I'm glad it works - I remember bumping into this one for the first time when first delivering the proxy code. It only happened in some obscure classes inside Derby, and it took quite a while to work out how to fix it!

It might be something to look at putting into a util bundle for weaving,  though probably not the existing util bundle because it would add an ASM dependency.

Regards

Tim Ward
-------------------
Apache Aries PMC member & Enterprise OSGi advocate
Enterprise OSGi in Action (http://www.manning.com/cummins)
-------------------


> From: david.bosschaert@gmail.com
> Date: Fri, 16 Dec 2011 09:42:14 +0000
> Subject: Re: Weaving Hook puzzle
> To: dev@aries.apache.org
> 
> Many thanks, Tim. That worked just fine!
> 
> David
> 
> On 14 December 2011 14:28, Timothy Ward <ti...@apache.org> wrote:
> >
> > Hi David,
> >
> > This is a known issue with ASM in OSGi. We override ClassWriter in the proxy code to get around this (as recommended by the ASM doc). See the following for details:
> >
> >  \proxy\proxy-impl\src\main\java\org\apache\aries\proxy\impl\common\OSGiFriendlyClassWriter.java in
> >
> > You can override this method to work even when the class isn't loadable from the ClassLoader that ASM is trying to use (or simply make sure that ASM is using the right classloader in the first place).
> >
> > Regards,
> >
> > Tim Ward
> > -------------------
> > Apache Aries PMC member & Enterprise OSGi advocate
> > Enterprise OSGi in Action (http://www.manning.com/cummins)
> > -------------------
> >
> >
> >> From: david.bosschaert@gmail.com
> >> Date: Wed, 14 Dec 2011 11:13:30 +0000
> >> Subject: Weaving Hook puzzle
> >> To: dev@aries.apache.org
> >>
> >> Hi all,
> >>
> >> A user was playing with the SPI-Fly stuff and hit an issue, which I
> >> have trouble understanding how it should be fixed, maybe someone has
> >> an idea here... It might be related to the interplay between the OSGi
> >> weaving hook and ASM...
> >>
> >> Here's the situation:
> >> * They use some code that at some point uses
> >> javax.sound.sampled.AudioSystem.getAudioFileReaders(). This code goes
> >> through a few hoops and then ends up at sun.misc.Service.providers()
> >> which is similar to java.util.ServiceLoader.load() in that it uses the
> >> TCCL to read resources from META-INF/service (I think its a
> >> sun-proprietary predecessor to ServiceLoader).
> >> * Because in their code they use AudioSystem this is the piece that
> >> can get woven to be surrounded by TCCL settings (by using the
> >> SPI-Consumer: javax.sound.sampled.AudioSystem#getAudioInputStream and
> >> SPI-Provider: javax.sound.sampled.AudioSystem headers).
> >> * However, ASM complains:
> >> java.lang.ClassNotFoundException: javax.sound.sampled.AudioInputStream
> >>       at org.objectweb.asm.ClassWriter.getCommonSuperClass(Unknown Source)
> >>       at org.objectweb.asm.ClassWriter.a(Unknown Source)
> >>       at org.objectweb.asm.Frame.a(Unknown Source)
> >>       at org.objectweb.asm.Frame.a(Unknown Source)
> >>       at org.objectweb.asm.MethodWriter.visitMaxs(Unknown Source)
> >>       at org.objectweb.asm.commons.LocalVariablesSorter.visitMaxs(Unknown Source)
> >>       at org.objectweb.asm.ClassReader.accept(Unknown Source)
> >>       at org.objectweb.asm.ClassReader.accept(Unknown Source)
> >>       at org.apache.aries.spifly.dynamic.ClientWeavingHook.weave(ClientWeavingHook.java:60)
> >> The relevant snippet of weaving hook code [1] is this:
> >>   @Override
> >>   public void weave(WovenClass wovenClass) {
> >>   Bundle consumerBundle = wovenClass.getBundleWiring().getBundle();
> >>   Set<WeavingData> wd = activator.getWeavingData(consumerBundle);
> >>   if (wd != null) {
> >>     activator.log(LogService.LOG_DEBUG, "Weaving class " +
> >> wovenClass.getClassName());
> >>
> >>     ClassReader cr = new ClassReader(wovenClass.getBytes());
> >>     ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS |
> >> ClassWriter.COMPUTE_FRAMES);
> >>     TCCLSetterVisitor tsv = new TCCLSetterVisitor(cw,
> >> wovenClass.getClassName(), wd);
> >>     cr.accept(tsv, ClassReader.SKIP_FRAMES); // line 60
> >> * The classloader associated with the BundleRevision does have
> >> visibility to AudioInputStream, I did this while debugging in Eclipse:
> >>     Evaluate: wovenClass.getBundleWiring().getClassLoader().loadClass("javax.sound.sampled.AudioSystem")
> >>        (java.lang.Class<T>) class javax.sound.sampled.AudioSystem
> >> * The bundle being woven does import javax.sound.sampled
> >>
> >> Anyone an idea what could be the issue here? Funny enough I can get
> >> this to work in eclipse's 'dev' mode (a framework launched from within
> >> eclipse), but I think that's because it seeminly implicitly imports
> >> javax.* into all bundles... If I use Felix or Equinox standalone it
> >> fails this way.
> >>
> >> Any ideas?
> >>
> >> Many thanks,
> >>
> >> David
> >>
> >> [1] https://svn.apache.org/repos/asf/aries/trunk/spi-fly/spi-fly-dynamic-bundle/src/main/java/org/apache/aries/spifly/dynamic/ClientWeavingHook.java
> >
 		 	   		  

Re: Weaving Hook puzzle

Posted by David Bosschaert <da...@gmail.com>.
Many thanks, Tim. That worked just fine!

David

On 14 December 2011 14:28, Timothy Ward <ti...@apache.org> wrote:
>
> Hi David,
>
> This is a known issue with ASM in OSGi. We override ClassWriter in the proxy code to get around this (as recommended by the ASM doc). See the following for details:
>
>  \proxy\proxy-impl\src\main\java\org\apache\aries\proxy\impl\common\OSGiFriendlyClassWriter.java in
>
> You can override this method to work even when the class isn't loadable from the ClassLoader that ASM is trying to use (or simply make sure that ASM is using the right classloader in the first place).
>
> Regards,
>
> Tim Ward
> -------------------
> Apache Aries PMC member & Enterprise OSGi advocate
> Enterprise OSGi in Action (http://www.manning.com/cummins)
> -------------------
>
>
>> From: david.bosschaert@gmail.com
>> Date: Wed, 14 Dec 2011 11:13:30 +0000
>> Subject: Weaving Hook puzzle
>> To: dev@aries.apache.org
>>
>> Hi all,
>>
>> A user was playing with the SPI-Fly stuff and hit an issue, which I
>> have trouble understanding how it should be fixed, maybe someone has
>> an idea here... It might be related to the interplay between the OSGi
>> weaving hook and ASM...
>>
>> Here's the situation:
>> * They use some code that at some point uses
>> javax.sound.sampled.AudioSystem.getAudioFileReaders(). This code goes
>> through a few hoops and then ends up at sun.misc.Service.providers()
>> which is similar to java.util.ServiceLoader.load() in that it uses the
>> TCCL to read resources from META-INF/service (I think its a
>> sun-proprietary predecessor to ServiceLoader).
>> * Because in their code they use AudioSystem this is the piece that
>> can get woven to be surrounded by TCCL settings (by using the
>> SPI-Consumer: javax.sound.sampled.AudioSystem#getAudioInputStream and
>> SPI-Provider: javax.sound.sampled.AudioSystem headers).
>> * However, ASM complains:
>> java.lang.ClassNotFoundException: javax.sound.sampled.AudioInputStream
>>       at org.objectweb.asm.ClassWriter.getCommonSuperClass(Unknown Source)
>>       at org.objectweb.asm.ClassWriter.a(Unknown Source)
>>       at org.objectweb.asm.Frame.a(Unknown Source)
>>       at org.objectweb.asm.Frame.a(Unknown Source)
>>       at org.objectweb.asm.MethodWriter.visitMaxs(Unknown Source)
>>       at org.objectweb.asm.commons.LocalVariablesSorter.visitMaxs(Unknown Source)
>>       at org.objectweb.asm.ClassReader.accept(Unknown Source)
>>       at org.objectweb.asm.ClassReader.accept(Unknown Source)
>>       at org.apache.aries.spifly.dynamic.ClientWeavingHook.weave(ClientWeavingHook.java:60)
>> The relevant snippet of weaving hook code [1] is this:
>>   @Override
>>   public void weave(WovenClass wovenClass) {
>>   Bundle consumerBundle = wovenClass.getBundleWiring().getBundle();
>>   Set<WeavingData> wd = activator.getWeavingData(consumerBundle);
>>   if (wd != null) {
>>     activator.log(LogService.LOG_DEBUG, "Weaving class " +
>> wovenClass.getClassName());
>>
>>     ClassReader cr = new ClassReader(wovenClass.getBytes());
>>     ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS |
>> ClassWriter.COMPUTE_FRAMES);
>>     TCCLSetterVisitor tsv = new TCCLSetterVisitor(cw,
>> wovenClass.getClassName(), wd);
>>     cr.accept(tsv, ClassReader.SKIP_FRAMES); // line 60
>> * The classloader associated with the BundleRevision does have
>> visibility to AudioInputStream, I did this while debugging in Eclipse:
>>     Evaluate: wovenClass.getBundleWiring().getClassLoader().loadClass("javax.sound.sampled.AudioSystem")
>>        (java.lang.Class<T>) class javax.sound.sampled.AudioSystem
>> * The bundle being woven does import javax.sound.sampled
>>
>> Anyone an idea what could be the issue here? Funny enough I can get
>> this to work in eclipse's 'dev' mode (a framework launched from within
>> eclipse), but I think that's because it seeminly implicitly imports
>> javax.* into all bundles... If I use Felix or Equinox standalone it
>> fails this way.
>>
>> Any ideas?
>>
>> Many thanks,
>>
>> David
>>
>> [1] https://svn.apache.org/repos/asf/aries/trunk/spi-fly/spi-fly-dynamic-bundle/src/main/java/org/apache/aries/spifly/dynamic/ClientWeavingHook.java
>

RE: Weaving Hook puzzle

Posted by Timothy Ward <ti...@apache.org>.
Hi David,

This is a known issue with ASM in OSGi. We override ClassWriter in the proxy code to get around this (as recommended by the ASM doc). See the following for details:

 \proxy\proxy-impl\src\main\java\org\apache\aries\proxy\impl\common\OSGiFriendlyClassWriter.java in

You can override this method to work even when the class isn't loadable from the ClassLoader that ASM is trying to use (or simply make sure that ASM is using the right classloader in the first place).

Regards,

Tim Ward
-------------------
Apache Aries PMC member & Enterprise OSGi advocate
Enterprise OSGi in Action (http://www.manning.com/cummins)
-------------------


> From: david.bosschaert@gmail.com
> Date: Wed, 14 Dec 2011 11:13:30 +0000
> Subject: Weaving Hook puzzle
> To: dev@aries.apache.org
> 
> Hi all,
> 
> A user was playing with the SPI-Fly stuff and hit an issue, which I
> have trouble understanding how it should be fixed, maybe someone has
> an idea here... It might be related to the interplay between the OSGi
> weaving hook and ASM...
> 
> Here's the situation:
> * They use some code that at some point uses
> javax.sound.sampled.AudioSystem.getAudioFileReaders(). This code goes
> through a few hoops and then ends up at sun.misc.Service.providers()
> which is similar to java.util.ServiceLoader.load() in that it uses the
> TCCL to read resources from META-INF/service (I think its a
> sun-proprietary predecessor to ServiceLoader).
> * Because in their code they use AudioSystem this is the piece that
> can get woven to be surrounded by TCCL settings (by using the
> SPI-Consumer: javax.sound.sampled.AudioSystem#getAudioInputStream and
> SPI-Provider: javax.sound.sampled.AudioSystem headers).
> * However, ASM complains:
> java.lang.ClassNotFoundException: javax.sound.sampled.AudioInputStream
> 	at org.objectweb.asm.ClassWriter.getCommonSuperClass(Unknown Source)
> 	at org.objectweb.asm.ClassWriter.a(Unknown Source)
> 	at org.objectweb.asm.Frame.a(Unknown Source)
> 	at org.objectweb.asm.Frame.a(Unknown Source)
> 	at org.objectweb.asm.MethodWriter.visitMaxs(Unknown Source)
> 	at org.objectweb.asm.commons.LocalVariablesSorter.visitMaxs(Unknown Source)
> 	at org.objectweb.asm.ClassReader.accept(Unknown Source)
> 	at org.objectweb.asm.ClassReader.accept(Unknown Source)
> 	at org.apache.aries.spifly.dynamic.ClientWeavingHook.weave(ClientWeavingHook.java:60)
> The relevant snippet of weaving hook code [1] is this:
>   @Override
>   public void weave(WovenClass wovenClass) {
>   Bundle consumerBundle = wovenClass.getBundleWiring().getBundle();
>   Set<WeavingData> wd = activator.getWeavingData(consumerBundle);
>   if (wd != null) {
>     activator.log(LogService.LOG_DEBUG, "Weaving class " +
> wovenClass.getClassName());
> 
>     ClassReader cr = new ClassReader(wovenClass.getBytes());
>     ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS |
> ClassWriter.COMPUTE_FRAMES);
>     TCCLSetterVisitor tsv = new TCCLSetterVisitor(cw,
> wovenClass.getClassName(), wd);
>     cr.accept(tsv, ClassReader.SKIP_FRAMES); // line 60
> * The classloader associated with the BundleRevision does have
> visibility to AudioInputStream, I did this while debugging in Eclipse:
>     Evaluate: wovenClass.getBundleWiring().getClassLoader().loadClass("javax.sound.sampled.AudioSystem")
> 	 (java.lang.Class<T>) class javax.sound.sampled.AudioSystem
> * The bundle being woven does import javax.sound.sampled
> 
> Anyone an idea what could be the issue here? Funny enough I can get
> this to work in eclipse's 'dev' mode (a framework launched from within
> eclipse), but I think that's because it seeminly implicitly imports
> javax.* into all bundles... If I use Felix or Equinox standalone it
> fails this way.
> 
> Any ideas?
> 
> Many thanks,
> 
> David
> 
> [1] https://svn.apache.org/repos/asf/aries/trunk/spi-fly/spi-fly-dynamic-bundle/src/main/java/org/apache/aries/spifly/dynamic/ClientWeavingHook.java