Win a copy of Mesos in Action this week in the Cloud/Virtualizaton forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

XSLT transormation issue in loop

 
raj jitu malhotra
Greenhorn
Posts: 3
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I have the XSLT transformation code as follows which works without any issue for a given set of files

for (File xmlFile : files) {
transformer = tFactory.newTransformer(new StreamSource(strStylesheet));
FileOutputStream os = new FileOutputStream(new File(outputDirs + "/" + xmlFile.getName()));
transformer.transform(new StreamSource(xmlFile), new StreamResult(os));
}


As a part of code re factoring i moved the transformer creation part out of the loop. i.e.

transformer = tFactory.newTransformer(new StreamSource(strStylesheet));
for (File xmlFile : files) {
FileOutputStream os = new FileOutputStream(new File(outputDirs + "/" + xmlFile.getName()));
transformer.transform(new StreamSource(xmlFile), new StreamResult(os));
}


I think the 2nd code snippet is the correct way to invoke the transformer on the set of files. However when i run this code on the same set of files, i get a OutOfMemory Exception.

Can any one let me know why i don't get a memory exception with first snippet when a new transformer is created for every iteration?
Is there something additional i need to take care of while doing the transformation?

StackTrace:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at net.sf.saxon.tinytree.TinyTree.ensureAttributeCapacity(TinyTree.java:250)
at net.sf.saxon.tinytree.TinyTree.addAttribute(TinyTree.java:538)
at net.sf.saxon.tinytree.TinyBuilder.attribute(TinyBuilder.java:263)
at net.sf.saxon.event.ReceivingContentHandler.startElement(ReceivingContentHandler.java:361)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startElement(AbstractSAXParser.java:501)
at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanStartElement(XMLNSDocumentScannerImpl.java:400)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2756)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:648)
at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:140)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:511)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:808)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:737)
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:119)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1205)
at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:522)
at net.sf.saxon.event.Sender.sendSAXSource(Sender.java:354)
at net.sf.saxon.event.Sender.send(Sender.java:184)
at net.sf.saxon.event.Sender.send(Sender.java:49)
at net.sf.saxon.Controller.transform(Controller.java:1550)
 
Jimmy Clark
Ranch Hand
Posts: 2187
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I think the 2nd code snippet is the correct way to invoke the transformer on the set of files. However when i run this code on the same set of files, i get a OutOfMemory Exception.


Why do you think the 2nd code is the the "correct" way? What is the basis for your opinion?

Can any one let me know why i don't get a memory exception with first snippet when a new transformer is created for every iteration?


Why do you think that you should have a memory usage problem? Do you know exactly how TransformerFactory or Transformer work? ... the inner details?
 
raj jitu malhotra
Greenhorn
Posts: 3
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Jimmy,

1. as a generic rule i think we have to move any operation which doesn't change inside the loop, outside.

2. as a transformer is created again and again there should be more object creation (memory allocation/de-allocation) in first snippet than the 2nd snippet.
 
Paul Clapham
Sheriff
Posts: 21107
32
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
raj jitu malhotra wrote:2. as a transformer is created again and again there should be more object creation (memory allocation/de-allocation) in first snippet than the 2nd snippet.


Indeed that's correct -- as far as your code is concerned. What is happening is that the Transformer caches various things that it produces. And then when you reuse it, it caches more of those things. Eventually you run out of memory. But reducing the number of objects created is usually a pointless goal. Especially in your case, where you were trying to avoid creating a single object in a loop which would normally create hundreds or thousands of objects. Try to keep things in perspective in the future.

Anyway, last time I went through the tutorials about XSLT in Java, the recommendation was to cache a Templates object rather than a Transformer object. If you really find you have to optimize things, then that would be the way to go. But don't bother until you really find you have to optimize things.
 
raj jitu malhotra
Greenhorn
Posts: 3
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
thanks paul, that helps...

can you elaborate on your point.....
But reducing the number of objects created is usually a pointless goal.
 
Jimmy Clark
Ranch Hand
Posts: 2187
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You attempted to reduce the number of objects created in a for loop and broke the code with a OutOfMemory Exception. In reality, your refactoring ended up creating more objects in the JVM. Sounds pointless to me...
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic