felix-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Thomas Watson (JIRA)" <j...@apache.org>
Subject [jira] [Commented] (FELIX-5570) Immediate service component that provides a WeavingHook results in an NPE
Date Tue, 28 Feb 2017 22:26:45 GMT

    [ 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

View raw message