36

I have a JavaFX application that minimizes to tray when the X button is pressed. I have been monitoring the application via VisualVM for memory trends.

The weird part is, when the application is open, or minimized to taskbar, the memory is always GCed back to initial memory used. However, when it is minimized to tray (stage.hide(), systemTray.show()), the memory gets GCed, but in an upward trend (leak).

In VisualVM, the Old Gen space keeps going up, and once it hits the max after some time, the application will be unresponsive, and CPU spikes to 80%.

I notice that if I stage.show() on the app by double clicking the tray icon etc, GC will clear everything back to normal. However, if left for prolonged periods, it will simply fail to GC the old gen.

A heap dump shows javafx.scene.Scene#7 and javafx.scene.Node[]#2 as having the most retained space. Both will not appear if the stage is not hidden. Under references, it shows this[] -> dirtyNodes().

this     - value: javafx.scene.Node[] #2
<- dirtyNodes     - class: javafx.scene.Scene, value: javafx.scene.Node[] #2
 <- value     - class: javafx.scene.Node$ReadOnlyObjectWrapperManualFire, value:  
 javafx.scene.Scene #7

What is causing this and how can I solve this?

Lii
  • 11,553
  • 8
  • 64
  • 88
staticvoid
  • 261
  • 3
  • 9
  • I have drastically reduced the amount of memory leaked when the stage is hidden by removing the one and only GIF image on the stage. However, the issue is still occuring. I suspect that the background thread updating the UI when it is hidden is causing the scene/node to hold references to the old value. What is the best practice for updating such applications? My application is somewhat like a chat application with ~50 users online at any time. – staticvoid Jun 24 '14 at 16:06
  • 10
    could be a fx bug - you might consider reporting it in the fx issue tracker, best with a short runnable example that demonstrates the behaviour – kleopatra Jun 24 '14 at 16:34
  • 1
    I agree with @kleopatra, it looks like a product bug and only developers can help you there. JavaFX bug tracking is here: https://javafx-jira.kenai.com/ – Sergey Grinev Jun 25 '14 at 10:26
  • 3
    Could you provide a [MCVE](http://stackoverflow.com/help/mcve) for this? – javajon Aug 02 '14 at 17:06
  • It is a long shot, but in the past I have experienced leaks when using VisualVM. Have you observed the same trend without using VisualVM? – Ioannis Deligiannis Oct 06 '14 at 06:59
  • 1
    Hey, @staticvoid did you ever find an answer to this? I may be experiencing something similar in a JavaFX app that I'm working on. – Dawood ibn Kareem Mar 22 '17 at 01:38
  • @DavidWallace Could you provide heap dump file? It hardly to analyze without any code or dump file. – Tony Mar 25 '17 at 01:55
  • Yeah, good point. I ought to put in the hard yards and make an MCVE. I was just kind of hoping that the OP had somehow progressed with this; and it was somewhat easier to part with some of my hard-earned unicorn points. – Dawood ibn Kareem Mar 25 '17 at 02:04

2 Answers2

2

I never did find and answer to this. Instead, I would null the node on hide and restore it back on view. For intensive dynamic nodes/multiple nodes I created a hash map to store them in memory.

This has sort of become a habit for me in javafx8 to dispose all graphics and reassign on hide & view from hash map. The extra memory and cpu usage is negligible on modern desktops. Using this method, I have had 0 cpu usage apps and low memory apps (~100m) running when hidden on win8/10.

staticvoid
  • 261
  • 3
  • 9
  • Thanks for getting back. One of my colleagues found out what was causing the memory leak in the case that I had, and I don't think it would have been happening in your case too. It shouldn't be necessary to do what you've been doing, of course. But if it works for you, that's great. – Dawood ibn Kareem Apr 08 '17 at 06:15
-2

Java has features Like Weak Reference: https://docs.oracle.com/javase/7/docs/api/java/lang/ref/WeakReference.html

Soft reference: https://docs.oracle.com/javase/7/docs/api/java/lang/ref/SoftReference.html

these allow you to specifically target the VM ->> what to garbage collect.

also, there is Concurrency API http://winterbe.com/posts/2015/04/07/java8-concurrency-tutorial-thread-executor-examples/

that that uses Executor Service and Thread Pooling.

and for memory restrictive Applications in java the Software should call

System.gc() // garbage collector

at Intervals irrespective to its automatic invocation

You can use the Runtime class to schedule the Load Balancers for the project https://docs.oracle.com/javase/7/docs/api/java/lang/Runtime.html

public Process exec(String command)


                throws IOException
//--------------------------------------------------------
    Executes the specified string command in a separate process.

public void gc()

//----------------------------------------------------------
Runs the garbage collector. Calling this method suggests that the Java virtual machine expends effort toward recycling unused objects in order to make the memory they currently occupy available for quick reuse. When control returns from the method call, the virtual machine has made its best effort to recycle all discarded objects
This is a convenience method. An invocation of the form exec(command) behaves in exactly the same way as the invocation exec(command, null, null). 

threading has always been a problem with memory intensive applications and within JavaFX every component of a scene are threads tightly bound to a Scene but as of the implementation, it seems to to be Loosely bound.

If there is a long running required its better to Handle some of the processor intensive tasks in the Native side(JNI). Moreover, a CLEAN architecture would Benefit

https://www.google.co.in/webhp?sourceid=chrome-instant&rlz=1C1CHBF_enIN736IN736&ion=1&espv=2&ie=UTF-8#q=clean+code&*

Aloy A Sen
  • 764
  • 5
  • 9
  • 2
    I don't like this answer much. It's a bit vague about what could be happening. The really interesting part is the paragraph below the big grey block, where you start talking about `Scene`, but nothing else is Java FX specific. However, in the absence of any other reasonable solution, you are the recipient of the bounty. Congratulations. – Dawood ibn Kareem Mar 28 '17 at 03:11