I wrote an application that uses GraphViz to generate some graphs as .gif’s according to the DOT syntax. When I run from Eclipse the images are generated fine but when I export it as a jar the images are created but there is no data in them. When I view them in Microsoft Picture Viewer its just the red X.
It was working as an exported jar until I put the picture generation in its own thread. I can’t seem to figure out whats going on here. Are there any problems exporting multi-threaded projects? Any one have any ideas?
Thanks
Here is some of the code. Its hard to pin point what is going wrong.
/**
* Writes the graph's image in a file.
* @param img A byte array containing the image of the graph.
* @param to A File object to where we want to write.
* @return Success: 1, Failure: -1
*/
public int writeGraphToFile(byte[] img, File to)
{
try {
FileOutputStream fos = new FileOutputStream(to);
fos.write(img);
fos.close();
} catch (java.io.IOException ioe) { return -1; }
return 1;
}
The above function is called from an alternate thread by this call.
public void generateMainGraph() {
//create the graph and put it to file name mainGraphCount.gif
GraphViz gv = new GraphViz();
System.out.println("Generating MAIN graph...");
//add the ending } to mainDot
mainDot += "}";
File newGraph = new File("graphs\\main" + Integer.toString(mainGraphCount) + ".gif");
gv.writeGraphToFile(gv.getGraph(mainDot), newGraph);
}
Here is the thread that calls the function which makes the call to generateMainGraph(…).
graphGeneratingThread = new Runnable() {
//This method will run in the timer thread
public void run() {
try {
//Generate the graphs
if (iData.importDataSet()) {
int timeout = 0;
Scanner scan = new Scanner(graphGen.logSource);
while(timeout < 10) {
if(!scan.hasNextLine()) {
Thread.sleep(1000);
timeout++;
} else {
timeout = 0;
graphGen.generateGraph(scan.nextLine()); //This function calls generateMainGraph(...)
if(!beginningButton.isEnabled()) {
enableTivoButtons();
}
}
}
}
} catch(Exception exc) {
System.err.println("GraphGenerationThread Runnable Error: " + exc.getMessage() + "\n");
exc.printStackTrace();
System.exit(1);
}
}
};
It does not make a difference if a project is multithreaded or not when you export it. Differences are cause by how the threads are being scheduled by the VM (which may be effected by running inside of eclipse).
Since your problem is with the threaded version my guess is you have internal object state that is being corrupted in the middle of the operation of one thread by another thread. For example:
this would be an explanation for a 0 byte image. Another scenario:
This would be a cause of a corrupt image file. Debugging concurrent code can be tricky. My suggestion is:
If you are looking for a “simple solution” after you find code that can be run by more than thread at once and effect your data simply make that method synchronized, however that will likely defeat what you are trying to achieve in adding the Threads.