lucene-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Vojtěch Toman (JIRA) <j...@apache.org>
Subject [jira] [Commented] (LUCENE-4713) SPI: Allow fallback to default ClassLoader if Thread#getContextClassLoader fails
Date Thu, 14 Feb 2013 10:00:13 GMT

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

Vojtěch Toman commented on LUCENE-4713:
---------------------------------------

We hit the same issue when using Lucene via Ant. After upgrading from Lucene 3.x to 4.0, our
Lucene-related Ant tasks stopped working because the class loader returned by Thread.currentThread().getContextClassLoader()
does not see META-INF/services/org.apache.lucene.codecs.Codec.

{code}
java.lang.ExceptionInInitializerError
        at org.apache.lucene.index.LiveIndexWriterConfig.<init>(LiveIndexWriterConfig.java:118)
        at org.apache.lucene.index.IndexWriterConfig.<init>(IndexWriterConfig.java:145)
        [.....left out.....]
        at com.xhive.anttasks.XhiveTask.execute(XhiveTask.java:180)
        at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:291)
        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:597)
        at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
        at org.apache.tools.ant.Task.perform(Task.java:348)
        at org.apache.tools.ant.Target.execute(Target.java:390)
        at org.apache.tools.ant.Target.performTasks(Target.java:411)
        at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1399)
        at org.apache.tools.ant.Project.executeTarget(Project.java:1368)
        at org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:41)
        at org.apache.tools.ant.Project.executeTargets(Project.java:1251)
        at org.apache.tools.ant.Main.runBuild(Main.java:809)
        at org.apache.tools.ant.Main.startAnt(Main.java:217)
        at org.apache.tools.ant.launch.Launcher.run(Launcher.java:280)
        at org.apache.tools.ant.launch.Launcher.main(Launcher.java:109)
Caused by: java.lang.IllegalArgumentException: A SPI class of type org.apache.lucene.codecs.Codec
with name 'Lucene40' does not exist. You need to add the corresponding JAR file supporting
this SPI to your classpath.The current classpath supports the following names: []
        at org.apache.lucene.util.NamedSPILoader.lookup(NamedSPILoader.java:104)
        at org.apache.lucene.codecs.Codec.forName(Codec.java:95)
        at org.apache.lucene.codecs.Codec.<clinit>(Codec.java:122)
        ... 34 more
{code}

The build file looks like this:

{code:xml}
<project>

  ...

  <path id="classpath">
    <fileset dir="${xhive.dir}">
       <!-- contains, among others, lucene.jar -->
      <include name="lib/xhivedb/**/*.jar"/>
      <!-- contains, among others, our custom Ant tasks -->
      <include name="build/jarfiles/plain/xhive.jar"/>
    </fileset>
  </path>

  ...

  <target name="build">
    <taskdef classpathref="classpath"
             resource="com/xhive/anttasks/tasks.properties"/>

    <!-- this custom task fails after migration to Lucene 4.x -->
    <our-lucene-related-task .../>
  </target>

</project>
{code}

What happens is that inside the task Thread.currentThread().getContextClassLoader() does not
return the Ant class loader (which knows the full classpath).

Doing something like this:

{code:java}
public NamedSPILoader(Class<S> clazz) {
  this(clazz, clazz.getClassLoader());
}
{code}

would fix it, but given the previous comments on the issue, I am not sure it would be the
best fix.

                
> SPI: Allow fallback to default ClassLoader if Thread#getContextClassLoader fails
> --------------------------------------------------------------------------------
>
>                 Key: LUCENE-4713
>                 URL: https://issues.apache.org/jira/browse/LUCENE-4713
>             Project: Lucene - Core
>          Issue Type: Improvement
>    Affects Versions: 4.0, 4.1, 4.2
>            Reporter: Christian Kohlschütter
>            Priority: Minor
>              Labels: ClassLoader, Thread
>         Attachments: LUCENE-4713.patch, LuceneContextClassLoader.patch
>
>
> NOTE: This issue has been renamed from:
> "Replace calls to Thread#getContextClassLoader with the ClassLoader of the current class"
> because the revised patch provides a clean fallback path.
> I am not sure whether it is a design decision or if we can indeed consider this a bug:
> In core and analysis-common some classes provide on-demand class loading using SPI. In
NamedSPILoader, SPIClassIterator, ClasspathResourceLoader and AnalysisSPILoader there are
constructors that use the Thread's context ClassLoader by default whenever no particular other
ClassLoader was specified.
> Unfortunately this does not work as expected when the Thread's ClassLoader can't see
the required classes that are instantiated downstream with the help of Class.forName (e.g.,
Codecs, Analyzers, etc.).
> That's what happened to us here. We currently experiment with running Lucene 2.9 and
4.x in one JVM, both being separated by custom ClassLoaders, each seeing only the corresponding
Lucene version and the upstream classpath.
> While NamedSPILoader and company get successfully loaded by our custom ClassLoader, their
instantiation fails because our Thread's Context-ClassLoader cannot find the additionally
required classes.
> We could probably work-around this by using Thread#setContextClassLoader at construction
time (and quickly reverting back afterwards), but I have the impression this might just hide
the actual problem and cause further trouble when lazy-loading classes later on, and potentially
from another Thread.
> Removing the call to Thread#getContextClassLoader would also align with the behavior
of AttributeSource.DEFAULT_ATTRIBUTE_FACTORY, which in fact uses Attribute#getClass().getClassLoader()
instead.
> A simple patch is attached. All tests pass.

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira

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


Mime
View raw message