GDI Object consumption
Hello Guys,
I would like to ask the gurus here about a problem I am experiencing. I am writing a Java 1.4.0 application, and in certain occasions I experience consumption of GDI objects. I see this using the Windows Task Manager. No other problem at all, like memory leak, or handles increasing - only the GDI object count rises. After 16 hours I reach the 10,000 GDI object limit and Windows messes up the screen.
I have the whole screen divided in several different canvases. I update every canvas only when needed, with explict calls to my render() routine. Here is a code sample for one object:
(...)
publicvoid redraw(){
render(screen);
}
publicvoid update(Graphics g){
paint(g);
}
publicvoid paint(Graphics g){
createBufferStrategy(1);
this.bs = getBufferStrategy();
this.screen = (Graphics2D)bs.getDrawGraphics();
render(screen);
}
publicvoid render(Graphics2D g2){
// allocates an offscreen region once
// after that, does all drawing offscreen normally
// finally, copy the whole offscreen image to the video memory
g2.drawImage(offscr,0,0,this);
}
So far, no big deal. I call a object.repaint() once on startup, to initialize the BufferStrategy, after that, I should be able to use only redraw().
However, the strange part is that when I call object.redraw() in my application, I have this GDI leak. If I replace the call with object.repaint(), everything seems fine. But I can't use repaint() because the game loses synchronization between the panels, and the gameflow becomes chaotic.
So what am I missing here? I have the same result with active and passive rendering (ie., without BufferStrategy, using simple double buffering). I know that there is a confirmed GDI leak in the 1.4Plug-in, but nothing is said about the JRE/JDK. Any ideas?
Ulrich
[2532 byte] By [
upeters] at [2007-9-27 19:59:49]

Hello, thank you for your thoughts.
Unfortunately, the lack of a dispose() is not be the cause of my problem. I placed it there, and still have the exact same behavior...
The problem is that I call redraw() several times, and I have no GDI consumption at all. Then, in certain points in the code, the next redraw() on that canvas causes the creation of a new GDI. If I place a repaint() at that point, the GDI is not created there, but in another place in the code where another redraw() can be found (and which did not cause a GDI consumption in the loop before). This is starting to drive me mad...
When executing the code in a debugger, the GDI object is created at the moment when I copy my offscreen buffer to the screen. But those memory regions were created when I first displayed the component, and reused on all screen updates since then.
As stupid as it seems, it *looks* like that a new GDI object is allocated each time a different thread updates the canvas. I have a demo loop, and when the demo is over comes a short pause, then a new demo loop starts, redrawing a new sequence of events on the same canvas. In the moment the new thread updates the canvas I have a new GDI object listed in the Task Manager. The count does not increase until the end of the cycle. When the next demo starts, I get again one more GDI. Now does this sound strange or what?
Ulrich
Hello again Abuse, and thanks for replying.
I don't believe in anything (Windows version, video driver) anymore. The same problem happens in the same way on anther PC, with different hardware and Win2000 instead of XP. It *might* be problem in the current JVM. Or I just did something very stupid and I don't see it.
I think I was right about the threads. I recoded a new project, using the same architecture as my current work (which is much too large to post), but even with the small example, I am able to consume GDI objects. It is like I said: each time a new *thread* tries to update the component, a new GDI is trashed. For my current application, this means certain death, because it is build to run for weeks without shutdown.
Anyone who is interested in the GDI consumption problem may download the bare-bones Eclipse project I placed on my server at http://www.mindquake.com.br/files/GDIConsumptionTest.zip
It works this way: Each thread updates the image 10 times. The first time the thread updates the image, a new GDI object is created. Check it monitoring GDI in the Windows Task Manager (select Processes, if you don't see GDI, select it with View - Select Columns).
I can't get rid of the threads in my current application. Each thread is for one game pass, and when the game cycle is over, a new thread must be created to start everthing again, it doesn't just update the several canvases...
Please post suggestions (or instructions how to tell Sun about this problem, if you can confirm it). I have to stop this GDI stuff *now*.
Ulrich