4

我在一个相当大的项目中使用 mt4j 库,其中场景被定期推送和弹出;mt4j 使用处理库来处理图像。

我们使用loadImage()加载图像的方法,但是我不知道如何在弹出场景时从内存中删除这些图像;我们实际上有内存问题,因为在应用程序运行期间使用的内存会增加..

你有什么想法吗?

谢谢杰里米

编辑 :

我刚刚写了一个 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:事实上,这种方法效果很好 :) 问题解决了!

4

5 回答 5

2

或者也许只是重复使用它们?首先image1 = loadImage(oneImage),后来image1 = loadImage(anotherImage)?

于 2012-10-10T17:01:38.790 回答
2

对于 java 中的内存泄漏,您可能会考虑打包。除了运行之外,我还没有找到一个很好的处理解决方案

顶部-s 5

(在 unix 系统上)并观察内存使用情况,直到它挂起。我最近在一个 datavis 项目中工作,我在 ArrayList 中创建了潜在的数千个 blitts(在我的例子中是在 opengl 中使用的文本图像)。最初,我每次加载数据时都会即时重新创建这些数组,这会导致“内存泄漏”。

就我而言,我尝试清空对象引用并专门调用垃圾收集器。我认为这可能与处理调用您的 void draw() 方法每秒可能 60 次以上的事实有关,但似乎它似乎从未放弃引用。

我为纠正这个问题所做的就是在 setup method() 中加载所有图像/只创建一次 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
于 2012-10-10T21:52:39.990 回答
1

LoadImage 返回一个 PImage 对象。如果您丢弃这些 PImage 引用,那么垃圾收集器 System.gc() 应该删除它们。你试过吗?

于 2012-10-10T16:46:45.653 回答
1

您使用的是 Processing 2.x 吗?如果是这样,也许处理论坛中的这个帖子可以是答案。显然在 2.x 中使用图像存在内存泄漏。他们还指出了一个你可能想尝试的解决方法,这里是我指出的线程中来自 PhiLho 的 hack 的示例。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));
}
于 2012-11-29T20:14:00.927 回答
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;
}
}
于 2012-10-11T10:23:46.640 回答