xalan
一段时间以来, Apache Xalan中存在一个令人尴尬的错误,该错误是XALANJ-2540 。 此错误的后果是Xalan每次XPath表达式求值将内部SPI配置文件加载数千次 ,可以很容易地进行如下测量:
这个:
Element e = (Element)
document.getElementsByTagName("SomeElementName")
.item(0);
String result = ((Element) e).getTextContent();
似乎比这快100倍:
// Accounts for 30%, can be cached
XPathFactory factory = XPathFactory.newInstance();
// Negligible
XPath xpath = factory.newXPath();
// Negligible
XPathExpression expression =
xpath.compile("//SomeElementName");
// Accounts for 70%
String result = (String) expression
.evaluate(document, XPathConstants.STRING);
可以看出,每10k测试XPath评估中的每一个都导致类加载器试图以某种默认配置查找DTMManager
实例。 此配置不会加载到内存中,但每次都会访问。 此外,此访问似乎受到ObjectFactory.class
本身上锁的保护。 当访问失败时(默认情况下),将从xalan.jar
文件的配置文件中加载配置:
META-INF/service/org.apache.xml.dtm.DTMManager
每次! :
幸运的是,可以通过指定如下所示的JVM参数来覆盖此行为:
-Dorg.apache.xml.dtm.DTMManager=
org.apache.xml.dtm.ref.DTMManagerDefault
要么
-Dcom.sun.org.apache.xml.internal.dtm.DTMManager=
com.sun.org.apache.xml.internal.dtm.ref.DTMManagerDefault
上面的方法可以正常工作,因为如果工厂类名仍然是默认值,这将绕过lookUpFactoryClassName()中的昂贵工作:
// Code from c.s.o.a.xml.internal.dtm.ObjectFactory
static String lookUpFactoryClassName(
String factoryId,
String propertiesFilename,
String fallbackClassName) {
SecuritySupport ss = SecuritySupport
.getInstance();
try {
String systemProp = ss
.getSystemProperty(factoryId);
if (systemProp != null) {
// Return early from the method
return systemProp;
}
} catch (SecurityException se) {
}
// [...] "Heavy" operations later
资源资源
上面的文字摘自我不久前对公众所做的堆栈溢出问题和解答 。 我将其再次发布在我的博客上,以便可以提高社区对于这个相当严重的错误的认识。 请随意在这张票上投票,因为地球上的每个Sun / Oracle JDK都会受到影响: https : //issues.apache.org/jira/browse/XALANJ-2540
当然,向Apache贡献修复程序会更好。
xalan