lucene-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Uwe Schindler (JIRA)" <j...@apache.org>
Subject [jira] [Comment Edited] (LUCENE-7870) Use cl.loadClass(...) instead of Class.forName(..., cl) in SPIClassIterator
Date Tue, 20 Jun 2017 14:50:00 GMT

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

Uwe Schindler edited comment on LUCENE-7870 at 6/20/17 2:49 PM:
----------------------------------------------------------------

Hi Andreas,
this issue should be solved in Lucene 7.0. We will not backport this as it breaks backwards
compatibility: We no longer use the context class loader for looking up services. It takes
the class loader that defined the interface. If you require another one (e.g. in OSGI without
using buddy classloading) you can call Codec.reloadCodecs(ClassLoader) and similar methods.
See the MIGRATE.txt in Lucene 7.


was (Author: thetaphi):
Hi Andreas,
this issue should be solved in Lucene 7.0. We will not backport this as it breaks backwards
compatibility: We no longer use the context class loader for looking up services. It takes
the class loader that defined the interface. If you require another one (e.g. in OSGI without
using buddy classloading) you can call Codec.reloadCodes(ClassLoader) and similar methods.
See the MIGRATE.txt in Lucene 7.

> Use cl.loadClass(...) instead of Class.forName(..., cl) in SPIClassIterator
> ---------------------------------------------------------------------------
>
>                 Key: LUCENE-7870
>                 URL: https://issues.apache.org/jira/browse/LUCENE-7870
>             Project: Lucene - Core
>          Issue Type: Bug
>    Affects Versions: 5.2.1, 6.1
>         Environment: Eclipse Equinox 4.7
>            Reporter: Andreas Sewe
>
> This issue is initially described in [Eclipse Bug 517935|https://bugs.eclipse.org/bugs/show_bug.cgi?id=517935]
and prevents multiple versions of Lucene Core coexisting in an Equinox environment (FYI, Equinox
is the OSGi container used by the Eclipse IDE).
> Here’s how the problem manifests: While Equinox cleanly separates two versions of the
same Lucene Core bundle (e.g., {{org.apache.lucene.core_5.2.1}} and  {{org.apache.lucene.core_6.1.0}})
using two different bundle class loaders, it uses a single context classloader for all threads:
the [{{ContextFinder}}|https://wiki.eclipse.org/Context_Class_Loader_Enhancements#Context_Finder_2].
When asked to load a class, the {{ContextFinder}} *initiates* a search through all bundle
class loaders currently “on“ the call stack; the class to be loaded is then *defined*
by the respective bundle’s class loader.
> And here is where the use of {{Class.forName(..., classLoader)}} rather than {{classLoader.loadClass(...)}}
causes problems. Consider the following sequence of events:
> # The {{NamedSPILoader}} of bundle {{o.a.l.core_5.2.1}} (re)loads some service (e.g.,
the {{Lucene50PostingFormat}}).
> ## It (through {{SPIClassIterator}}) first uses {{Class.forName}} with the bundle class
loader of {{o.a.l.core_5.2.1}} (as per LUCENE-4713) to successfully load {{Lucene50PostingFormat}}
from the {{o.a.l.core_5.2.1}} bundle.
> ## Then (through another {{SPIClassIterator}}) it uses {{Class.forName}} with the thread’s
context class loader (here: {{ContextFinder}}) to load {{Lucene50PostingFormat}}. The {{ContextFinder}}
delegates loading to the {{o.a.l.core_5.2.1}} bundle’s class loader, as that bundle is topmost
on the call stack. This bundle class loader (again) successfully loads {{Lucene50PostingFormat}}
from the {{o.a.l.core_5.2.1}} bundle.
> # Later, the {{NamedSPILoader}} of *another* bundle {{o.a.l.core_6.1.0}} loads the {{Lucene50PostingFormat}}
service.
> ## It (through {{SPIClassIterator}}) first uses {{Class.forName}} with the bundle class
loader of {{o.a.l.core_6.1.0}} to successfully load {{Lucene50PostingFormat}} from the {{o.a.l.core_6.1.0}}
bundle.
> ## Then (through another {{SPIClassIterator}}) it uses {{Class.forName}} with the thread’s
context class loader (the same {{ContextFinder}} again) to load {{Lucene50PostingFormat}}.
As {{Class.forName}} remembers that the {{ContextFinder}} has successfully initiated the loading
of {{Lucene50PostingFormat}} before, it simply returns the {{Class}} instance defined earlier
in step _1.2_. But that class was defined by a different bundle class loader, namely that
of {{o.a.l.core_5.2.1}}! This cache look up happens in native code; the {{ContextFinder}}‘s
{{loadClass}} method isn’t even called, so there’s no way it can load the class from the
{{o.a.l.core_6.1.0}} bundle, even though it now is topmost on the stack.
> ## Casting the {{Lucene50PostingFormat}} loading from bundle {{o.a.l.core_5.2.1}} to
{{PostingFormat}} from bundle {{o.a.l.core_6.1.0}} then fails, leaving the {{o.a.l.core_6.1.0}}
bundle in a broken state.
> It {{SPIClassIterator.next()}} would use {{classLoader.loadClass(...)}} rather than {{Class.forName(...,
classLoader}}), then class loading in step _1.2_ wouldn’t *lock in* the {{Lucene50PostingFormat}}
class from {{org.apache.lucene.core_5.2.1}}; instead, step _2.2_ would perform a completely
independent look up that retrieves the class from the correct bundle. The cast in step _2.3_
would then succeed.
> At Eclipse Orbit, we plan to distribute a [patched version|https://git.eclipse.org/r/98804/]
of Lucene Core, but obviously we would like to see the (one-line) change included in the upstream
project.
> BTW, if you fear that bypassing {{Class.forName}} “caching” affects performance,
then there’s no need to worry: Most {{ClassLoader}} implementations cache as well ({{findLoadedClass}});
it’s only {{ContextFinder}} that [overrides {{loadClass}} wholesale|https://git.eclipse.org/c/equinox/rt.equinox.framework.git/tree/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/ContextFinder.java?h=R4_7_maintenance],
as it dynamically (based on the current call stack) delegates to the (caching) bundle class
loaders.



--
This message was sent by Atlassian JIRA
(v6.4.14#64029)

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@lucene.apache.org
For additional commands, e-mail: dev-help@lucene.apache.org


Mime
View raw message