mirror of https://github.com/apache/lucene.git
Fix classloading deadlock in analysis factories / AnalysisSPILoader initialization. This closes #11701 (#11718)
This commit is contained in:
parent
53b1ce7504
commit
1d54299011
|
@ -124,6 +124,9 @@ Bug Fixes
|
|||
|
||||
* LUCENE-10644: Facets#getAllChildren testing should ignore child order. (Yuting Gan)
|
||||
|
||||
* LUCENE-10665, GITHUB#11701: Fix classloading deadlock in analysis factories / AnalysisSPILoader
|
||||
initialization. (Uwe Schindler)
|
||||
|
||||
Build
|
||||
---------------------
|
||||
|
||||
|
|
|
@ -27,22 +27,39 @@ import java.util.Set;
|
|||
*/
|
||||
public abstract class CharFilterFactory extends AbstractAnalysisFactory {
|
||||
|
||||
private static final AnalysisSPILoader<CharFilterFactory> loader =
|
||||
new AnalysisSPILoader<>(CharFilterFactory.class);
|
||||
/**
|
||||
* This static holder class prevents classloading deadlock by delaying init of factories until
|
||||
* needed.
|
||||
*/
|
||||
private static final class Holder {
|
||||
private static final AnalysisSPILoader<CharFilterFactory> LOADER =
|
||||
new AnalysisSPILoader<>(CharFilterFactory.class);
|
||||
|
||||
private Holder() {}
|
||||
|
||||
static AnalysisSPILoader<CharFilterFactory> getLoader() {
|
||||
if (LOADER == null) {
|
||||
throw new IllegalStateException(
|
||||
"You tried to lookup a CharFilterFactory by name before all factories could be initialized. "
|
||||
+ "This likely happens if you call CharFilterFactory#forName from a CharFilterFactory's ctor.");
|
||||
}
|
||||
return LOADER;
|
||||
}
|
||||
}
|
||||
|
||||
/** looks up a charfilter by name from context classpath */
|
||||
public static CharFilterFactory forName(String name, Map<String, String> args) {
|
||||
return loader.newInstance(name, args);
|
||||
return Holder.getLoader().newInstance(name, args);
|
||||
}
|
||||
|
||||
/** looks up a charfilter class by name from context classpath */
|
||||
public static Class<? extends CharFilterFactory> lookupClass(String name) {
|
||||
return loader.lookupClass(name);
|
||||
return Holder.getLoader().lookupClass(name);
|
||||
}
|
||||
|
||||
/** returns a list of all available charfilter names */
|
||||
public static Set<String> availableCharFilters() {
|
||||
return loader.availableServices();
|
||||
return Holder.getLoader().availableServices();
|
||||
}
|
||||
|
||||
/** looks up a SPI name for the specified char filter factory */
|
||||
|
@ -65,7 +82,7 @@ public abstract class CharFilterFactory extends AbstractAnalysisFactory {
|
|||
* given classpath/classloader!</em>
|
||||
*/
|
||||
public static void reloadCharFilters(ClassLoader classloader) {
|
||||
loader.reload(classloader);
|
||||
Holder.getLoader().reload(classloader);
|
||||
}
|
||||
|
||||
/** Default ctor for compatibility with SPI */
|
||||
|
|
|
@ -27,22 +27,39 @@ import java.util.Set;
|
|||
*/
|
||||
public abstract class TokenFilterFactory extends AbstractAnalysisFactory {
|
||||
|
||||
private static final AnalysisSPILoader<TokenFilterFactory> loader =
|
||||
new AnalysisSPILoader<>(TokenFilterFactory.class);
|
||||
/**
|
||||
* This static holder class prevents classloading deadlock by delaying init of factories until
|
||||
* needed.
|
||||
*/
|
||||
private static final class Holder {
|
||||
private static final AnalysisSPILoader<TokenFilterFactory> LOADER =
|
||||
new AnalysisSPILoader<>(TokenFilterFactory.class);
|
||||
|
||||
private Holder() {}
|
||||
|
||||
static AnalysisSPILoader<TokenFilterFactory> getLoader() {
|
||||
if (LOADER == null) {
|
||||
throw new IllegalStateException(
|
||||
"You tried to lookup a TokenFilterFactory by name before all factories could be initialized. "
|
||||
+ "This likely happens if you call TokenFilterFactory#forName from a TokenFilterFactory's ctor.");
|
||||
}
|
||||
return LOADER;
|
||||
}
|
||||
}
|
||||
|
||||
/** looks up a tokenfilter by name from context classpath */
|
||||
public static TokenFilterFactory forName(String name, Map<String, String> args) {
|
||||
return loader.newInstance(name, args);
|
||||
return Holder.getLoader().newInstance(name, args);
|
||||
}
|
||||
|
||||
/** looks up a tokenfilter class by name from context classpath */
|
||||
public static Class<? extends TokenFilterFactory> lookupClass(String name) {
|
||||
return loader.lookupClass(name);
|
||||
return Holder.getLoader().lookupClass(name);
|
||||
}
|
||||
|
||||
/** returns a list of all available tokenfilter names from context classpath */
|
||||
public static Set<String> availableTokenFilters() {
|
||||
return loader.availableServices();
|
||||
return Holder.getLoader().availableServices();
|
||||
}
|
||||
|
||||
/** looks up a SPI name for the specified token filter factory */
|
||||
|
@ -65,7 +82,7 @@ public abstract class TokenFilterFactory extends AbstractAnalysisFactory {
|
|||
* given classpath/classloader!</em>
|
||||
*/
|
||||
public static void reloadTokenFilters(ClassLoader classloader) {
|
||||
loader.reload(classloader);
|
||||
Holder.getLoader().reload(classloader);
|
||||
}
|
||||
|
||||
/** Default ctor for compatibility with SPI */
|
||||
|
|
|
@ -27,22 +27,39 @@ import org.apache.lucene.util.AttributeFactory;
|
|||
*/
|
||||
public abstract class TokenizerFactory extends AbstractAnalysisFactory {
|
||||
|
||||
private static final AnalysisSPILoader<TokenizerFactory> loader =
|
||||
new AnalysisSPILoader<>(TokenizerFactory.class);
|
||||
/**
|
||||
* This static holder class prevents classloading deadlock by delaying init of factories until
|
||||
* needed.
|
||||
*/
|
||||
private static final class Holder {
|
||||
private static final AnalysisSPILoader<TokenizerFactory> LOADER =
|
||||
new AnalysisSPILoader<>(TokenizerFactory.class);
|
||||
|
||||
private Holder() {}
|
||||
|
||||
static AnalysisSPILoader<TokenizerFactory> getLoader() {
|
||||
if (LOADER == null) {
|
||||
throw new IllegalStateException(
|
||||
"You tried to lookup a TokenizerFactory by name before all factories could be initialized. "
|
||||
+ "This likely happens if you call TokenizerFactory#forName from a TokenizerFactory ctor.");
|
||||
}
|
||||
return LOADER;
|
||||
}
|
||||
}
|
||||
|
||||
/** looks up a tokenizer by name from context classpath */
|
||||
public static TokenizerFactory forName(String name, Map<String, String> args) {
|
||||
return loader.newInstance(name, args);
|
||||
return Holder.getLoader().newInstance(name, args);
|
||||
}
|
||||
|
||||
/** looks up a tokenizer class by name from context classpath */
|
||||
public static Class<? extends TokenizerFactory> lookupClass(String name) {
|
||||
return loader.lookupClass(name);
|
||||
return Holder.getLoader().lookupClass(name);
|
||||
}
|
||||
|
||||
/** returns a list of all available tokenizer names from context classpath */
|
||||
public static Set<String> availableTokenizers() {
|
||||
return loader.availableServices();
|
||||
return Holder.getLoader().availableServices();
|
||||
}
|
||||
|
||||
/** looks up a SPI name for the specified tokenizer factory */
|
||||
|
@ -65,7 +82,7 @@ public abstract class TokenizerFactory extends AbstractAnalysisFactory {
|
|||
* given classpath/classloader!</em>
|
||||
*/
|
||||
public static void reloadTokenizers(ClassLoader classloader) {
|
||||
loader.reload(classloader);
|
||||
Holder.getLoader().reload(classloader);
|
||||
}
|
||||
|
||||
/** Default ctor for compatibility with SPI */
|
||||
|
|
Loading…
Reference in New Issue