【问题标题】:Parsing XML in XFire cause CPU high?在 XFire 中解析 XML 会导致 CPU 高吗?
【发布时间】:2014-03-26 08:34:38
【问题描述】:

我的服务器正在使用 XFire 来处理 Web 服务请求

但它的 CPU 被占用高达 100% 甚至 1000%

当我重新启动服务器并经过一些请求后,这个奇怪的问题又出现了

我扫描线程转储,占用CPU的线程是这样的:

httpWorkerThread-18028-39" daemon prio=10 tid=0xa0832800 nid=0x1d89 runnable [0x99e69000]
java.lang.Thread.State: RUNNABLE
at com.sun.xml.stream.XMLDocumentScannerImpl$PrologDriver.next(XMLDocumentScannerImpl.java:892)
at com.sun.xml.stream.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:362)
at com.sun.xml.stream.XMLReaderImpl.next(XMLReaderImpl.java:568)
at org.codehaus.xfire.soap.handler.ReadHeadersHandler.invoke(ReadHeadersHandler.java:44)
at org.codehaus.xfire.handler.HandlerPipeline.invoke(HandlerPipeline.java:131)
at org.codehaus.xfire.transport.DefaultEndpoint.onReceive(DefaultEndpoint.java:64)
at org.codehaus.xfire.transport.AbstractChannel.receive(AbstractChannel.java:38)
at org.codehaus.xfire.transport.http.XFireServletController.invoke(XFireServletController.java:304)
at org.codehaus.xfire.transport.http.XFireServletController.doService(XFireServletController.java:129)
at org.codehaus.xfire.transport.http.XFireServlet.doPost(XFireServlet.java:116)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:753)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:846)

看起来XFire是在解析一个XML文件,但随着时间的推移,线程转储并没有什么不同,线程就像在无限循环中。

但是,我对 XFire 没有足够的经验,我无法弄清楚问题的原因

我google了很多,发现这个topic的现象和我的一样

但是,这个主题表明它可能是一个 JVM 错误并且使用 JDK5 而不是 JDK6。我正在尝试使用 JDK5 看看它是否会有所帮助

有人遇到过这样的问题吗?是什么导致了这个问题以及如何解决?

非常感谢。

【问题讨论】:

    标签: java xml performance web-services xfire


    【解决方案1】:

    最后,我解决了这个问题。

    造成这个问题的原因是JDK6 XMLStreamReader实现的错误,正如topic所说。

    如何解决?

    我阅读了XFire的源代码,答案就在这段代码中:

    XMLStreamReader reader = 
                STAXUtils.createXMLStreamReader(request.getInputStream(), 
                                                charEncoding,
                                                context);
    

    STAXUtils.createXMLStreamReader 将创建 XMLInputFactory 以生成 XMLStreamReader。

    public static XMLInputFactory getXMLInputFactory(MessageContext ctx)
    {
        if (ctx == null) return xmlInputFactory;
    
        Object inFactoryObj = ctx.getContextualProperty(XFire.STAX_INPUT_FACTORY);
    
        if (inFactoryObj instanceof XMLInputFactory)
        {
            return (XMLInputFactory) inFactoryObj; 
        }
        else if (inFactoryObj instanceof String)
        {
            String inFactory = (String) inFactoryObj;
            XMLInputFactory xif = (XMLInputFactory) factories.get(inFactory);
            if (xif == null)
            {
                xif = (XMLInputFactory) createFactory(inFactory, ctx);
                configureFactory(xif,ctx);
                factories.put(inFactory, xif);
            }
            return xif;
        }
    
        if(!inFactoryConfigured){
            configureFactory(xmlInputFactory,ctx);
            inFactoryConfigured=true;
        }
    
    
    
        return xmlInputFactory;
    }
    

    在这段代码中,你可以配置“xfire.stax.input.factory”XFire属性来生成XMLInputFactory,它的XMLStreamReader没有bug,但是我不知道如何设置这个属性。

    在我的项目中,xmlInputFactory 是 JDK 的默认 xmlInputFactory。

     /**
    * Create a new instance of the factory.
    * This static method creates a new factory instance. 
    * This method uses the following ordered lookup procedure to determine 
    * the XMLInputFactory implementation class to load: 
    * Use the javax.xml.stream.XMLInputFactory system property. 
    * Use the properties file "lib/stax.properties" in the JRE directory. 
    * This configuration file is in standard java.util.Properties format and contains 
    * the fully qualified name of the implementation class with the key being the system property defined above. 
    * Use the Services API (as detailed in the JAR specification), if available, to determine the classname. 
    * The Services API will look for a classname in the file META-INF/services/javax.xml.stream.XMLInputFactory 
    * in jars available to the runtime. 
    * Platform default XMLInputFactory instance. 
    * Once an application has obtained a reference to a XMLInputFactory 
    * it can use the factory to configure and obtain stream instances. 
    *
    * @throws FactoryConfigurationError if an instance of this factory cannot be loaded
    */
    public static XMLInputFactory newInstance()
      throws FactoryConfigurationError
    {
        return (XMLInputFactory) FactoryFinder.find(
      "javax.xml.stream.XMLInputFactory",
      "com.sun.xml.internal.stream.XMLInputFactoryImpl");
    }
    

    因此,您可以使用 javax.xml.stream.XMLInputFactory 系统属性来使用另一个 XMLInputFactroy,例如 wstx lib。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多