Community
Participate
Working Groups
I have a large diagram in GEF/Draw2d: 7000x7000 px. I want export this diagram to a jpeg/png. Normally I do this with the following steps: Image image = new Image(display, 7000, 7000); // ... paint figures from GEF diagram in image ImageData imageData = image.getImageData(); ImageLoader loader = new ImageLoader(); loader.data = new ImageData[] { imageData }; loader.save("c:/temp/newImage.png", SWT.IMAGE_PNG); With this large diagram I've got the following exception: org.eclipse.swt.SWTError: No more handles at org.eclipse.swt.SWT.error(SWT.java:4308) at org.eclipse.swt.SWT.error(SWT.java:4197) at org.eclipse.swt.SWT.error(SWT.java:4168) at org.eclipse.swt.graphics.Image.getImageData(Image.java:1463) In the Image class I've found this: int /*long*/ lpvBits = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, imageSize); if (lpvBits == 0) SWT.error(SWT.ERROR_NO_HANDLES); It seems there is a problem with the memory allocation. But I've checked it and there is enough heap memory available. I need ~186 MB for the image model and on the heap there are more then 500 MB available. If I take smaller images this method works fine: Image image = new Image(display, 5000, 5000); // ... paint figures from GEF diagram in image ImageData imageData[]=new ImageData[4]; for (int i = 0; i < imageData.length; i++) { imageData[i] = image.getImageData(); } In this case I've allocated 380 MB (95 MB for each of these 4 image models) without any problem. Please can you improve the implementation of the method org.eclipse.swt.graphics.Image.getImageData() so it can handle also larger images? 10K*10K px should be enough for us. Or do you have another idea how we can export diagrams without using ImageData/ImageLoader? BR, Matthias
(In reply to comment #0) > I need ~186 MB for the image model and > on the heap there are more then 500 MB available. How did you check ? Runtime.getRuntime().freeMemory(); ? I don't know how the VM manages the memory in this case. That is memory available for the VM to store java objects. Silenio, is it possible that the VM is reserving this memory so that it is to available to other malloc calls such as OS.HeapAlloc() ?
(In reply to comment #1) > (In reply to comment #0) > > I need ~186 MB for the image model and > > on the heap there are more then 500 MB available. > > How did you check ? Runtime.getRuntime().freeMemory(); ? > > I don't know how the VM manages the memory in this case. That is memory > available for the VM to store java objects. I just talked to VM expert from the J9 team. That memory returned by Runtime.getRuntime().freeMemory() is reserved up front by the VM, and can not be touched by other alloc methods. Try to decrease the size of the java heap, and try again. Let me know it that helps. "You cannot directly set the size of the process heap. Instead, the process heap uses memory within the 32-bit address space that is not used by the garbage-collected heap. To increase the size of the process heap, decrease the maximum Java heap size (-Xmx option)." Note that HeapAlloc() can also fail when you are out of address space.
I released code the has a good probability of fixing your problem on VMs that support memory pinning (which is very common now a days). Instead of allocating memory in the C heap to get the image bits, the java array (already allocated) is used directly using JNI GetPrimitiveArrayCritical(). http://git.eclipse.org/c/platform/eclipse.platform.swt.git/commit/?id=270369a2774c9adb72d20072ee39a162882a5dda Please give this a try (next integration build) and reopen the bug if it is not fixed. Or provide a testcase that reproduces the problem so that I can confirm it. Out of curiosity, how is your application launched? Do you use the eclipse launcher (eclipse.exe) or java.exe directly? The reason I ask is because there is a difference between the way eclipse.exe and java.exe are compiled with respect to large address spaces (LargeAddressAware flag). The code might work if you run with java.exe instead eclipse.exe.
(In reply to comment #3) > I released code the has a good probability of fixing your problem on VMs that > support memory pinning (which is very common now a days). Instead of > allocating memory in the C heap to get the image bits, the java array (already > allocated) is used directly using JNI GetPrimitiveArrayCritical(). > http://git.eclipse.org/c/platform/eclipse.platform.swt.git/commit/?id=270369a2774c9adb72d20072ee39a162882a5dda > Please give this a try (next integration build) and reopen the bug if it is not > fixed. Or provide a testcase that reproduces the problem so that I can confirm > it. Thanks, we will test it and provide feedback. Probably in Juno M4 only, since the colleague working on that is on vacation now. > Out of curiosity, how is your application launched? Do you use the eclipse > launcher (eclipse.exe) or java.exe directly? The reason I ask is because there > is a difference between the way eclipse.exe and java.exe are compiled with > respect to large address spaces (LargeAddressAware flag). The code might work > if you run with java.exe instead eclipse.exe. How the final application is started is open; we (Graphiti project) offer a graphical framework that supports printing and saving diagrams using this. We stumbled over this in our tutorial application, which is started using standard eclipse.exe