NOTICE: This version of the NSF Unidata web site (archive.unidata.ucar.edu) is no longer being updated.
Current content can be found at unidata.ucar.edu.
To learn about what's going on, see About the Archive Site.
I have mostly tried to use visad for offscreen rendering, from servlets in web apps. The intention was DisplayImpl di = new DisplayImplJ2D( "", w, h ); BufferedImage bi = di.getImage(true); di.destroy(); As you would expect, we want the net memory footprint of the above sequence to be just the BufferedImage, which we can save to disk or use a servlet to serialize to some web client. Thus the net footprint is then zero. This is vital in a long lived app like a web site. I have always had problems, frequently exhausting memory. I should point out that I am trying to render some large images, on the order of 6000 x 6000, but really that is beside the point, it just makes the outofmemory occur earlier. Finally, after about 3 years of looking at this, I think have a solution. It now seems obvious why it was failing at all. In VisADCanvasJ2D, we have stop() { renderThread =null; } and run() { while ( renderThread != null ) { do some work; wait for more work; } The problem is that the stop code is not powerful enough to halt the run code. At any given point in time, the run code (the renderThread) can be anywhere in its loop. If it is in wait, it will stay there forever. The thread is live, thus the canvas it references (the Runnable) is also, and so are any BufferedImages we have built. we cannot GC any of it. We need to raise an interrupt in this thread. This will get us out of a wait call, if the interrupt is posted either before or during the wait. I think the soln is this volatile boolean done = false; stop () { done = true; renderThread.interrupt(); renderThread.join(); } run() { while( !done ) { try { do some work; wait; } catch( InterruptedException ie ) { } } } This makes the calling program , which calls stop via the DisplayImpl.destroy(), wait for the renderThread to finish. We need the boolean done, we cannot do this from stop: renderThread.interrupt(); renderThread = null; since the run could get the interrupt, test the renderThread for non null and do another wait, all before the stop can set the renderThread to null ( i have tested this and seen it occur). Initially i coded the joining of the calling (application) thread and renderThread using a CountdownLatch set to 1, from java.util.concurrent, with stop doing a latch.await() and run doing a latch.countDown() as its final action, but the thread join seems equivalent to that (anyone??). One caveat of raising the interrupt on the renderThread is that somewhere in the 'do some work' the newly raised interrupt can lead to an abort of the work. But we dont really care, since we have got our image via getImage and then called destroy in that order. I hope this helps anyone trying to use Visad in offscreen mode, particularly in webapps. Comments welcomed. Stuart
visad
archives: