IM发送大JSON来设备直通请求响应和正常的尺寸大约是5MB,所以决定使用GZIP和从5MB此下降到小于1MB内存不足上Gzip已解压缩
的问题是,即时得到内存不足我不知道在哪里发生了它的发生(我知道它在连接/响应处理程序内,但它有点偶然,我知道内存不足时可以从内存中弹出,但我认为这是主要来源)
使用改造我收到:
{ 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);
为什么它不工作,因为我希望这不会一次加载所有对象到内存?
“使用改造我收到:'{data:gzipBase64String}'” - 在那里,你浪费了大量的内存。您的Web服务应直接返回GZip数据,而不是base64编码的,不包含在某些JSON中。现在你必须解码设备上的base64。所以你已经通过1MB的byte []'和1.3MB的base64编码数据创建了'byte []'形式的堆空间。正如Mike指出的那样,'getGzipInputStreamFromByteArray()'将返回一个5MB'byte []'。这三个巨大分配中的任何一个都可能触发'OutOfMemoryError'。 – CommonsWare
@CommonsWare我知道了,但即使直接发送GZIP(不是base64),它在解码时会消耗更少的内存,或者问题依然存在?!在这一刻,即时搜索通过改造这样的事情(考虑不跨越多个GET分割数据) – user2582318
“或问题仍然存在?” - 问题仍然存在,虽然它会少一些(而且你的代码运行得更快)。 “考虑不跨越多个GET分割数据” - 恕我直言,这没有任何意义。这就好像说我们不应该在Web上使用PNG和JPEG图像,并且每个网页的''标签中都应该有base64编码的图像。如果您想要执行一个GET请求,请删除JSON中的嵌入式GZip,返回完整的JSON数据集,并让您的Web服务器GZip整个响应。 – CommonsWare