【问题标题】:Codename One "out of memory" when using Object-C native interface (HEIC to JPEG conversion)使用 Object-C 本机接口(HEIC 到 JPEG 转换)时的代号一“内存不足”
【发布时间】:2020-10-03 00:01:26
【问题描述】:

由于我正在为 Android 和 iOS 实现自定义图库,因此我必须通过本机接口直接访问存储在 FileSystemStorage 中的图库文件。

基本思路是通过原生接口检索文件列表,然后在Codename One中制作一个跨平台的GUI。这适用于 Android,我必须尽可能快地生成拇指(在 Codename One 一侧,而不是在本机界面一侧),总体结果是可以接受的。

在 iOS 上,我还有一个问题,即 HEIC 图像文件格式,需要将其转换为 JPEG 才能在 Codename One 中使用。基本上,我通过the code in this question得到文件列表(我正在等待答案...),然后我必须将每个HEIC文件转换为临时JPEG文件,但我的HEICtoJPEG 原生界面使应用在几张图片后崩溃,并带有“内存不足”的 Xcode 消息...

我怀疑有问题的代码如下,可能UIImage* image 和/或NSData* mediaData 从未发布:

#import "myapp_utilities_HEICtoJPEGNativeImpl.h"

@implementation myapp_utilities_HEICtoJPEGNativeImpl

-(NSData*)heicToJpeg:(NSData*)param{
    UIImage* image = [UIImage imageWithData:param];
    NSData* mediaData = UIImageJPEGRepresentation(image, 0.9);
    return mediaData;
}

-(BOOL)isSupported{
    return YES;
}

@end

这是 Java 原生接口:

import com.codename1.system.NativeInterface;

/**
 * @deprecated
 */
public interface HEICtoJPEGNative extends NativeInterface {
        
    public byte[] heicToJpeg(byte[] heicInput);
}

这是 Java 公共 API:

import com.codename1.io.FileSystemStorage;
import com.codename1.io.Util;
import com.codename1.system.NativeLookup;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class HEICtoJPEG {
    private static HEICtoJPEGNative nativeInterface = NativeLookup.create(HEICtoJPEGNative.class);
    
    /**
     * Public API to convert an HEIC file to a new JPEG file (placed in /heic)
     * @param heicFile in the FileSystemStorage
     * @return a new file (with unique name)
     */
    public static String convertToJPEG(String heicFile) throws IOException {
        if (nativeInterface != null && nativeInterface.isSupported()) {
            
            // It ensures that the directory exists.
            FileSystemStorage fss = FileSystemStorage.getInstance();
            String heicDir = fss.getAppHomePath() + "/heic";
            if (!fss.isDirectory(heicDir)) {
                fss.mkdir(heicDir);
            }
            
            ByteArrayOutputStream outHeic = new ByteArrayOutputStream();
            InputStream inHeic = fss.openInputStream(heicFile);
            Util.copy(inHeic, outHeic);
            byte[] heicData = outHeic.toByteArray();
            
            byte[] jpegData = nativeInterface.heicToJpeg(heicData);
            
            String jpegFile = heicDir + "/" + DeviceUtilities.getUniqueId() + ".jpg";
            OutputStream outJpeg = fss.openOutputStream(jpegFile);
            ByteArrayInputStream inJpeg = new ByteArrayInputStream(jpegData);
            Util.copy(inJpeg, outJpeg);
            
            return jpegFile;
            
        } else {
            return null;
        }
    }
}

由于 Android 对应的工作正常,我希望我的自定义库代码的其余部分没有问题,并且这个内存不足问题是我在此处发布的代码中的问题。

我希望你能给我一个可行的解决方案。谢谢

【问题讨论】:

  • 我觉得你需要在return前加上[image release]来释放你分配的图片。
  • 我已经试过了,现在又试了一次,还是不行。它也不起作用return [mediaData autorelease]。还有其他建议吗?也许我需要一种完全不同的方法?
  • 我们需要调查一下。这里可能存在固有的内存泄漏,如果体积相对较小,我们没有注意到,但对于较大的数据量却很明显
  • 我刚刚开始研究它,我认为我们在 iOS 上的本机接口调用中确实存在内存泄漏问题。我很快就会解决这个问题 - 今天不会发布,但会在下周五发布。

标签: codenameone


【解决方案1】:

iOS 端口调用接收或返回原始数组(byte[]int[] 等)的本机接口方法的方式存在内存泄漏。

我刚刚对此进行了修复(本机接口调用现在包装在自动释放池中),该修复将于下周五(2020 年 10 月 9 日)在构建服务器上可用。

编辑:(2020 年 10 月 2 日,星期五)

此修复已部署到构建服务器,因此您应该能够立即再次构建它并查看它是否解决了您的问题。

【讨论】:

    猜你喜欢
    • 2019-11-18
    • 2021-03-10
    • 2015-11-11
    • 2018-01-11
    • 2015-05-14
    • 1970-01-01
    • 1970-01-01
    • 2018-05-05
    相关资源
    最近更新 更多