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

问题描述 投票:-3回答:4

我有一个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();
}

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

java memory cpu
4个回答
1
投票

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

  • 不断增加内存利用率
  • 应用程序变得越来越慢,因为GC需要更长时间并且运行得越来越频繁。
  • 最终,你得到一个OutOfMemoryError和应用程序崩溃。

当应用程序创建越来越多的对象时,通常会发生内存泄漏,这些对象无法进行垃圾回收,因为它们仍然可以访问。

对此的一般解决方案是找到内存泄漏的原因(通常是一个错误)并修复它。在Java程序中有很多用于查找内存泄漏的工具,而StackOverflow则有很多用于查找内存泄漏的工具。如何做到这一点。

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

一旦任何对象丢失了对它的所有引用,JVM是否会自动回收内存以供重用?

是。

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

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


2
投票

memoryleak可以在代码中的任何位置。在IDE中使用VisualVM分析器或内置分析器来查找它。


1
投票

关于JVM垃圾收集何时启动,它是“未定义的”。

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


1
投票

JVM将回收未使用对象的内存,但在GC进程运行之前不会执行此操作。我猜想runRound在内部分配了很多对象。有可能GC不会在循环的下一次迭代中运行,因此会分配新的内存,然后再次分配,等等。

最终它会击中JVM的上限(-Xmx参数),然后GC将开始更积极地释放未使用的对象,但你真的无法控制它何时发生。

使用VisualVM等工具可以帮助您确定问题所在。它将显示分配的字节与实际使用的字节之间的差异。您还可以查看GC过程何时发生。 VisualVM包含在JDK中。

另一种选择是runRound正在分配对象,它正在保留某种全局引用。再次,仔细使用VisualVM应该让你识别这一点。

© www.soinside.com 2019 - 2024. All rights reserved.