隐藏阶段时的 JavaFX 8 内存泄漏

我有一个JavaFX应用程序,当按下X按钮时,它会最小化到托盘。我一直在通过VisualVM监视应用程序以了解内存趋势。

奇怪的是,当应用程序打开或最小化到任务栏时,内存总是被GCed回使用的初始内存。但是,当它最小化到托盘(,)时,内存会GCed,但呈上升趋势(泄漏)。stage.hide()systemTray.show()

在 VisualVM 中,旧一代空间不断上升,一旦它在一段时间后达到最大值,应用程序将无响应,CPU 峰值达到 80%。

我注意到,如果我通过双击托盘图标等在应用程序上stage.show(),GC会将所有内容清除恢复正常。但是,如果长时间放置,它根本无法GC旧一代。

堆转储显示 并具有最多保留的空间。如果未隐藏舞台,则两者都不会出现。在“引用”下,它显示 。javafx.scene.Scene#7javafx.scene.Node[]#2this[] -> 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

这是什么原因造成的,我该如何解决这个问题?


答案 1

我从来没有找到并回答过这个问题。相反,我会在 hide 上使节点清空,并将其恢复到视图中。对于密集型动态节点/多个节点,我创建了一个哈希映射以将它们存储在内存中。

这已经成为我在javafx8中的习惯,即处理所有图形并从哈希映射中重新分配隐藏和视图。在现代台式机上,额外的内存和 CPU 使用率可以忽略不计。使用这种方法,当隐藏在win8 / 10上时,我有0个CPU使用率应用程序和低内存应用程序(〜100m)运行。


答案 2

Java具有诸如弱参考:https://docs.oracle.com/javase/7/docs/api/java/lang/ref/WeakReference.html

软参考:https://docs.oracle.com/javase/7/docs/api/java/lang/ref/SoftReference.html

这些允许您专门针对 VM ->>垃圾回收的内容。

此外,还有并发API http://winterbe.com/posts/2015/04/07/java8-concurrency-tutorial-thread-executor-examples/

使用执行程序服务和线程池。

对于java中的内存限制性应用程序,软件应调用

System.gc() // garbage collector

在间隔处,无论其自动调用如何

可以使用 Runtime 类为项目计划负载均衡器 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). 

线程一直是内存密集型应用程序的问题,在JavaFX中,场景的每个组件都是紧密绑定到场景的线程,但从实现开始,它似乎是松散绑定的。

如果需要长时间运行,最好在本机端(JNI)中处理一些处理器密集型任务。此外,CLEAN架构将受益匪浅

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


推荐