在 java-8“安全处理 org.xml.sax.SAXNotRecognizedException 导致 java.lang.IllegalStateException”中解组 xml 时出错
Posted
技术标签:
【中文标题】在 java-8“安全处理 org.xml.sax.SAXNotRecognizedException 导致 java.lang.IllegalStateException”中解组 xml 时出错【英文标题】:Error unmarshalling xml in java-8 "secure-processing org.xml.sax.SAXNotRecognizedException causing java.lang.IllegalStateException" 【发布时间】:2014-10-27 22:28:45 【问题描述】:以下代码在 Java 7 中运行良好
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
String xmlString = '<xml ..... ';
StringReader reader = new StringReader(xmlString);
JAXBContext jc = JAXBContext.newInstance(MyClass.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
MyClass myClass = (MyClass) unmarshaller.unmarshal(reader);
....
现在我们必须升级到 Java 8,现在执行代码时出现此异常:
Sep 03, 2014 1:42:47 PM com.sun.xml.internal.bind.v2.util.XmlFactory createParserFactory
SCHWERWIEGEND: null
org.xml.sax.SAXNotRecognizedException: Feature: http://javax.xml.XMLConstants/feature/secure-processing
at org.apache.xerces.jaxp.SAXParserFactoryImpl.setFeature(SAXParserFactoryImpl.java:100)
at com.sun.xml.internal.bind.v2.util.XmlFactory.createParserFactory(XmlFactory.java:114)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.getXMLReader(UnmarshallerImpl.java:139)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:157)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:214)
我知道有一个question 针对类似的问题,但退回到 java 7 对我来说不是解决方案。
我尝试添加以下maven依赖
<dependency>
<groupId>javax.xml</groupId>
<artifactId>jaxp-api</artifactId>
<version>1.4</version>
</dependency>
但这并没有改变结果,所以我删除了它(感谢@BlaiseDoughan 提供的信息,它包含在 Java 6 中)
欢迎任何提示,非常感谢。
【问题讨论】:
【参考方案1】:我遇到了同样的问题,并通过将 JVM 争论设置为 -Djavax.xml.accessExternalDTD=all -Djavax.xml.parsers.SAXParserFactory=com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl
【讨论】:
【参考方案2】:我在尝试解决声纳漏洞java:S2755
时遇到了类似的问题。
SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
schemaFactory.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, ""); // added (for sonar)
schemaFactory.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, ""); // added (for sonar)
在添加这两行之后,第一个 setProperty()
调用抛出了 SAXNotRecognizedException
。
我猜这是因为 XMLSchemaFactory
有多种实现可用,其中一个包含在 JDK 中。
我的解决方案是在项目上运行mvn dependency:tree
并搜索任何出现的“xerces”。我发现了两个从所有使用它们的依赖项中排除的依赖项:
<dependency>
<!-- ... -->
<exclusions>
<exclusion>
<groupId>xerces</groupId>
<artifactId>xercesImpl</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<!-- ... -->
<exclusions>
<exclusion>
<groupId>com.rackspace.apache</groupId>
<artifactId>xerces2-xsd11</artifactId>
</exclusion>
</exclusions>
</dependency>
【讨论】:
【参考方案3】:我遇到过类似的问题,当 xerces jar 和 xercesImpl jar 的版本存在很大差异时会出现此问题。为了解决这个问题,我使用了 xerces-2.9.0 和 xercesImpl-2.9.1,问题就消失了。
【讨论】:
【参考方案4】:我在我的项目中使用第二个 Mitch 解决方案解决了这个问题,但只是使用了
java -Djavax.xml.parsers.SAXParserFactory="com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl"
【讨论】:
它解决了我的问题,我们使用jdk6编译和运行tomcat6 & jdk8。不需要任何与代码相关的更改,真是太好了。【参考方案5】:我们也遇到了这个问题,注意到需要保持jdk版本和jre版本一致,否则会存在版本不匹配导致的问题。
遇到问题的人用的是jdk1.6和jre 1.8,改成jdk1.6后问题就解决了。
【讨论】:
【参考方案6】:另一种可能的解决方案是添加系统变量:
我在对我有用的 maven tomcat 插件中使用了这些:
<javax.xml.parsers.DocumentBuilderFactory>com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl</javax.xml.parsers.DocumentBuilderFactory>
<org.xml.sax.parser>com.sun.org.apache.xerces.internal.parsers.SAXParser</org.xml.sax.parser>
<javax.xml.parsers.SAXParserFactory>com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl</javax.xml.parsers.SAXParserFactory>
但你也应该可以设置如下:
java -Dorg.xml.sax.parser="com.sun.org.apache.xerces.internal.parsers.SAXParser" \
-Djavax.xml.parsers.DocumentBuilderFactory="com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl" \
-Djavax.xml.parsers.SAXParserFactory="com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl"
甚至使用 System.setProperty:
System.setProperty("org.xml.sax.driver", "com.sun.org.apache.xerces.internal.parsers.SAXParser");
System.setProperty("javax.xml.parsers.DocumentBuilderFactory","com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl");
System.setProperty("javax.xml.parsers.SAXParserFactory","com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl");
【讨论】:
这对我有用。你能解释一下它到底是做什么的吗? 如果你不能重建 java.lang.在 jruby 中使用java.lang.System.setProperty("org.xml.sax.driver", "com.sun.org.apache.xerces.internal.parsers.SAXParser");
等。
系统属性“jdk.xml.entityExpansionLimit”被我忽略了,直到我在底部设置了这三个属性。谢谢,你救了我的包子......但是为什么我必须设置解析器属性才能让“jdk.xml.entityExpansionLimit”等其他属性生效?【参考方案7】:
Xerces impl 是这里的罪魁祸首。去掉它。 jdk内置了jaxb解析器,你不需要这个。
所以,如果该依赖项来自父项目(在 maven 的情况下) 使用排除选项卡以防您无法直接删除它。
<exclusion>
<groupId>xerces</groupId>
<artifactId>xercesImpl</artifactId>
</exclusion>
这个问题很难被发现的原因是,当你通常编写一个 jaxb 解组代码时
您将对 try 块进行解组,然后捕获 jaxb 异常,然后对错误执行任何操作。
但是这个 jar (xercesimpl) 的罪魁祸首解析器在中间抛出了一个运行时异常,导致错误不会 被记录下来,只有在仔细调试后才会被检测到。看下面的代码sn-p
try
JAXBContext context = JAXBContext.newInstance(YourClass.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
YourClass object = (YourClass)unmarshaller.unmarshal(new StringReader("SomeXmlInString"));
catch (JAXBException e)
e.printStackTrace();
这里的 xercesImpl 导致解组器使用其他一些 sax 解析器(而不是常规的 jaxb 解析器) 导致它抛出不同的异常 不会被我们的 catch 块捕获,该块期待 jaxbexception 或其子类之一。
【讨论】:
对于未来的访问者:mvn dependency:tree -Dverbose -Dincludes=xerces
。现在阅读树以找出正在加载它的依赖项。
在我们的例子中,排除 xercesImpl
像上面的依赖 jaxen:jaxen
修复了构建。
对我来说它来自junit-addons:junit-addons
【参考方案8】:
尝试创建一个 XML 文档并解组它。它对我有用。 JAXBContext jc = JAXBContext.newInstance( Message.class );
InputStream stream = new ByteArrayInputStream( string.getBytes( StandardCharsets.UTF_8 ) );
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse( stream );
Unmarshaller unmarshaller = jc.createUnmarshaller();
Message msg = ( Message ) unmarshaller.unmarshal( doc );
【讨论】:
如下所述,它是/是一个依赖问题,在我的情况下是 jcs。如此普通的代码总是运行良好。【参考方案9】:Bernard 和 Blaise 的回答都非常有帮助。就我而言,由于我使用的是 JDK 7,因此解决方案是排除我的一个依赖项包含的 xerces 子依赖项:
<dependency>
<groupId>org.apache.axis</groupId>
<artifactId>axis</artifactId>
<version>1.4.1-SNAPSHOT</version>
<exclusions>
<exclusion>
<groupId>xerces</groupId>
<artifactId>xercesImpl</artifactId>
</exclusion>
<exclusion>
<groupId>xerces</groupId>
<artifactId>xmlParserAPIs</artifactId>
</exclusion>
</exclusions>
</dependency>
【讨论】:
【参考方案10】:我们遇到了类似的问题 - 我们的首席开发人员找到了适合我们的解决方案。
我们将此依赖项添加到几个 pom.xml 文件中
对于那些关心的人来说,Sonar 中失败的单元测试显然失败了,因为 Cobatura 默认情况下会引入旧版本的 xerces。它引入的版本与 Java 8 中的 JAX-B 不兼容。该库不用于生产代码——只是 Cobatura。因此,修复是在更新版本的 xerces (2.11.0) 上添加测试依赖项。这是通过将依赖项添加到 pom 文件来完成的:
<dependency>
<groupId>xerces</groupId>
<artifactId>xercesImpl</artifactId>
<version>2.11.0</version>
<scope>test</scope>
</dependency>
【讨论】:
C:\Java64\jdk1.8.0_60\jre\lib\rt.jar 中的 javax.xml.bind.JAXBContext 无法正常工作。解决方案是在 CLASSPATH 中使用早期版本的 xerces。在 pom.xml 中,将上述 xerces 2.11.0 依赖项插入到所有其他这是一个依赖问题。
这是我解决问题的方法:
-
创建一个新的 maven 项目,使用我在下面附加的那些简单代码,程序正常崩溃并出现错误,无法解析结构,这没关系。
将你的依赖项复制到项目 pom.xml 中,现在程序应该崩溃(如上所述)
不,你在你喜欢的方法(好猜测,Bisection,1-by-1 ..)之后删除依赖项以找到“坏”依赖项。也许有人有更好(更专业)的方法,这个对我有用。
现在你可以决定要做什么了,也许有新版本可用,在我们的例子中,它是一个大学自己的包,他包含一个大学的包,我可以排除。
public class Test
public Test()
public static void main(String[] args)
try
StringReader reader = new StringReader("<xml></xml>");
JAXBContext jc = JAXBContext.newInstance(TestXML.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
TestXML testXMLs = (TestXML) unmarshaller.unmarshal(reader);
catch (JAXBException e)
e.printStackTrace();
和 testXML 类
@XmlRootElement(name="rss")
@XmlAccessorType(XmlAccessType.FIELD)
public class TestXML
public TestXML()
@XmlElementWrapper(name="channel")
@XmlElement(name="item")
private int i ;
public int getI()
return i;
public void setI(int i)
this.i = i;
顺便说一句:在我的情况下是
<dependency>
<groupId>jcs</groupId>
<artifactId>jcs</artifactId>
<version>1.3</version>
</dependency>
希望对您有所帮助。
【讨论】:
这是您描述的一个有用的过程。但是获取有关在您的情况下导致此错误的依赖项的信息也很有用! @Lii 在我的例子中,它是 java 缓存系统org.apache.maven.plugins:maven-dependency-plugin:2.10:tree
【参考方案12】:
使用 SAXparser 可能是一场噩梦。这是 java 中使用最广泛的 XML 解析器,每个人最终都直接或间接使用。 JDK 8 已经提供了 JAXB。因此,如果您使用的是 JDK 8,那么唯一可能的方法应该是删除 maven 依赖项。 我也遇到了这个问题,所以我尝试删除 maven 依赖项,但没有发生。然后我想如果 java 和 VOILLA 我成功了,为什么不恢复到旧版本。我目前正在使用 jdk 7,并且我的测试运行顺利。我想这是唯一的解决方案。
【讨论】:
降级是/不是一种选择。但我发现了导致问题的依赖性。 如果不深入调查原因,我认为建议使用旧版本的 java 是不好的。【参考方案13】:Java SE 自版本 6 起就包含了 JAXB 的实现。如果您删除 Maven 依赖项(这可能会导致版本冲突),一切都应该正常工作。
【讨论】:
Mhhh ...谢谢,因为我很绝望,我添加了依赖项来解决问题,但没有任何改变。我删除了它,但结果仍然相同。我编辑了我的问题。 @mmx73 - 在没有 Maven 的情况下运行示例时,您是否看到同样的问题? 你认为这是一个依赖问题吗?也许我可以设置一个简单的项目,只运行一个小型 XML 解析器程序。我会在周末试试这个然后回来。 @mmx73 - 是的,我认为这是一个依赖问题。 @blaise_doughan :你是对的,这是一个依赖问题。我将用我发现的解决方案自己回答我的问题。感谢您的帮助。以上是关于在 java-8“安全处理 org.xml.sax.SAXNotRecognizedException 导致 java.lang.IllegalStateException”中解组 xml 时出错的主要内容,如果未能解决你的问题,请参考以下文章