这是我第一次使用stackoverflow并希望获得一些帮助以了解我遇到的问题。在时间允许的范围内,我已经从事几个月的2D切片游戏的工作了几个月,但是我认为在绘制图形或至少在代码的那部分地方遇到了内存泄漏。一切正常,游戏运行,所有图像渲染,等等,但是昨晚我决定看看运行该程序时cpu和内存是如何保持的。我注意到随着时间的流逝,内存只会不断增长。从大约50mb开始,超过10-15分钟可以增长到150mb。我注释掉了一段代码,其中绘制了图形,并且执行了计时器的操作。我认为罪魁祸首在那附近,因为我认为注释时内存没有不必要的增长。
在绘制图形的类中,我创建并存储一个大约864x768的缓冲图像,并使用各种32x32的较小图像组成。
我使用一个经常触发的javax.swing.Timer,在执行动作的方法中,我只运行了update()方法,该方法检查玩家的输入,然后通过缓冲图像获取大缓冲图像的子图像。 subimage方法并将其显示在画布上。
我想这可能与计时器有关,但不确定。
下面是一些代码:
private BufferedImage map;
private Timer timer;
private BufferStrategy bs;
private Graphics g;
private boolean isInitialized;
public class World extends Canvas implements ActionListener {
public World() {
isInitialized = false;
timer = new Timer(25, this);
timer.setInitialDelay(100);
timer.start();
}
@Override
public void actionPerformed(ActionEvent e) {
if(!isInitialized) {
createBufferStrategy(3);
bs = getBufferStrategy();
isInitialied = true;
}
update();
}
public void update() {
player.input();
g = bs.getDrawGraphics();
BufferedImage temp = map.getSubimage(x,
y, viewWidth, viewHeight);
g.drawImage(temp, 0, 0, null);
g.drawImage(player, playerX, playerY,
null);
bs.show();
g.dispose();
}
}
提前谢谢!!
编辑:
好的,所以花了一些时间研究垃圾回收,JVM等之后,我发现我不了解这些东西在基本水平上是如何工作的。我对该项目进行了概要分析,发现GC可以按预期工作,依此类推。因此,总的来说,我认为是内存泄漏的情况不一定如此。我最初担心的是,从Windows任务管理器中我看到内存正在增长,并且从未稳定过该过程,而我只是知道该过程从代码,第二次检查,尝试不同的代码等是不正确的。我感到了解我现在所知道的要多得多!
我也采用了这种方法:
public abstract boolean drawImage(Image img, int dx1, int dy1, int dx2,
int dy2, int sx1, int sy1, int sx2, ImageObserver observer)
代替: BufferedImage temp = map.getSubimage(x,y,viewWidth,viewHeight); g.drawImage(temp,0,0,null);
现在我遇到了另一个问题。在我的台式机上,我用于编程和测试游戏,一切运行正常,并且可以在不使用任何应用程序的情况下测试游戏时正常运行。但是,当我启动浏览器并尝试在youtube或netflix上观看某些内容然后测试运行游戏时,会出现一毫秒的暂停(从25到50毫秒不等)。这种暂停每秒发生一次,这是明显的,绝对是不希望的!我进行了一些测试,它仅在以下draw方法期间发生:
公共抽象布尔drawImage(Image img,int dx1,int dy1,int dx2, dy2,int sx1,int sy1,int sx2,ImageObserver观察器)
但是同样,仅在特定情况下,即使在该情况下,每次也要在1-2毫秒内完成,除非经过一秒钟或接近它,否则会有延迟。
有什么想法吗?
答案 0 :(得分:1)
我看不到要刷新BufferedImage
的任何地方,因此它将保留先前分配的所有内存。
完成BufferedImage temp
值后,需要使用temp.flush()
刷新它
答案 1 :(得分:0)
无需获取子图像即可将其绘制到Graphics
中。
public abstract boolean drawImage(Image img,
int dx1,
int dy1,
int dx2,
int dy2,
int sx1,
int sy1,
int sx2,
int sy2,
ImageObserver observer)
This overload of drawImage
允许您指定要直接绘制的源图像部分:s
中的sx1
,sy1
等参数表示“源”。