关于Gzip的OutOfMemory解压缩

时间:2017-08-01 17:08:31

标签: android crash compression retrofit

我通过请求响应将大型json发送到设备,通常大小约为5mb,所以我决定使用GZIP,这从5mb减少到不到1mb

问题是我得到OutOfMemory而且我不知道它在哪里发生了什么(我知道它在连接/响应处理程序中但它有点随意,我知道内存不足时可以从内存中弹出,但是我认为这是主要来源)

使用改装我收到:

{ data: gzipBase64String }

我使用一种方法解压缩base64字符串,另一种方法返回GZIPInputStream

  public static GZIPInputStream getByteArrayFromGzippedBase64(String base64) throws IOException {
        if(base64 != null) {
            try {
                byte[] data = Base64.decode(base64, Base64.DEFAULT);
                if (data != null) {
                    return getGzipInputStreamFromByteArray(data);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }

  public static GZIPInputStream getGzipInputStreamFromByteArray(byte[] compressed) throws IOException {
        final int BUFFER_SIZE = 32;
        ByteArrayInputStream is = new ByteArrayInputStream(compressed);
        GZIPInputStream gis = new GZIPInputStream(is, BUFFER_SIZE);
        return gis;
    }

我使用JsonReader处理这个GZIPInputStream:

reader = new JsonReader(new InputStreamReader(Utils.getByteArrayFromGzippedBase64(response.body().data)));

然后把它放在一个对象

body = gson.fromJson(reader, SyncDayjourneysResponse.class);

为什么它不工作,因为我希望这不会立即将所有对象加载到内存中?

1 个答案:

答案 0 :(得分:3)

#include <windows.h> #include <vector> #include <iostream> using namespace std; typedef BOOL (WINAPI *LPFN_GLPI)(LOGICAL_PROCESSOR_RELATIONSHIP, PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, PDWORD); int main() { LPFN_GLPI glpi = (LPFN_GLPI) GetProcAddress( GetModuleHandle(TEXT("kernel32")), "GetLogicalProcessorInformationEx"); if (!glpi) return 1; DWORD bytes = 0; glpi(RelationAll, 0, &bytes); vector<char> buffer(bytes); SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX* info; if (!glpi(RelationAll, (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*) &buffer[0], &bytes)) return 1; for (size_t i = 0; i < bytes; i += info->Size) { info = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*) &buffer[i]; if (info->Relationship == RelationCache && (info->Cache.Type == CacheData || info->Cache.Type == CacheUnified)) { cout << "info->Cache.Level: " << (int) info->Cache.Level << endl; cout << "info->Cache.CacheSize: " << (int) info->Cache.CacheSize << endl; cout << "info->Cache.GroupMask.Group: " << info->Cache.GroupMask.Group << endl; cout << "info->Cache.GroupMask.Mask: " << info->Cache.GroupMask.Mask << endl << endl; } } return 0; } 看起来肯定会在内存中构建整个5 MB数组,并且

Utils.getByteArrayFromGzippedBase64(response.body().data)也肯定会产生一个完整的bigbighuge JSON对象,它对应于内存中整整5兆字节的JSON文本。

我建议看看是否有任何方法可以在运行中进行放气,而不是创建一个包含整个放气内容的字节数组。

除此之外,您可能希望将单个bigbighuge JSON对象分解为更小的对象。