【问题标题】:Error unmarshalling xml in java-8 "secure-processing org.xml.sax.SAXNotRecognizedException causing java.lang.IllegalStateException"在 java-8“安全处理 org.xml.sax.SAXNotRecognizedException 导致 java.lang.IllegalStateException”中解组 xml 时出错
【发布时间】: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 中)

欢迎任何提示,非常感谢。

【问题讨论】:

    标签: java xml-parsing jaxb java-8


    【解决方案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 依赖项插入到所有其他 之上,因此它具有更高的优先级以被 Java 8 获取。
              • 对于 Jdk v1.8.0_181 和 Jaxb v2.2.11 和 xercesIml v2.11.0,此解决方案不起作用
              • 这对我不起作用。我也测试了 2.12.0 版,但不起作用!我的 java 版本是 1.8.0_202
              【解决方案11】:

              这是一个依赖问题。

              这是我解决问题的方法:

              1. 创建一个新的 maven 项目,使用我在下面附加的那些简单代码,程序正常崩溃并出现错误,无法解析结构,这没关系。
              2. 将你的依赖项复制到项目 pom.xml 中,现在程序应该崩溃(如上所述)

              3. 不,你在你喜欢的方法(好猜测,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 缓存系统 jcsjcs1.3
              • > “也许有人有更好(更专业)的方法” 那就是使用 Maven 依赖插件并简单地寻找 Xerces。 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 :你是对的,这是一个依赖问题。我将用我发现的解决方案自己回答我的问题。感谢您的帮助。
              猜你喜欢
              • 2014-07-20
              • 2023-03-22
              • 2011-08-30
              • 1970-01-01
              • 2015-09-26
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2014-06-13
              相关资源
              最近更新 更多