Java应用程序消耗越来越多的内存,有时高达2GB,
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java应用程序消耗越来越多的内存,有时高达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();
}
问题是在我运行应用程序并单击“开始”按钮运行“runningThread()”函数后,内存和CPU的消耗越来越高,当它达到2GB以上的内存和90%的CPU时, “for(int m = 0; m <1000; m ++)”循环变得非常慢。我在每个循环开始之前清除所有对象。一旦任何对象丢失了对它的所有引用,JVM是否会自动回收内存以供重用?
您描述的症状强烈暗示内存泄漏:
- 不断增加内存利用率
- 应用程序变得越来越慢,因为GC需要更长时间并且运行得越来越频繁。
- 最终,你得到一个
OutOfMemoryError
和应用程序崩溃。
当应用程序创建越来越多的对象时,通常会发生内存泄漏,这些对象无法进行垃圾回收,因为它们仍然可以访问。
对此的一般解决方案是找到内存泄漏的原因(通常是一个错误)并修复它。在Java程序中有很多用于查找内存泄漏的工具,而StackOverflow则有很多用于查找内存泄漏的工具。如何做到这一点。
- 强制GC运行无济于事。 GC已经在运行......并且无法回收对象,因为它们仍然可以访问。
- 增加堆大小可能也无济于事。它只是推迟了应用程序运行后期的不可避免的减速。
一旦任何对象丢失了对它的所有引用,JVM是否会自动回收内存以供重用?
是。
而且您不需要强制GC运行。
对象未被回收的事实意味着它们仍然可以访问。换句话说,应该确保对象无法访问的代码不起作用。
memoryleak可以在代码中的任何位置。在IDE中使用VisualVM分析器或内置分析器来查找它。
关于JVM垃圾收集何时启动,它是“未定义的”。
我认为你的主要问题是你的内部while循环在不停顿的情况下不断进行测试 - 尝试在while循环中添加Thread.sleep(100)。
JVM将回收未使用对象的内存,但在GC进程运行之前不会执行此操作。我猜想runRound
在内部分配了很多对象。有可能GC不会在循环的下一次迭代中运行,因此会分配新的内存,然后再次分配,等等。
最终它会击中JVM的上限(-Xmx
参数),然后GC将开始更积极地释放未使用的对象,但你真的无法控制它何时发生。
使用VisualVM等工具可以帮助您确定问题所在。它将显示分配的字节与实际使用的字节之间的差异。您还可以查看GC过程何时发生。 VisualVM包含在JDK中。
另一种选择是runRound
正在分配对象,它正在保留某种全局引用。再次,仔细使用VisualVM应该让你识别这一点。
以上是关于Java应用程序消耗越来越多的内存,有时高达2GB,的主要内容,如果未能解决你的问题,请参考以下文章