记一个Maven依赖里隐含某有问题的旧版本Jar包导致ClassPath加载该Jar包出现隐式Bug的问题

问题场景:两个项目分别调用同一个关闭微信支付订单的方法,其中一个项目在将Map转为Xml的时候抛出了

1
2
3
4
5
6
Exception in thread "main" java.lang.AbstractMethodError: javax.xml.parsers.DocumentBuilderFactory.setFeature(Ljava/lang/String;Z)V
at gov.nasa.worldwind.util.WWXML.createDocumentBuilder(WWXML.java:61)
at gov.nasa.worldwind.util.WWXML.openDocumentStream(WWXML.java:236)
at gov.nasa.worldwind.util.WWXML.openDocumentStream(WWXML.java:223)
at gov.nasa.worldwind.util.WWXML.openDocumentFile(WWXML.java:175)
at gov.nasa.worldwind.util.WWXML.openDocument(WWXML.java:148)

这个异常。而另一个项目主动调用关闭微信支付订单方法则无此异常抛出。

问题分析:因为之前一直主动调用该方法,功能正常,于是排除底层方法错误。这时候机智的我面向StackOverFlow果断找到了类似的问题。

相关代码: 这是微信SDK中Map转XML的方法,直接拿来用了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/**
* 将Map转换为XML格式的字符串
*
* @param data Map类型数据
* @return XML格式的字符串
* @throws Exception
*/
public static String mapToXml(Map<String, String> data) throws Exception {
org.w3c.dom.Document document = WXPayXmlUtil.newDocument();
org.w3c.dom.Element root = document.createElement("xml");
document.appendChild(root);
for (String key: data.keySet()) {
String value = data.get(key);
if (value == null) {
value = "";
}
value = value.trim();
org.w3c.dom.Element filed = document.createElement(key);
filed.appendChild(document.createTextNode(value));
root.appendChild(filed);
}
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
DOMSource source = new DOMSource(document);
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
StringWriter writer = new StringWriter();
StreamResult result = new StreamResult(writer);
transformer.transform(source, result);
String output = writer.getBuffer().toString(); //.replaceAll("\n|\r", "");
try {
writer.close();
}
catch (Exception ex) {
}
return output;
}

Example WorldWind application encounters AbstractMethodError when started

这里的思路很关键,是该项目中的Maven的某个依赖加载了错误版本的apache/xerces项目,该回答提出可以用ClassLoader获取当前加载该类的URL 于是我照做后发现果然是这里的问题:

如下,错误的项目里加载2.5.0版本的xerces项目 而这个版本的刚好会有问题

The jar that’s being used is the one that came with WorldWind, version 2.5.0, so presumably it should work. I don’t see any indication in the WorldWind forums that this is the problem

而正常的项目没有加载该类

问题找到了,那么下一步就是去看哪个Maven项目中引用了该Jar。

OK找到了问题,下面就是去POM文件里把这个依赖屏蔽掉

再次调用同样的方法,问题解决。

这里引申了ClassLoader加载类的机制以及classpath中可能隐藏的问题,值得深挖和学习。

分享到:
0%