Java 应用程序正在消耗越来越多的内存,有时高达 2GB,

Java Application is consuming more and more Memory, which sometimes is up to 2GB,

我有一个 JavaFX 应用程序,它包含一个用于数据处理并在用户界面中显示结果的后台线程。 我创建了以下数据处理代码:

    public static void runningThread(){
    long startTime = java.lang.System.nanoTime();

    WSN wsn = new WSN(100, 100, 30, 60, 200);
    wsn.initializeNodePosition();
    wsn.alphaNodesDead = wsn.nodeNumber/2;


    BaseStation BS = new  BaseStation();                                            //the BS is created
    BS.x = 125;
    BS.y = 50;
    BS.maxRadius = 65;
    BS.energyModel = new NOEnergyModel();

    wsn.BS = BS;
    BS.wsn = wsn;



    Thread queryThread = new Thread() {
        public void run() {
            System.out.println("Start");

            for(int m=0; m<1000; m++){
                System.out.println(m);

                wsn.protocol    = new HEED(wsn);
                wsn.generateHomogeneousWSN(HEEDNODE.class, new MITModel(), new SimpleAggregation());
                wsn.protocol.setRadiusAndNeighbors();


                boolean running = true;
                while(running){
                    wsn.roundPerformed++;

                    wsn.protocol.election_cluster_formation();              //cluster formation
                    wsn.defineStandardCHRouting();                          //defines the routing at CH level
                    wsn.protocol.runRound();

                    System.out.println(wsn.roundPerformed);

                    if(wsn.deadNodeList.size() >= wsn.alphaNodesDead){
                        long stopTime = java.lang.System.nanoTime();

                        System.out.println("end: " + (stopTime-startTime) / 1000000000.0);

                        running = false;
                    }
                }
            }

        }
    };
    queryThread.start();
}

问题是在我 运行 应用程序并单击 "Start" 按钮以 运行 "runningThread()" 功能后,内存消耗和 CPU 是越来越高,当达到2GB以上内存和CPU的90%时,"for(int m=0; m<1000; m++)"循环变得很慢。我在每个循环开始之前清除所有对象。 一旦任何对象失去对它的所有引用,JVM 是否会自动回收内存以供重用?

JVM 垃圾收集何时开始'undefined'。

我认为你的主要问题是你的内部 while 循环不停地不断测试 - 尝试在 while 循环中添加 Thread.sleep(100)。

内存泄漏可能出现在您代码中的任何位置。使用 VisualVM 探查器或 IDE 中的内置探查器来找到它。

JVM 会为未使用的对象回收内存,但直到 GC 进程 运行s 才会这样做。我猜测 runRound 在内部分配了很多对象。 GC 很可能在循环的下一次迭代时没有 运行,因此分配新内存,然后一次又一次,等等

最终它会达到 JVM 的上限(-Xmx 参数),然后 GC 将开始更积极地释放未使用的对象,但你实际上没有很多控制它何时发生。

使用 VisualVM 等工具将帮助您确定问题所在。它会告诉你分配的字节数和实际使用的字节数之间的区别。您还可以查看 GC 进程何时发生。 JDK.

中包含 VisualVM

另一种选择是 runRound 正在分配它保持某种全局引用的对象。同样,仔细使用 VisualVM 应该可以让您识别这一点。

您描述的症状强烈暗示存在内存泄漏:

  • 内存利用率不断提高
  • 应用程序变得越来越慢,因为 GC 花费的时间越来越长,而且 运行s 越来越频繁。
  • 最终,您得到 OutOfMemoryError 并且应用程序崩溃。

内存泄漏通常发生在应用程序创建越来越多的对象时,这些对象由于仍然可访问而无法被垃圾回收。

一般的解决办法是找到内存泄漏的原因(通常是一个错误)并修复它。有很多工具可以在 Java 程序中查找内存泄漏,Whosebugs 上也有关于如何做到这一点的信息。关于如何做。

  • 强制 GC 运行 无济于事。 GC 已经 运行ning ...并且无法回收对象,因为它们仍然可以访问。
  • 增加堆大小可能也无济于事。它只是将不可避免的减速推迟到应用程序 运行.
  • 的后期

Does JVM will reclaims memory automatically for reuse once any of the object lose all the reference to it ?

是的。

而且您不需要强制 GC 运行。

对象未被回收这一事实意味着它们仍然可以访问。换句话说,您应该确保对象变得不可访问的代码不起作用。