Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[equinox-dev] DS bug when refreshing previously-active bundles

Declarative Services from CVS Trunk throws the following exception
when refreshing a bundle that was previously active:

 java.lang.IllegalArgumentException: object is not an instance of
declaring class
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:585)
    at org.eclipse.equinox.ds.instance.InvokeMethod.invokeMethod(InvokeMethod.java:144)
    at org.eclipse.equinox.ds.instance.InvokeMethod.bindComponent(InvokeMethod.java:103)
    at org.eclipse.equinox.ds.instance.BuildDispose.bindServiceToReference(BuildDispose.java:413)
    at org.eclipse.equinox.ds.instance.BuildDispose.bindReference(BuildDispose.java:356)
    at org.eclipse.equinox.ds.instance.BuildDispose.bind(BuildDispose.java:306)
    at org.eclipse.equinox.ds.instance.BuildDispose.buildComponentConfigInstance(BuildDispose.java:120)
    at org.eclipse.equinox.ds.instance.InstanceProcess.registerComponentConfigs(InstanceProcess.java:112)
    at org.eclipse.equinox.ds.resolver.Resolver.dispatchWork(Resolver.java:702)
    at org.eclipse.equinox.ds.workqueue.WorkQueue$Queued.dispatch(WorkQueue.java:57)
    at org.eclipse.equinox.ds.workqueue.WorkQueue.run(WorkQueue.java:108)

The problem can be recreated with the following sequences of steps:

1. Start bundle
2. Refresh bundle

   - OR -

1. Start bundle
2. Stop bundle
3. Refresh bundle
4. Start bundle

I tracked down the issue and found that references to a component's
bind, unbind, activate and deactivate methods are not being reset when
the containing bundle's ClassLoader is re-created.  Therefore, the
Method fields are still referencing the methods from the old Class
instance.

To fix the issue, I added the following method to ComponentDescription
to clear the activate and deactivate methods, as well as all of the
reference bind and unbind methods:

    public void clearReflectionMethods() {
        activateMethodInitialized = false;
        activateMethod = null;
        deactivateMethodInitialized = false;
        deactivateMethod = null;

        Iterator iter = referenceDescriptions.iterator();
        while (iter.hasNext()) {
            ReferenceDescription rd = (ReferenceDescription) iter.next();
            rd.setBindMethod(null);
            rd.setUnbindMethod(null);
        }
    }

I added a call to the new method in Activator.removedBundle(Bundle
bundle, Object object).  This method is called when a bundle changes
state from ACTIVE to non-ACTIVE.  It may not be optimal to reset the
Method fields here, as simply stopping a bundle shouldn't cause its
ClassLoader to be recreated.  However, since the DS Activator uses the
custom BundleTracker class and does not implement BundleListener, this
was the best place I found to perform the operation.

Is this a known issue?  If not, should I file a bug?

Thanks,
Jeremy Volkman


Back to the top