theJuddson
theJuddson

Reputation: 41

Is there any way to force JavaFX to release video memory?

I'm writing an application leveraging JavaFX that scrolls a large amount of image content on and off of the screen every 20-30 seconds. It's meant to be able to run for multiple hours, pulling in completely new content and discarding old content every couple minutes. I have 512Mb of graphics memory on my system and after several minutes, all of that memory has been consumed by JavaFX and no matter what I do with my JavaFX scene, none of it is released. I've been very careful to discard nodes when they drop off of the scene, and at most I have 50-60 image nodes in memory at one time. I really need to be able to do a hard release of the graphics memory that was backing these images, but haven't been able to figure out how to accomplish that, as the Image interface in JavaFX seems to be very high level. JavaFX will continue to run fine, but other graphics heavy applications will fail to load due to limited resources.

I'm looking for something like the flush() method on java.awt.image.Image: http://docs.oracle.com/javase/7/docs/api/java/awt/Image.html#flush()

I'm running java 7u13 on Linux.

EDIT:

I managed to work out a potential workaround ( see below ), but have also entered a JavaFX JIRA ticket to request the functionality described above:

RT-28661 Add explicit access to a native resource cleanup function on nodes.

Upvotes: 3

Views: 2753

Answers (2)

jewelsea
jewelsea

Reputation: 159406

Perhaps you are encountering behaviour related to the root cause of the following issue:

RT-16011 Need mechanism for PG nodes to know when they are no longer part of a scene graph

From the issue description:

Some PG nodes contain handles to non-heap resources, such as GPU textures, which we would want to aggressively reclaim when the node is no longer part of a scene graph. Unfortunately, there is no mechanism to report this state change to them so that they can release their resources so we must rely on a combination of GC, Ref queues, and sometimes finalization to reclaim the resources. Lazy reclamation of some of these resources can result in exceptions when garbage collection gets behind and we run out of these limited resources.

There are numerous other related issues you can see when you look at the issue page I linked (signup is required to view the issue, but anybody can signup).

A sample related issue is:

RT-15516 image data associated with cached nodes that are removed from a scene are not aggressively released

On which a user commented:

I found a workaround for my app just settihg up an using of cashe to false for all frequently using nodes. 2 days working without any crashes.

So try calling setCache(false) on your nodes.

Also try using a Java 8 preview release where some of these issues have been fixed and see if it increases the stability of your application. Though currently, even in the Java 8 branch, there are still open issues such as the following:

RT-25323 Need a unified Texture resource management system for Prism

Currently texture resources are managed separately in at least 2 places depending on how it is used; one is a texture cache for images and the other is the ImagePool for RTTs. This approach is flawed in its design, i.e. the 2 caches are unaware of each other and it assumes system has unlimited native resources.

Using a video card with more memory may either reduce or eliminate the issue.

You may also wish to put together a minimal executable example which demonstrates your issue and raise a bug request against the JavaFX Runtime project so that a JavaFX developer can investigate your scenario and see if it is new or a duplicate of a known issue.

Upvotes: 1

theJuddson
theJuddson

Reputation: 41

The best workaround that I could come up with was to set my JVM's max heap to half of the available limit of my graphics card. ( I have 512mb of graphics memory, so I set this to -Xmx256m ) This forces the GC to be more proactive in cleaning up my discarded javafx.image.Image objects, which in turn seems to trigger graphics memory cleanup on the part of JavaFX.

Previously my heap space was set to 512mb, ( I have 4gb of system memory, so this is a very manageable limit ). The problem with that seems to be that the JVM was being very lazy about cleaning up my images until it started approaching this 512mb limit. Since all of my image data was copied into graphics memory, this meant I had most likely exhausted my graphics memory before the JVM really started really caring about cleanup.

I did try some of the suggestions by jewelsea:

I am calling setCache(false), so this may be having a positive affect, but I didn't notice an improvement until I dropped my max heap size.

I tried running with Java8 with some positive results. It did seem to behave better in graphics memory management, but it still ate up all of my memory and didn't seem to start caring about graphics memory until I was almost out. If reducing your the application's heap limit is not feasible, then evaluating the Java8 pre-release may be worthwhile.

I will be posting some feature requests to the JavaFX project and will provide links to the JIRA tickets.

Upvotes: 1

Related Questions