Java 尝试写入大缓冲区时,SocketChannel.write()抛出OfMemoryError
我的代码在运行以下行时抛出OutOfMemoryError:Java 尝试写入大缓冲区时,SocketChannel.write()抛出OfMemoryError,java,android,nio,android-memory,socketchannel,Java,Android,Nio,Android Memory,Socketchannel,我的代码在运行以下行时抛出OutOfMemoryError: int numBytes=socketChannel.write(\u send\u buffer); 其中,socketChannel是 而\u send\u buffer是 代码通过非阻塞选择器写入操作到达该点,并在\u send\u buffer的容量较大时,在第一次尝试写入时抛出该操作。当\u send\u buffer小于20Mb时,我对代码没有任何问题,但当尝试使用更大的缓冲区(例如>100Mb)进行测试时,它失败了 根
int numBytes=socketChannel.write(\u send\u buffer);
其中,socketChannel
是
而\u send\u buffer
是
代码通过非阻塞选择器写入操作到达该点,并在\u send\u buffer
的容量较大时,在第一次尝试写入时抛出该操作。当\u send\u buffer
小于20Mb时,我对代码没有任何问题,但当尝试使用更大的缓冲区(例如>100Mb)进行测试时,它失败了
根据以下文件:
尝试将最多r个字节写入通道,其中r是调用此方法时缓冲区中剩余的字节数,即src.remaining()。
假设写入了长度为n的字节序列,其中0 0 | | | recv_buffer.position()>0){
如果(比特读取>0){
//Log.v(标记,从“+socketChannel.getRemoteAddress()”读取“+bitsRead+”字节);
}
//如果尚未通过2字节短的原始头确定头的长度,
//尝试确定它,尽管没有gaurantee,但它将有足够的字节。因此它可能
//多次传递此if语句。只有在读取该语句后,才会
//_jsonheader_len具有非零长度;
if(this.\u jsonheader\u len==0){
socketReadTimeStart=System.nanoTime();
进程_protoheader();
}
//_jsonheader_len只有在设置正确(设置完成)的情况下才会大于0。
//jsonHeaderRead将为null,直到它填充并转换为缓冲区集合
//JSONobject。
else if(this.jsonHeaderRead==null){
process_jsonheader();
}
否则如果(!msgReadComplete){
过程内容(选择键);
}否则{
Log.e(标记为“比特读取但不知道如何处理它们”);
}
}
}
}
私有无效写入(SelectionKey SelectionKey)引发IOException、JSONException{
如果(!writeBufferVector.isEmpty()){
SocketChannel SocketChannel=(SocketChannel)selectionKey.channel();
Log.v(标记“writeBufferVector包含数据”);
if(jsonHeaderWrite==null){
int numBytesToWrite=writeBufferVector.get(0.limit();
//创建包含事件长度(字节)的JSONHeader
Log.v(标记,“生成jsonheader”);
jsonHeaderWrite=生成jsonheader(numBytesToWrite);
byte[]jsonBytes=jsonHeaderWrite.toString().getBytes(StandardCharsets.UTF_8);
//将JSONHeader的长度编码为前两个字节,并写入socketChannel
int jsonLength=jsonBytes.length;
//将protoHeader、JSONheader和插曲字节的长度相加
int totalNumBytesToWrite=Integer.BYTES+jsonLength+numBytesToWrite;
//创建编译protoHeader、JsonHeader和Incide的新缓冲区
_发送缓冲区=ByteBuffer.allocate(totalNumBytesToWrite);
Log.v(标记“组装发送缓冲区”);
//组装所有字节并翻转以准备读取
_send_buffer.putInt(jsonLength);
_send_buffer.put(jsonBytes);
_send_buffer.put(writeBufferVector.get(0));
_send_buffer.flip();
Log.d(标记“写入服务器…”);
//将字节写入socketChannel//todo不应为空,而as应为非阻塞
if(_send_buffer.remaining()>0){
int numBytes=socketChannel.write(_send_buffer);//此处todo内存转储错误!
int percentDone=(int)Math.ceil(((双精度)\u send\u buffer.limit()-(双精度)\u send\u buffer.remaining())
/(双精度)_send_buffer.limit())*100);
int total=\u send\u buffer.limit()/1000000;
//Log.d(标记“Sent”+percentDone+“%of”+total+“Mb到”+socketChannel.getRemoteAddress());
}
}否则{
//将字节写入socketChannel
if(_send_buffer.remaining()>0){
socketChannel.write(发送缓冲区);
}
}
if(_send_buffer.remaining()==0){
int total=\u send\u buffer.limit()/1000000;
双时间=(System.nanoTime()-socketWriteTimeStart)*10e-10;
DecimalFormat df=新的DecimalFormat();
df.setMaximumFractionDigits(2);
Log.i(标记为“+df.format(timetake)+”s“,“Sent”+“total+”Mb);
//从缓冲区中删除插曲,以免再次写入。
writeBufferVector.remove(0);
//清除发送缓冲区
_发送缓冲区。清除();
//设为null,以便捕获初始if语句以编写新的if语句。
jsonHeaderWrite=null;
//将套接字设置为在写入完成后读取。
Log.d(标记“从服务器读取…”);
int ops=SelectionKey.OP_READ;
sc.register(selectionKey.selector(),ops,selectionKey.attachment());
}
}
}
私有JSONObject generate_jsonheader(int numBytesToWrite)抛出JSONException{
JSONObject jsonHeader=新的JSONObject();
jsonHeader.put(“byteorder”,byteorder.nativeOrder().toString());
jsonHeader.put(“内容长度”,numBytesToWrite);
put(“内容类型”、“flatbuffer”)//
2021-04-22 11:52:44.260 11591-11733/jp.oist.abcvlib.serverLearning I/.serverLearnin: Clamp target GC heap from 195MB to 192MB
2021-04-22 11:52:44.260 11591-11733/jp.oist.abcvlib.serverLearning I/.serverLearnin: Alloc concurrent copying GC freed 2508(64KB) AllocSpace objects, 0(0B) LOS objects, 10% free, 171MB/192MB, paused 27us total 12.714ms
2021-04-22 11:52:44.261 11591-11733/jp.oist.abcvlib.serverLearning W/.serverLearnin: Throwing OutOfMemoryError "Failed to allocate a 49915610 byte allocation with 21279560 free bytes and 20MB until OOM, target footprint 201326592, growth limit 201326592" (VmSize 5585608 kB)
2021-04-22 11:52:44.261 11591-11733/jp.oist.abcvlib.serverLearning I/.serverLearnin: Starting a blocking GC Alloc
2021-04-22 11:52:44.261 11591-11733/jp.oist.abcvlib.serverLearning I/.serverLearnin: Starting a blocking GC Alloc