【发布时间】:2017-06-30 23:36:40
【问题描述】:
我目前正在开发一款游戏,并选择 Java 作为我的主要开发平台。我现在有点后悔,因为我遇到了一个我不完全理解的重大内存泄漏。到目前为止,我对 Java 并不陌生,但由于某种原因,我无法解决这个错误。基本问题是我将我的游戏世界分段加载,以免使用太多内存。玩家离开一个区域后,保存在地图中的设置区域会从地图中移除。出于某种原因,此后垃圾收集器不会删除该区域,并且内存消耗量只会不断增加,直到我停止游戏。根据我对垃圾收集器的理解,当没有线程访问对象时,它应该删除堆变量,我的游戏就是这种情况。
因为我的游戏引擎已经相当大而且太复杂了,所以我做了一个小测试程序来检查我对垃圾收集器的理解是否是“垃圾;P”。 (我知道我很吝啬,对吧?... sry ^^)
这是程序:
public static void main(String... args) throws InterruptedException {
new Thread(() -> {
try {
Set<Long> set = new HashSet<>();
System.out.println("Saving stuff");
for (long i = 0; i < 19999999L; i++) {
set.add(i);
}
Thread.sleep(10000);
System.out.println("Clearing stuff");
set.clear();
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
Thread.sleep(40000);
System.out.println("Exiting program!");
}
如您所见,我基本上只是在 HashSet 中保存一堆 long 并在之后清除它。为了确保不再访问 longs,它们所属的线程甚至停止。但是由于某种奇怪的原因,没有释放内存。
在担任程序员期间,我从来没有像现在这样对一个问题如此困惑过。我希望我可以在不重写 C++ 的所有内容的情况下解决这个问题,这真的很糟糕,因为该程序在我迄今为止工作的几个月里变得非常大。
我很高兴你们能提供任何帮助,我真的希望我能解决这个问题, 提前谢谢你:)
【问题讨论】:
-
关于像这样的玩具程序的事情是 a) 它们不一定会执行您想要显示的内容(这里没有任何东西可以触发 GC,反正您也不能); b) 它们不一定与您的实际代码的行为有关系,因此它们实际上并不能说明实际问题。
-
根据我对垃圾收集器的理解应该删除堆变量-> 我认为这句话是错误的,特别是应该,没有什么GC应该做的,你只能假设GC可以做一些事情。 GC 行为,语义未定,无法控制。
标签: java memory-leaks garbage-collection set