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] [Resolved] (FELIX-5450) Fragments with multiple hosts can cause java.lang.ArrayIndexOutOfBoundsException
Date Thu, 15 Dec 2016 21:53:58 GMT

     [ https://issues.apache.org/jira/browse/FELIX-5450?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel

Thomas Watson resolved FELIX-5450.
    Resolution: Fixed

I committed a fix along with two new tests.

> Fragments with multiple hosts can cause java.lang.ArrayIndexOutOfBoundsException
> --------------------------------------------------------------------------------
>                 Key: FELIX-5450
>                 URL: https://issues.apache.org/jira/browse/FELIX-5450
>             Project: Felix
>          Issue Type: Bug
>          Components: Resolver
>    Affects Versions: resolver-1.10.0
>            Reporter: Thomas Watson
>            Assignee: Thomas Watson
> The fix in FELIX-5389 for ShadowList is not complete.  There are still cases where the
underlying ArrayList from the CandidateSelector is reused in the ShadowList when it is not
intended.  This leads to exceptions like the following:
> java.lang.ArrayIndexOutOfBoundsException: -1
> 	at java.util.ArrayList.elementData(ArrayList.java:418)
> 	at java.util.ArrayList.set(ArrayList.java:446)
> 	at org.apache.felix.resolver.util.ShadowList.replace(ShadowList.java:81)
> 	at org.apache.felix.resolver.Candidates.prepare(Candidates.java:915)
> 	at org.apache.felix.resolver.ResolverImpl.getInitialCandidates(ResolverImpl.java:502)
> 	at org.apache.felix.resolver.ResolverImpl.doResolve(ResolverImpl.java:387)
> 	at org.apache.felix.resolver.ResolverImpl.resolve(ResolverImpl.java:375)
> 	at org.apache.felix.resolver.ResolverImpl.resolve(ResolverImpl.java:368)
> This is happening when there are multiple hosts for a single fragment and the fragment
has a requirement that is getting resolved to a candidate from another host resource that
also has at least one fragment.
> The issue comes up when replacing the capability from the host with a wrapped capability
for the fragment requirement which is a payload requirement for more than one host.  It should
do this for each WrappedRequirement that is wrapping the payload requirement from the fragment
to each host.  The first WrappedRequirement has its candidates modified, but that changes
the shared ArrayList of the candidates for each of the other WrappedRequirements for the other
hosts.  The fix for this is to ensure the ArrayList from a CandidateSelector is never shared
with a ShadowList.
> But once I fixed this I ran into another strange issue that ended up causing Uses constraint
errors like this:
> org.osgi.service.resolver.ResolutionException: Uses constraint violation. Unable to resolve
resource host [osgi.identity; host] because it is exposed to package 'exporter' from resources
exporter [osgi.identity; exporter] and exporter [osgi.identity; exporter] via two dependency
> Chain 1:
>   host [osgi.identity; host]
>     import: (osgi.wiring.package=exporter)
>      |
>     export: osgi.wiring.package: exporter
>   exporter [osgi.identity; exporter]
> Chain 2:
>   host [osgi.identity; host]
>     import: (osgi.wiring.package=exporter)
>      |
>     export: osgi.wiring.package: exporter
>   exporter [osgi.identity; exporter]
> This only happens if a fragment has more than one host and the fragment and host have
a requirement for a the same package.  Additionally the capability that satisfies the payload
requirement must come from a host that also has at least one fragment.  The issue here is
how we are finding CandidateSelectors of depending requirements when we need to replace a
capability with a wrapped capability.  There is a loop in the Candidates.prepare method which
is says "Copy candidates for fragment requirements to the host.".  This loop basically copies
the candidates from the original requirement from the fragment to a CandidateSelector for
the WrappedRequirement for the host.  But it also removes the original requirement from the
dependents for the capability.  If there are multiple hosts this becomes problematic because
this dependency set is used to find CandidateSelectors that need to be modified when wrapping
a host.  But since we remove the original requirement from the fragment that means any other
hosts the fragment is attached to will not be discovered and therefore will not have the original
capability properly replaced with the WrappedCapability.  That makes the consistency check
fail and give this bogus message that make it look like there are 2 identical chains leading
to the identical capability.  But the two capabilities are different because one is wrapped
and one is not.
> The fix is to separate out the inner loop that "Copy candidates for fragment requirements
to the host." to a outer loop that is done before the main loop over the hostResources.  This
way we properly setup all the CandidateSelector for the payload WrappedRequirements before
actually modifying the CandidateSelector capabilities with the WrappedCapabilities.
> Super long story short:  Fragments are just horribly complex. 

This message was sent by Atlassian JIRA

View raw message