Made sure all out-of-the-box encoders and decoders respect the ChannelBufferFactory configuration
This commit is contained in:
parent
22b3885fe5
commit
1fa791c4a4
|
@ -185,6 +185,14 @@ public class ChannelBuffers {
|
||||||
return dynamicBuffer(BIG_ENDIAN, 256);
|
return dynamicBuffer(BIG_ENDIAN, 256);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static ChannelBuffer dynamicBuffer(ChannelBufferFactory factory) {
|
||||||
|
if (factory == null) {
|
||||||
|
throw new NullPointerException("factory");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new DynamicChannelBuffer(factory.getDefaultOrder(), 256, factory);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new big-endian dynamic buffer with the specified estimated
|
* Creates a new big-endian dynamic buffer with the specified estimated
|
||||||
* data length. More accurate estimation yields less unexpected
|
* data length. More accurate estimation yields less unexpected
|
||||||
|
|
|
@ -109,6 +109,7 @@ public class DirectChannelBufferFactory extends AbstractChannelBufferFactory {
|
||||||
} else {
|
} else {
|
||||||
slice = allocateLittleEndianBuffer(capacity);
|
slice = allocateLittleEndianBuffer(capacity);
|
||||||
}
|
}
|
||||||
|
slice.clear();
|
||||||
return slice;
|
return slice;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,10 +25,12 @@ package org.jboss.netty.handler.codec.frame;
|
||||||
import static org.jboss.netty.channel.Channels.*;
|
import static org.jboss.netty.channel.Channels.*;
|
||||||
|
|
||||||
import java.net.SocketAddress;
|
import java.net.SocketAddress;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
import org.jboss.netty.buffer.ChannelBuffer;
|
import org.jboss.netty.buffer.ChannelBuffer;
|
||||||
import org.jboss.netty.buffer.ChannelBuffers;
|
import org.jboss.netty.buffer.ChannelBuffers;
|
||||||
import org.jboss.netty.channel.Channel;
|
import org.jboss.netty.channel.Channel;
|
||||||
|
import org.jboss.netty.channel.ChannelEvent;
|
||||||
import org.jboss.netty.channel.ChannelHandlerContext;
|
import org.jboss.netty.channel.ChannelHandlerContext;
|
||||||
import org.jboss.netty.channel.ChannelPipelineCoverage;
|
import org.jboss.netty.channel.ChannelPipelineCoverage;
|
||||||
import org.jboss.netty.channel.ChannelStateEvent;
|
import org.jboss.netty.channel.ChannelStateEvent;
|
||||||
|
@ -147,8 +149,8 @@ import org.jboss.netty.channel.SimpleChannelHandler;
|
||||||
@ChannelPipelineCoverage("one")
|
@ChannelPipelineCoverage("one")
|
||||||
public abstract class FrameDecoder extends SimpleChannelHandler {
|
public abstract class FrameDecoder extends SimpleChannelHandler {
|
||||||
|
|
||||||
// TODO Respect ChannelBufferFactory
|
private final AtomicReference<ChannelBuffer> cumulation =
|
||||||
private final ChannelBuffer cumulation = ChannelBuffers.dynamicBuffer();
|
new AtomicReference<ChannelBuffer>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void messageReceived(
|
public void messageReceived(
|
||||||
|
@ -165,6 +167,7 @@ public abstract class FrameDecoder extends SimpleChannelHandler {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ChannelBuffer cumulation = cumulation(e);
|
||||||
if (cumulation.readable()) {
|
if (cumulation.readable()) {
|
||||||
cumulation.discardReadBytes();
|
cumulation.discardReadBytes();
|
||||||
cumulation.writeBytes(input);
|
cumulation.writeBytes(input);
|
||||||
|
@ -253,6 +256,7 @@ public abstract class FrameDecoder extends SimpleChannelHandler {
|
||||||
|
|
||||||
private void cleanup(ChannelHandlerContext ctx, ChannelStateEvent e)
|
private void cleanup(ChannelHandlerContext ctx, ChannelStateEvent e)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
|
ChannelBuffer cumulation = cumulation(e);
|
||||||
try {
|
try {
|
||||||
if (cumulation.readable()) {
|
if (cumulation.readable()) {
|
||||||
// Make sure all frames are read before notifying a closed channel.
|
// Make sure all frames are read before notifying a closed channel.
|
||||||
|
@ -269,4 +273,16 @@ public abstract class FrameDecoder extends SimpleChannelHandler {
|
||||||
ctx.sendUpstream(e);
|
ctx.sendUpstream(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ChannelBuffer cumulation(ChannelEvent e) {
|
||||||
|
ChannelBuffer buf = cumulation.get();
|
||||||
|
if (buf == null) {
|
||||||
|
buf = ChannelBuffers.dynamicBuffer(
|
||||||
|
e.getChannel().getConfig().getBufferFactory());
|
||||||
|
if (!cumulation.compareAndSet(null, buf)) {
|
||||||
|
buf = cumulation.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,9 +89,8 @@ public abstract class HttpMessageDecoder extends ReplayingDecoder<HttpMessageDec
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
case READ_CONTENT: {
|
case READ_CONTENT: {
|
||||||
// TODO Respect ChannelBufferFactory
|
|
||||||
if (content == null) {
|
if (content == null) {
|
||||||
content = ChannelBuffers.dynamicBuffer();
|
content = ChannelBuffers.dynamicBuffer(channel.getConfig().getBufferFactory());
|
||||||
}
|
}
|
||||||
//this will cause a replay error until the channel is closed where this will read whats left in the buffer
|
//this will cause a replay error until the channel is closed where this will read whats left in the buffer
|
||||||
content.writeBytes(buffer.readBytes(buffer.readableBytes()));
|
content.writeBytes(buffer.readBytes(buffer.readableBytes()));
|
||||||
|
@ -122,7 +121,7 @@ public abstract class HttpMessageDecoder extends ReplayingDecoder<HttpMessageDec
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case READ_CHUNKED_CONTENT: {
|
case READ_CHUNKED_CONTENT: {
|
||||||
readChunkedContent(buffer);
|
readChunkedContent(channel, buffer);
|
||||||
}
|
}
|
||||||
case READ_CRLF: {
|
case READ_CRLF: {
|
||||||
byte next = buffer.readByte();
|
byte next = buffer.readByte();
|
||||||
|
@ -147,10 +146,10 @@ public abstract class HttpMessageDecoder extends ReplayingDecoder<HttpMessageDec
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void readChunkedContent(ChannelBuffer buffer) {
|
private void readChunkedContent(Channel channel, ChannelBuffer buffer) {
|
||||||
if (content == null) {
|
if (content == null) {
|
||||||
// TODO Respect ChannelBufferFactory
|
content = ChannelBuffers.dynamicBuffer(
|
||||||
content = ChannelBuffers.dynamicBuffer(chunkSize);
|
chunkSize, channel.getConfig().getBufferFactory());
|
||||||
}
|
}
|
||||||
content.writeBytes(buffer, chunkSize);
|
content.writeBytes(buffer, chunkSize);
|
||||||
nextState = State.READ_CHUNK_SIZE;
|
nextState = State.READ_CHUNK_SIZE;
|
||||||
|
|
|
@ -51,8 +51,8 @@ public abstract class HttpMessageEncoder extends SimpleChannelHandler {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
HttpMessage request = (HttpMessage) e.getMessage();
|
HttpMessage request = (HttpMessage) e.getMessage();
|
||||||
// TODO Respect ChannelBufferFactory
|
ChannelBuffer buf = ChannelBuffers.dynamicBuffer(
|
||||||
ChannelBuffer buf = ChannelBuffers.dynamicBuffer();
|
e.getChannel().getConfig().getBufferFactory());
|
||||||
encodeInitialLine(buf, request);
|
encodeInitialLine(buf, request);
|
||||||
encodeHeaders(buf, request);
|
encodeHeaders(buf, request);
|
||||||
buf.writeBytes(CRLF);
|
buf.writeBytes(CRLF);
|
||||||
|
|
|
@ -25,8 +25,10 @@ package org.jboss.netty.handler.codec.replay;
|
||||||
import static org.jboss.netty.channel.Channels.*;
|
import static org.jboss.netty.channel.Channels.*;
|
||||||
|
|
||||||
import java.net.SocketAddress;
|
import java.net.SocketAddress;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
import org.jboss.netty.buffer.ChannelBuffer;
|
import org.jboss.netty.buffer.ChannelBuffer;
|
||||||
|
import org.jboss.netty.buffer.ChannelBufferFactory;
|
||||||
import org.jboss.netty.channel.Channel;
|
import org.jboss.netty.channel.Channel;
|
||||||
import org.jboss.netty.channel.ChannelHandlerContext;
|
import org.jboss.netty.channel.ChannelHandlerContext;
|
||||||
import org.jboss.netty.channel.ChannelPipelineCoverage;
|
import org.jboss.netty.channel.ChannelPipelineCoverage;
|
||||||
|
@ -212,8 +214,9 @@ import org.jboss.netty.handler.codec.frame.FrameDecoder;
|
||||||
@ChannelPipelineCoverage("one")
|
@ChannelPipelineCoverage("one")
|
||||||
public abstract class ReplayingDecoder<T extends Enum<T>> extends SimpleChannelHandler {
|
public abstract class ReplayingDecoder<T extends Enum<T>> extends SimpleChannelHandler {
|
||||||
|
|
||||||
private final ChannelBuffer cumulation = new UnsafeDynamicChannelBuffer(256);
|
private final AtomicReference<ChannelBuffer> cumulation =
|
||||||
private final ReplayingDecoderBuffer replayable = new ReplayingDecoderBuffer(cumulation);
|
new AtomicReference<ChannelBuffer>();
|
||||||
|
private volatile ReplayingDecoderBuffer replayable;
|
||||||
private volatile T state;
|
private volatile T state;
|
||||||
private volatile int checkpoint;
|
private volatile int checkpoint;
|
||||||
|
|
||||||
|
@ -235,7 +238,7 @@ public abstract class ReplayingDecoder<T extends Enum<T>> extends SimpleChannelH
|
||||||
* Stores the internal cumulative buffer's reader position.
|
* Stores the internal cumulative buffer's reader position.
|
||||||
*/
|
*/
|
||||||
protected void checkpoint() {
|
protected void checkpoint() {
|
||||||
checkpoint = cumulation.readerIndex();
|
checkpoint = cumulation().readerIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -243,8 +246,8 @@ public abstract class ReplayingDecoder<T extends Enum<T>> extends SimpleChannelH
|
||||||
* the current decoder state.
|
* the current decoder state.
|
||||||
*/
|
*/
|
||||||
protected void checkpoint(T state) {
|
protected void checkpoint(T state) {
|
||||||
|
checkpoint = cumulation().readerIndex();
|
||||||
this.state = state;
|
this.state = state;
|
||||||
checkpoint = cumulation.readerIndex();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -309,9 +312,10 @@ public abstract class ReplayingDecoder<T extends Enum<T>> extends SimpleChannelH
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ChannelBuffer cumulation = cumulation(ctx);
|
||||||
cumulation.discardReadBytes();
|
cumulation.discardReadBytes();
|
||||||
cumulation.writeBytes(input);
|
cumulation.writeBytes(input);
|
||||||
callDecode(ctx, e.getChannel(), e.getRemoteAddress());
|
callDecode(ctx, e.getChannel(), cumulation, e.getRemoteAddress());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -332,7 +336,7 @@ public abstract class ReplayingDecoder<T extends Enum<T>> extends SimpleChannelH
|
||||||
ctx.sendUpstream(e);
|
ctx.sendUpstream(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void callDecode(ChannelHandlerContext context, Channel channel, SocketAddress remoteAddress) throws Exception {
|
private void callDecode(ChannelHandlerContext context, Channel channel, ChannelBuffer cumulation, SocketAddress remoteAddress) throws Exception {
|
||||||
while (cumulation.readable()) {
|
while (cumulation.readable()) {
|
||||||
int oldReaderIndex = checkpoint = cumulation.readerIndex();
|
int oldReaderIndex = checkpoint = cumulation.readerIndex();
|
||||||
Object result = null;
|
Object result = null;
|
||||||
|
@ -373,10 +377,11 @@ public abstract class ReplayingDecoder<T extends Enum<T>> extends SimpleChannelH
|
||||||
|
|
||||||
private void cleanup(ChannelHandlerContext ctx, ChannelStateEvent e)
|
private void cleanup(ChannelHandlerContext ctx, ChannelStateEvent e)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
|
ChannelBuffer cumulation = cumulation(ctx);
|
||||||
try {
|
try {
|
||||||
if (cumulation.readable()) {
|
if (cumulation.readable()) {
|
||||||
// Make sure all data was read before notifying a closed channel.
|
// Make sure all data was read before notifying a closed channel.
|
||||||
callDecode(ctx, e.getChannel(), null);
|
callDecode(ctx, e.getChannel(), cumulation, null);
|
||||||
if (cumulation.readable()) {
|
if (cumulation.readable()) {
|
||||||
// and send the remainders too if necessary.
|
// and send the remainders too if necessary.
|
||||||
Object partiallyDecoded = decodeLast(ctx, e.getChannel(), cumulation, state);
|
Object partiallyDecoded = decodeLast(ctx, e.getChannel(), cumulation, state);
|
||||||
|
@ -391,4 +396,27 @@ public abstract class ReplayingDecoder<T extends Enum<T>> extends SimpleChannelH
|
||||||
ctx.sendUpstream(e);
|
ctx.sendUpstream(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private ChannelBuffer cumulation(ChannelHandlerContext ctx) {
|
||||||
|
ChannelBuffer buf = cumulation.get();
|
||||||
|
if (buf == null) {
|
||||||
|
ChannelBufferFactory factory = ctx.getChannel().getConfig().getBufferFactory();
|
||||||
|
buf = new UnsafeDynamicChannelBuffer(factory);
|
||||||
|
if (cumulation.compareAndSet(null, buf)) {
|
||||||
|
replayable = new ReplayingDecoderBuffer(buf);
|
||||||
|
} else {
|
||||||
|
buf = cumulation.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ChannelBuffer cumulation() {
|
||||||
|
ChannelBuffer cumulation = this.cumulation.get();
|
||||||
|
if (cumulation == null) {
|
||||||
|
throw new IllegalStateException("Should be called in decode() only");
|
||||||
|
}
|
||||||
|
return cumulation;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,8 +22,7 @@
|
||||||
*/
|
*/
|
||||||
package org.jboss.netty.handler.codec.replay;
|
package org.jboss.netty.handler.codec.replay;
|
||||||
|
|
||||||
import java.nio.ByteOrder;
|
import org.jboss.netty.buffer.ChannelBufferFactory;
|
||||||
|
|
||||||
import org.jboss.netty.buffer.DynamicChannelBuffer;
|
import org.jboss.netty.buffer.DynamicChannelBuffer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -35,12 +34,8 @@ import org.jboss.netty.buffer.DynamicChannelBuffer;
|
||||||
*/
|
*/
|
||||||
class UnsafeDynamicChannelBuffer extends DynamicChannelBuffer {
|
class UnsafeDynamicChannelBuffer extends DynamicChannelBuffer {
|
||||||
|
|
||||||
UnsafeDynamicChannelBuffer(int estimatedLength) {
|
UnsafeDynamicChannelBuffer(ChannelBufferFactory factory) {
|
||||||
super(estimatedLength);
|
super(factory.getDefaultOrder(), 256, factory);
|
||||||
}
|
|
||||||
|
|
||||||
UnsafeDynamicChannelBuffer(ByteOrder endianness, int estimatedLength) {
|
|
||||||
super(endianness, estimatedLength);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -22,15 +22,17 @@
|
||||||
*/
|
*/
|
||||||
package org.jboss.netty.handler.codec.serialization;
|
package org.jboss.netty.handler.codec.serialization;
|
||||||
|
|
||||||
import static org.jboss.netty.buffer.ChannelBuffers.*;
|
|
||||||
import static org.jboss.netty.channel.Channels.*;
|
import static org.jboss.netty.channel.Channels.*;
|
||||||
|
|
||||||
import java.io.ObjectInputStream;
|
import java.io.ObjectInputStream;
|
||||||
import java.io.ObjectOutputStream;
|
import java.io.ObjectOutputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
import org.jboss.netty.buffer.ChannelBuffer;
|
import org.jboss.netty.buffer.ChannelBuffer;
|
||||||
|
import org.jboss.netty.buffer.ChannelBufferFactory;
|
||||||
import org.jboss.netty.buffer.ChannelBufferOutputStream;
|
import org.jboss.netty.buffer.ChannelBufferOutputStream;
|
||||||
|
import org.jboss.netty.buffer.ChannelBuffers;
|
||||||
import org.jboss.netty.channel.ChannelDownstreamHandler;
|
import org.jboss.netty.channel.ChannelDownstreamHandler;
|
||||||
import org.jboss.netty.channel.ChannelEvent;
|
import org.jboss.netty.channel.ChannelEvent;
|
||||||
import org.jboss.netty.channel.ChannelHandlerContext;
|
import org.jboss.netty.channel.ChannelHandlerContext;
|
||||||
|
@ -49,11 +51,11 @@ import org.jboss.netty.channel.MessageEvent;
|
||||||
*
|
*
|
||||||
* @version $Rev:231 $, $Date:2008-06-12 16:44:50 +0900 (목, 12 6월 2008) $
|
* @version $Rev:231 $, $Date:2008-06-12 16:44:50 +0900 (목, 12 6월 2008) $
|
||||||
*/
|
*/
|
||||||
@ChannelPipelineCoverage("all")
|
@ChannelPipelineCoverage("one")
|
||||||
public class CompatibleObjectEncoder implements ChannelDownstreamHandler {
|
public class CompatibleObjectEncoder implements ChannelDownstreamHandler {
|
||||||
|
|
||||||
// TODO Respect ChannelBufferFactory
|
private final AtomicReference<ChannelBuffer> buffer =
|
||||||
private final ChannelBuffer buffer = dynamicBuffer();
|
new AtomicReference<ChannelBuffer>();
|
||||||
private final int resetInterval;
|
private final int resetInterval;
|
||||||
private volatile ObjectOutputStream oout;
|
private volatile ObjectOutputStream oout;
|
||||||
private int writtenObjects;
|
private int writtenObjects;
|
||||||
|
@ -99,12 +101,8 @@ public class CompatibleObjectEncoder implements ChannelDownstreamHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageEvent e = (MessageEvent) evt;
|
MessageEvent e = (MessageEvent) evt;
|
||||||
|
ChannelBuffer buffer = buffer(context);
|
||||||
buffer.clear();
|
ObjectOutputStream oout = this.oout;
|
||||||
if (oout == null) {
|
|
||||||
oout = newObjectOutputStream(new ChannelBufferOutputStream(buffer));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (resetInterval != 0) {
|
if (resetInterval != 0) {
|
||||||
// Resetting will prevent OOM on the receiving side.
|
// Resetting will prevent OOM on the receiving side.
|
||||||
writtenObjects ++;
|
writtenObjects ++;
|
||||||
|
@ -116,6 +114,29 @@ public class CompatibleObjectEncoder implements ChannelDownstreamHandler {
|
||||||
oout.flush();
|
oout.flush();
|
||||||
|
|
||||||
ChannelBuffer encoded = buffer.readBytes(buffer.readableBytes());
|
ChannelBuffer encoded = buffer.readBytes(buffer.readableBytes());
|
||||||
|
buffer.discardReadBytes();
|
||||||
write(context, e.getChannel(), e.getFuture(), encoded, e.getRemoteAddress());
|
write(context, e.getChannel(), e.getFuture(), encoded, e.getRemoteAddress());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ChannelBuffer buffer(ChannelHandlerContext ctx) throws Exception {
|
||||||
|
ChannelBuffer buf = buffer.get();
|
||||||
|
if (buf == null) {
|
||||||
|
ChannelBufferFactory factory = ctx.getChannel().getConfig().getBufferFactory();
|
||||||
|
buf = ChannelBuffers.dynamicBuffer(factory);
|
||||||
|
if (buffer.compareAndSet(null, buf)) {
|
||||||
|
boolean success = false;
|
||||||
|
try {
|
||||||
|
oout = newObjectOutputStream(new ChannelBufferOutputStream(buf));
|
||||||
|
success = true;
|
||||||
|
} finally {
|
||||||
|
if (!success) {
|
||||||
|
oout = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
buf = buffer.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,9 +96,9 @@ public class ObjectEncoder implements ChannelDownstreamHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageEvent e = (MessageEvent) evt;
|
MessageEvent e = (MessageEvent) evt;
|
||||||
// TODO Respect ChannelBufferFactory
|
|
||||||
ChannelBufferOutputStream bout =
|
ChannelBufferOutputStream bout =
|
||||||
new ChannelBufferOutputStream(dynamicBuffer(estimatedLength));
|
new ChannelBufferOutputStream(dynamicBuffer(
|
||||||
|
estimatedLength, e.getChannel().getConfig().getBufferFactory()));
|
||||||
bout.write(LENGTH_PLACEHOLDER);
|
bout.write(LENGTH_PLACEHOLDER);
|
||||||
ObjectOutputStream oout = new CompactObjectOutputStream(bout);
|
ObjectOutputStream oout = new CompactObjectOutputStream(bout);
|
||||||
oout.writeObject(e.getMessage());
|
oout.writeObject(e.getMessage());
|
||||||
|
|
|
@ -92,8 +92,8 @@ public class ObjectEncoderOutputStream extends OutputStream implements
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeObject(Object obj) throws IOException {
|
public void writeObject(Object obj) throws IOException {
|
||||||
// TODO Respect ChannelBufferFactory
|
ChannelBufferOutputStream bout = new ChannelBufferOutputStream(
|
||||||
ChannelBufferOutputStream bout = new ChannelBufferOutputStream(ChannelBuffers.dynamicBuffer(estimatedLength));
|
ChannelBuffers.dynamicBuffer(estimatedLength));
|
||||||
ObjectOutputStream oout = new CompactObjectOutputStream(bout);
|
ObjectOutputStream oout = new CompactObjectOutputStream(bout);
|
||||||
oout.writeObject(obj);
|
oout.writeObject(obj);
|
||||||
oout.flush();
|
oout.flush();
|
||||||
|
|
Loading…
Reference in New Issue
Block a user