我在一个相当大的项目中使用mt4j库,其中场景被定期推送和poped; mt4j使用Processing库来处理图像。
我们使用loadImage()
方法加载图像,但我不知道如何在场景加载时从内存中删除这些图像;我们实际上有内存问题,因为在应用程序运行时使用的内存会增加..
你有什么想法吗?
由于 的Jérémy
编辑:
我刚写了一个ImageManager类:
package managers;
import java.util.HashMap;
import java.util.Map;
import org.mt4j.MTApplication;
import processing.core.PImage;
public class ImageManager {
private static ImageManager mImageManager = null;
protected MTApplication mApp;
protected Map< String, PImage > mImages;
protected PImage mTempImg;
private ImageManager( MTApplication app ) {
mApp = app;
mImages = new HashMap< String, PImage >();
}
public static synchronized ImageManager getInstance( MTApplication app ) {
if( mImageManager == null ) {
mImageManager = new ImageManager( app );
}
return mImageManager;
}
/**
* Load or retrieve img in memory
*
* @param path Path to the image
* @return <PImage> the image
*/
public PImage getImage( String path ) {
// Search for image
if( mImages.containsKey( path ) ) {
System.out.println( "ImageManager::getImage : image found !" );
mTempImg = mImages.get( path );
}
else {
System.out.println( "ImageManager::getImage : image not found, loading" );
mTempImg = mApp.loadImage( path );
mImages.put( path, mTempImg );
}
return mTempImg;
}
}
这是我的问题:我认为它会帮助我解决内存问题,但每次加载图像时我仍然会看到内存增加。一个例子:
ImageManager imgManager = ImageManager.getInstance( (MTApplication) app );
PImage image = imgManager.getImage( getPathToIcons() + imagesNames[i] );
//PImage image = app.loadImage(getPathToIcons() + imagesNames[i]);
mSceneImages.add( image );
有什么想法吗?感谢
编辑2:事实上,这种方法很有效:)问题解决了!
答案 0 :(得分:2)
或者只是重复使用它们?首先,image1 = loadImage(oneImage),后来image1 = loadImage(anotherImage)?
答案 1 :(得分:2)
对于java中的内存泄漏,您可能会考虑打包。除了运行
之外,我还没有找到一个很好的处理解决方案top -s 5
(在unix系统上)并观察内存使用情况,直到它挂起。我最近在一个datavis项目上工作,我在ArrayList中创建了可能数千个blitts(在我的例子中是在opengl中使用的文本图像)。最初我每次加载数据时都会动态地重新创建这些数组,这会导致内存泄漏[&p>;
在我的情况下,我尝试将对象引用归零并专门调用垃圾收集器。我认为它可能与处理调用你的void draw()方法每秒可能超过60次的事实有关,但它似乎似乎永远不会放弃引用。
我所做的纠正问题的方法是在setup方法()中加载所有图像/仅创建一次blits,并且只有在有新数据时才将新项目附加到ArrayList。
在此之前,我只是动态地重新创建整个ArrayList,因为它看起来足够快,但是当运行很长时间时,这个可怕的内存泄漏问题。
现在我只是为这个引用分配了blit,而不是每次都创建一个新对象和ArrayList。它效率更高,并且没有遭受同样的内存问题。
例如类似的东西(在循环中运行数千次):
tempImage = imageArrayList.get(i); // just assigns a reference, does not create a new object
而不是像这样:
tempImage = loadImage("image.jpg"); // this creates a new object every time it is called
答案 2 :(得分:1)
LoadImage返回一个PImage对象。如果丢弃这些PImage引用,那么垃圾收集器System.gc()应该删除它们。你试过了吗?
答案 3 :(得分:1)
您使用的是Processing 2.x吗?如果是这样,处理论坛中的this线程可能就是答案。显然,使用2.x中的图像存在内存泄漏。而且他们指出了一个你可能想要尝试的工作,这里是我指出的线程中来自PhiLho的黑客的例子。 HTH。
void draw()
{
PImage img = createImage(width, height, RGB);
image(img, 0, 0);
g.removeCache(img);// this is avoiding the leak
println(frameCount + " " + g.getCache(img));
}
答案 4 :(得分:0)
我对问题的解决方案:ImageManager类
package managers;
import java.util.HashMap;
import java.util.Map;
import org.mt4j.MTApplication;
import processing.core.PImage;
public class ImageManager {
private static ImageManager mImageManager = null;
protected MTApplication mApp;
protected Map< String, PImage > mImages;
protected PImage mTempImg;
private ImageManager( MTApplication app ) {
mApp = app;
mImages = new HashMap< String, PImage >();
}
public static synchronized ImageManager getInstance( MTApplication app ) {
if( mImageManager == null ) {
mImageManager = new ImageManager( app );
}
return mImageManager;
}
/**
* Load or retrieve img in memory
*
* @param path Path to the image
* @return <PImage> the image
*/
public PImage getImage( String path ) {
// Search for image
if( mImages.containsKey( path ) ) {
System.out.println( "ImageManager::getImage : image found !" );
mTempImg = mImages.get( path );
}
else {
System.out.println( "ImageManager::getImage : image not found, loading" );
mTempImg = mApp.loadImage( path );
mImages.put( path, mTempImg );
}
return mTempImg;
}
}