Javax Transformer在高并发环境中失败

Javax Transformer在高并发环境中失败,java,xslt,singleton,transformer,Java,Xslt,Singleton,Transformer,我有一个带有单例Bean的平台,在这里我加载了一个Transformer实例(因为xslt太大了,所以每次请求都要创建一个实例) 在正常负载下,一切工作正常,但在对大量并发请求进行压力测试时,转换器开始抛出ArrayIndexOutOfBoundsException并停止工作,因此我必须重新启动服务器实例或重新部署应用程序 这是部署应用程序时创建实例的方式: private Transformer createCFDI33TransformerInstance() {

我有一个带有单例Bean的平台,在这里我加载了一个Transformer实例(因为xslt太大了,所以每次请求都要创建一个实例)

在正常负载下,一切工作正常,但在对大量并发请求进行压力测试时,转换器开始抛出ArrayIndexOutOfBoundsException并停止工作,因此我必须重新启动服务器实例或重新部署应用程序

这是部署应用程序时创建实例的方式:

private Transformer createCFDI33TransformerInstance() {

            InputStream in = new URL("http://www.sat.gob.mx/sitio_internet/cfd/3/cadenaoriginal_3_3/cadenaoriginal_3_3.xslt").openStream();

            TransformerFactory factory = TransformerFactory.newInstance();            
            Transformer transformer
                    = factory.newTransformer(new StreamSource(in));
            Logger.getLogger(PadeSingleton.class.getName()).log(Level.INFO, " Se ha cargado la instancia de XSLT");
            return transformer;
        } catch (TransformerConfigurationException | IOException ex) {
// Loading a remote instance was not possible so I will load a local instance
            Logger.getLogger(PadeSingleton.class.getName()).log(Level.SEVERE, "No fue posible cargar una nueva instancia de cadena original, se usara la del sistema", ex);
            InputStream in = CFDIv33Tools.class.getClassLoader()
                    .getResourceAsStream("com/soft/cadenaoriginal_3_3.xslt");

            TransformerFactory factory = TransformerFactory.newInstance();
            Transformer transformer;
            try {
                transformer = factory.newTransformer(new StreamSource(in));
                Logger.getLogger(PadeSingleton.class.getName()).log(Level.WARNING, "No fue posible cargar la instancia, se cargara una local");
            } catch (TransformerConfigurationException ex1) {
                Logger.getLogger(PadeSingleton.class.getName()).log(Level.SEVERE, null, ex1);
                // Estamos en problemas 
                throw new Exception("Error critico");
            }
            return transformer;
        }
    }
所以在另一个bean中,我注入我的单例bean并调用一个方法来获取我的Transformer实例

public static String transform(String xml, Transformer instance) throws Exception {

        StringWriter writer = new StringWriter();

        try {

            instance.transform(new StreamSource(new StringReader(xml)), new StreamResult(writer));

        } catch (TransformerException e) {
            throw new Exception("El comprobante contiene simbolos no permitidos o esta mal formado", e);
        }

        return writer.toString();
    }
在这个方法中,我得到ArrayIndexOutOfBoundsException

Caused by: javax.xml.transform.TransformerException: java.lang.ArrayIndexOutOfBoundsException: -1
    at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:746)
    at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:351)
    at com.icontech.pade.common.xml.tools.CFDIv33Tools.calcularCadenaOriginalV2(CFDIv33Tools.java:93)
    ... 138 more

我重复在进行压力测试时发生的情况,当抛出此异常时,以下请求失败,出现相同的异常。我想我的实例已损坏。。或者别的什么。

变压器不是线程安全的。您应该创建一个表示已编译样式表的
Templates
对象,然后为每个转换实例化一个新的Transformer对象


(原则上,转换器是串行可重用的,因此在一次转换完成后,您可以在同一个线程中重用一个转换器。我不知道使用Xalan这样做是否有任何好处;在Saxon的情况下,最好每次都创建一个新的转换器。)

转换器不是线程安全的。您应该创建一个表示已编译样式表的
Templates
对象,然后为每个转换实例化一个新的Transformer对象


(原则上,转换器是串行可重用的,因此在一次转换完成后,您可以在同一线程中重用一个转换器。我不知道使用Xalan这样做是否有任何好处;在Saxon的情况下,最好每次都创建一个新的转换器。)

那么,这到底是哪个Java版本?您是否试图找到该Java版本的源代码,以检查
TransformerImpl.Java
的第746行中发生了什么?您尝试过不同的Java版本吗?您是否尝试过不同的XSLT实现,如Saxon 9?听起来很相似,但似乎是固定的,所以您可能需要更新Java版本。您好!我使用的是OracleJDK1.8.0—那么这到底是哪个Java版本?您是否试图找到该Java版本的源代码,以检查
TransformerImpl.Java
的第746行中发生了什么?您尝试过不同的Java版本吗?您是否尝试过不同的XSLT实现,如Saxon 9?听起来很相似,但似乎是固定的,所以您可能需要更新Java版本。您好!我正在使用OracleJDK1.8.0_151