我有一个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是否会自动回收内存以供重用?
答案 0 :(得分:2)
memoryleak可以在您的代码中的任何位置。在IDE中使用VisualVM分析器或内置分析器来查找它。
答案 1 :(得分:1)
未定义&#39;关于JVM垃圾收集何时启动。
我认为你的主要问题是你的内部while循环在不停顿的情况下不断进行测试 - 尝试在while循环中添加Thread.sleep(100)。
答案 2 :(得分:1)
JVM将回收未使用对象的内存,但在GC进程运行之前不会这样做。我猜想runRound
在内部分配了很多对象。 GC可能会在循环的下一次迭代中运行,因此会分配新内存,然后再分配,等等。
最终它会触及JVM的上限(-Xmx
参数),然后GC会开始更积极地释放未使用的物体,但你不会真的有很多控制它发生的时间。
使用VisualVM等工具可以帮助您确定问题所在。它将显示分配的字节与实际使用的字节之间的差异。您还可以查看GC过程何时发生。 VisualVM包含在JDK中。
另一种选择是runRound
正在分配它保留某种全局引用的对象。再次,仔细使用VisualVM应该让你识别这一点。
答案 3 :(得分:1)
您描述的症状强烈暗示内存泄漏:
OutOfMemoryError
,应用程序崩溃。当应用程序创建越来越多的对象时,通常会发生内存泄漏,这些对象无法进行垃圾回收,因为它们仍然可以访问。
对此的一般解决方案是找到内存泄漏的原因(通常是一个错误)并修复它。在Java程序中有很多用于查找内存泄漏的工具,而StackOverflow则有很多用于查找内存泄漏的工具。如何做到这一点。
一旦任何对象失去对它的所有引用,JVM是否会自动回收内存以供重用?
是
你不需要强制GC运行。
对象未被回收的事实意味着它们仍然可以访问。换句话说,应该确保对象无法访问的代码不起作用。