简体   繁体   中英

JavaFX 8 Memory leak when Hiding Stage

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?

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.

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& *

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM