[ 
https://issues.apache.org/jira/browse/FELIX-5570?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15888978#comment-15888978
 ] 

Thomas Watson commented on FELIX-5570:
--------------------------------------

The framework is supposed to ignore the registration of the weaving hook and 
move on if null is returned by getService.  That is what we do in Equinox but 
this ugly error is logged because of a recursive define class situation that 
SCR is causing.  Both Equinox and Felix frameworks detect a recursive call when 
a call to the ServiceFactory.getService causes the same classloader to re-enter 
to try and define the same class name using the same thread.  Equinox correctly 
throws a CNFE while felix silently returns null which then really blows up SCR 
implementation.

I know I can improve Equinox to split out the recursive define class check so 
that we separate the check between calls to weaving hook registrations and the 
actual call to the ClassLoader.defineClass.  This way it will avoid the issue 
altogether which SCR is introducing by allowing its own getService 
implementation to re-enter.  It seems clear to me that the design of the SCR 
ServiceFactory implementation is not designed to allow recursive calls to 
itself, yet the way it is being invoked will allow this to happen.  Either way 
I am likely going to improve equinox to allow this to 'work' without error.  
But I do think this is above and beyond what the specification requires a 
framework to do for weaving hooks registrations when they cause recursive class 
loads to occur.

My basic approach in Equinox is to detect recursive class loads while invoking 
weaving hooks, if recursion is detected for a class name then I will simply 
ignore all weave hooks for the recursive class load and allow it to proceed to 
define class.  This makes it so that the ugly CNFE is no longer thrown or 
logged by SCR.

> Immediate service component that provides a WeavingHook results in an NPE
> -------------------------------------------------------------------------
>
>                 Key: FELIX-5570
>                 URL: https://issues.apache.org/jira/browse/FELIX-5570
>             Project: Felix
>          Issue Type: Bug
>          Components: Declarative Services (SCR)
>    Affects Versions: scr-2.0.8
>            Reporter: Thomas Watson
>
> If you have an immediate service component that provides a WeavingHook 
> service then an NPE will result.  An example service component XML:
> <?xml version="1.0" encoding="UTF-8"?>
> <scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0"; 
> enabled="true" immediate="true" name="Test Patches Weaver">
>    <implementation class="test.patches.Weaver" />
>    <service>
>       <provide interface="org.osgi.framework.hooks.weaving.WeavingHook"/>
>    </service>
> </scr:component>
> If you deploy this bundle along with SCR 2.0.8 on Felix Framework 5.6.2 the 
> following NPE happens:
> ERROR: [Test Patches Weaver(0)] Error during instantiation of the 
> implementation object
> java.lang.NullPointerException
>       at 
> org.apache.felix.scr.impl.manager.SingleComponentManager.createImplementationObject(SingleComponentManager.java:237)
>       at 
> org.apache.felix.scr.impl.manager.SingleComponentManager.createComponent(SingleComponentManager.java:109)
>       at 
> org.apache.felix.scr.impl.manager.SingleComponentManager.getService(SingleComponentManager.java:906)
>       at 
> org.apache.felix.scr.impl.manager.SingleComponentManager.getServiceInternal(SingleComponentManager.java:879)
>       at 
> org.apache.felix.scr.impl.manager.SingleComponentManager.getService(SingleComponentManager.java:823)
>       at 
> org.apache.felix.framework.ServiceRegistrationImpl.getFactoryUnchecked(ServiceRegistrationImpl.java:347)
>       at 
> org.apache.felix.framework.ServiceRegistrationImpl.getService(ServiceRegistrationImpl.java:247)
>       at 
> org.apache.felix.framework.ServiceRegistry.getService(ServiceRegistry.java:350)
>       at org.apache.felix.framework.Felix.getService(Felix.java:3720)
>       at 
> org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.transformClass(BundleWiringImpl.java:2359)
>       at 
> org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.findClass(BundleWiringImpl.java:2052)
>       at 
> org.apache.felix.framework.BundleWiringImpl.findClassOrResourceByDelegation(BundleWiringImpl.java:1518)
>       at 
> org.apache.felix.framework.BundleWiringImpl.access$200(BundleWiringImpl.java:79)
>       at 
> org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.loadClass(BundleWiringImpl.java:1958)
>       at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
>       at org.apache.felix.framework.Felix.loadBundleClass(Felix.java:1925)
>       at org.apache.felix.framework.BundleImpl.loadClass(BundleImpl.java:978)
>       at 
> org.apache.felix.scr.impl.manager.AbstractComponentManager.initDependencyManagers(AbstractComponentManager.java:976)
>       at 
> org.apache.felix.scr.impl.manager.AbstractComponentManager.collectDependencies(AbstractComponentManager.java:1003)
>       at 
> org.apache.felix.scr.impl.manager.SingleComponentManager.getServiceInternal(SingleComponentManager.java:859)
>       at 
> org.apache.felix.scr.impl.manager.AbstractComponentManager.activateInternal(AbstractComponentManager.java:749)
>       at 
> org.apache.felix.scr.impl.manager.AbstractComponentManager.enableInternal(AbstractComponentManager.java:675)
>       at 
> org.apache.felix.scr.impl.manager.AbstractComponentManager.enable(AbstractComponentManager.java:430)
>       at 
> org.apache.felix.scr.impl.manager.ConfigurableComponentHolder.enableComponents(ConfigurableComponentHolder.java:657)
>       at 
> org.apache.felix.scr.impl.BundleComponentActivator.initialEnable(BundleComponentActivator.java:341)
>       at 
> org.apache.felix.scr.impl.Activator.loadComponents(Activator.java:390)
>       at org.apache.felix.scr.impl.Activator.access$200(Activator.java:54)
>       at 
> org.apache.felix.scr.impl.Activator$ScrExtension.start(Activator.java:265)
>       at 
> org.apache.felix.utils.extender.AbstractExtender.createExtension(AbstractExtender.java:254)
>       at 
> org.apache.felix.utils.extender.AbstractExtender.modifiedBundle(AbstractExtender.java:227)
>       at 
> org.apache.felix.utils.extender.AbstractExtender.addingBundle(AbstractExtender.java:187)
>       at 
> org.osgi.util.tracker.BundleTracker$Tracked.customizerAdding(BundleTracker.java:469)
>       at 
> org.osgi.util.tracker.BundleTracker$Tracked.customizerAdding(BundleTracker.java:415)
>       at 
> org.osgi.util.tracker.AbstractTracked.trackAdding(AbstractTracked.java:256)
>       at org.osgi.util.tracker.AbstractTracked.track(AbstractTracked.java:229)
>       at 
> org.osgi.util.tracker.BundleTracker$Tracked.bundleChanged(BundleTracker.java:444)
>       at 
> org.apache.felix.framework.EventDispatcher.invokeBundleListenerCallback(EventDispatcher.java:915)
>       at 
> org.apache.felix.framework.EventDispatcher.fireEventImmediately(EventDispatcher.java:834)
>       at 
> org.apache.felix.framework.EventDispatcher.fireBundleEvent(EventDispatcher.java:516)
>       at org.apache.felix.framework.Felix.fireBundleEvent(Felix.java:4562)
>       at org.apache.felix.framework.Felix.activateBundle(Felix.java:2229)
>       at org.apache.felix.framework.Felix.startBundle(Felix.java:2144)
>       at org.apache.felix.framework.Felix.setActiveStartLevel(Felix.java:1371)
>       at 
> org.apache.felix.framework.FrameworkStartLevelImpl.run(FrameworkStartLevelImpl.java:308)
>       at java.lang.Thread.run(Thread.java:745)
> This is because SCR is invoking SingleComponentManager.getServiceInternal 
> after registering the WeavingHook service in order to get the service object 
> for immediate activation.  This ends up trying to load the 
> test.patches.Weaver implementation class which then causes the framework to 
> look for WeavingHooks to call.  Which causes a recursive call back into 
> SingleComponentManager.getServiceInternal for the same service component 
> which triggers another load of the implementation class.  Here Felix 
> framework detects a recursive class load for the same class name and returns 
> null from Bundle.loadClass() (Something I think is not correct, I think 
> instead a CNFE must be thrown or some other class loader LinkageError).
> This null class results in the above NPE.  I found this bug while running SCR 
> on the Equinox framework.  On Equinox a CNFE is thrown and logged by SCR and 
> things seem to recover from that but we are left with an error message in the 
> log making it look like things are not working.
> Both Equinox and Felix seem to detect the recursive class load that SCR is 
> causing but handle the situation slightly different.  In both cases I argue 
> that SCR should avoid recursive calls into 
> SingleComponentManager.getServiceInternal for the same service component.
> The difficulty here is that SCR can depend on the framework to  avoid 
> recursive calls into its ServiceFactory because the specification mandates 
> that (see org.osgi.framework.ServiceException.FACTORY_RECURSION).  But here 
> SCR is invoking SingleComponentManager.getServiceInternal itself and an 
> internal implementation detail of an immediate service component.  It seems 
> that for this internal call to SingleComponentManager.getServiceInternal 
> something should be done to prevent recurse calls so that this is consistent 
> with how non-immediate components work.
> Also see https://bugs.eclipse.org/bugs/show_bug.cgi?id=512707



--
This message was sent by Atlassian JIRA
(v6.3.15#6346)

Reply via email to