2012-02-02 17 views
7

¿Es javax.xml.XPathFactory.newInstance() thread-safe?Java XPathFactory thread-safety

Pregunto porque la documentación me parece ambigua. The JDK 5 docs no mencionen la seguridad de hilos en absoluto; en JDK 6 escribieron lo siguiente:

La clase XPathFactory no es segura para subprocesos. En otras palabras, es responsabilidad de la aplicación asegurarse de que como máximo un hilo sea usando un objeto XPathFactory en cualquier momento dado. Las implementaciones son recomendadas para marcar los métodos como sincronizados para protegerse de clientes rotos.

lo que tengo entendido, no es seguro tener una implementación Singleton para XPathFactory, pero haciendo algo como esto debe ser seguro:

XPath xPathEvaluator = XPathFactory.newInstance().newXPath(); 

Me estoy perdiendo algo? ¿Depende de la clase real que lo extiende? ¿Necesito synchronize el método que contiene la declaración anterior?

Respuesta

11

XPath xPathEvaluator = XPathFactory.newInstance(). NewXPath();

Eso es seguro, porque cada hilo tiene su propia fábrica (gracias a newInstance()). No hay necesidad de sincronizar aquí.

Lo que no se puede hacer con seguridad es obtener la fábrica una sola vez, y luego compartirla entre hilos sin sincronización, por ejemplo como singleton. Lo mismo aplica para la instancia de XPath (xPathEvaluator).

+0

Gracias, estaba pensando lo mismo, pero quería volver a asegurar :). –

+1

Siempre aquí para tomarse de las manos :-) – Thilo

+5

Hay muchas cosas malas sobre el diseño de JAXP-XPath. Uno de ellos es que XPathFactory.newInstance() es muy caro; otra es que se espera que lo llames repetidamente en cada hilo. Otra es que no tiene forma de saber si recibirá un motor XPath 1.0 o un motor XPath 2.0. Pregúntese si realmente desea utilizar este mecanismo: si sabe qué motor XPath desea, existen mejores formas de cargarlo. –

3

"Una de ellas es que XPathFactory.newInstance() es muy caro;"

True statement! Me di cuenta de que para cada hilo llamando newInstance(), jaxp.properties deben estar ubicados en la ruta de clase y leer en:

java.lang.Thread.State: BLOCKED (on object monitor) 
     at java.util.zip.ZipFile.getEntry(ZipFile.java:160) 
     - locked <0x0000000968dec028> (a sun.net.www.protocol.jar.URLJarFile) 
     at java.util.jar.JarFile.getEntry(JarFile.java:208) 
     at sun.net.www.protocol.jar.URLJarFile.getEntry(URLJarFile.java:107) 
     at sun.net.www.protocol.jar.JarURLConnection.connect(JarURLConnection.java:114) 
     at sun.net.www.protocol.jar.JarURLConnection.getInputStream(JarURLConnection.java:132) 
     at java.net.URL.openStream(URL.java:1010) 
     at javax.xml.xpath.SecuritySupport$4.run(Unknown Source) 
     at java.security.AccessController.doPrivileged(Native Method) 
     at javax.xml.xpath.SecuritySupport.getURLInputStream(Unknown Source) 
     at javax.xml.xpath.XPathFactoryFinder._newFactory(Unknown Source) 
     at javax.xml.xpath.XPathFactoryFinder.newFactory(Unknown Source) 
     at javax.xml.xpath.XPathFactory.newInstance(Unknown Source) 
     at javax.xml.xpath.XPathFactory.newInstance(Unknown Source) 

ZipFile hace una llamada nativa (a zlib creo) y descomprime el frasco, que necesita de disco IO y procesador de compresión de descompresión comprimida. En este caso, teníamos más de 1400 subprocesos esperando en ese bloqueo.