我目前停留在这一点上,我正在使用 engine.io java 客户端,我必须从服务器获取二进制数据,实际上每 16 毫秒超过 40000 个字节作为字节数组。
效果很好,我可以毫无问题地获取数据,但是,当通过这些方法解析数据时,每次我收到数据时都会创建一个新的字节数组,每 16 毫秒一次。
观察监视器,我可以看到每次调用 new byte 来存储数据时,Dalvik 运行时都会分配相同数量的内存,因此垃圾收集器会被激活很多时间,并在某个时刻卡住申请。
16 毫秒是否对垃圾收集器清除所有未使用的字节数组来说太快了? 在 android 中使用字节数组时是否有推荐的大小?
编辑: 这是代码
在我的主要 Activity 中,当来自 websocket 的消息到达时,我有一个这样的处理程序:
@Override
public void onMessage(ByteBuffer buffer) {
System.out.println("received message: " + buffer);
if (buffer.hasArray()) {
byte[] array = buffer.array();
}
}
而之前,它是由这段代码解析的:
public static class InputStreamImpl extends DataInputStream {
public InputStreamImpl(InputStream in) {
super(in);
}
public byte[] readBytes(int length) throws IOException {
byte[] buffer = new byte[length];
readFully(buffer);
return buffer;
}
}
长度是来自服务器的当前字节数组的大小。 在 Monitor 中,我可以看到 new byte[length] 行增加了堆内存。
我应该放置一个非常大的固定数组缓冲区并重复使用同一个缓冲区吗?
谢谢!
最佳答案
一般来说,垃圾收集器会在收集到足够多的垃圾时运行。它消耗多少时间大致取决于堆上的对象总数。 byte[40000]
是一个中等大小的对象,但每秒 60 个加起来达到 2.4 MB/s,或接近 150 MB/min。对于您希望找到运行 Android 的小型设备来说,这是相当可观的(如果您实际上以该速率接收数据,那么对于您的数据计划来说也是相当可观的)。
作为一般原则,您应该根据每个 I/O 事务需要或实际期望接收的数据量来适当调整缓冲区大小。完成后,您希望重用该缓冲区并避免不必要地复制它。这些通常都是可能的。您没有提供任何代码,所以我无法开始猜测为什么要复制您的缓冲区。
关于java - Android 4.4.4,创建大量字节数组时,垃圾收集器如何处理?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27111126/