diff --git a/src/main/java/com/caucho/hessian/io/Hessian2Input.java b/src/main/java/com/caucho/hessian/io/Hessian2Input.java index 4f81721..2ebc650 100644 --- a/src/main/java/com/caucho/hessian/io/Hessian2Input.java +++ b/src/main/java/com/caucho/hessian/io/Hessian2Input.java @@ -2583,13 +2583,88 @@ public Object readObject() _isLastChunk = tag == 'B'; _chunkLength = (read() << 8) + read(); - int data; - ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ByteArrayOutputStream bos = null; + while (!_isLastChunk) { + if (bos == null) { + bos = new ByteArrayOutputStream(); + } + byte[] temp = new byte[_chunkLength]; + int i = 0; + + //处理完内存里的buffer + while (_offset < _length && i < _chunkLength) { + temp[i] = _buffer[_offset++]; + i++; + } + int needRead = _chunkLength - i; + if (needRead > 0) { + _is.read(temp, i, needRead); + } + + bos.write(temp); + + //读下一个块 + int code = read(); + switch (code) { + case 'b': + _isLastChunk = false; + _chunkLength = (read() << 8) + read(); + break; + + case 'B': + _isLastChunk = true; + _chunkLength = (read() << 8) + read(); + break; + + case 0x20: + case 0x21: + case 0x22: + case 0x23: + case 0x24: + case 0x25: + case 0x26: + case 0x27: + case 0x28: + case 0x29: + case 0x2a: + case 0x2b: + case 0x2c: + case 0x2d: + case 0x2e: + case 0x2f: + _isLastChunk = true; + _chunkLength = code - 0x20; + break; + + default: + throw expect("byte[]", code); + } + } - while ((data = parseByte()) >= 0) - bos.write(data); + byte[] res = new byte[_chunkLength]; + int i = 0; - return bos.toByteArray(); + //处理完内存里的buffer + while (_offset < _length && i < _chunkLength) { + res[i] = _buffer[_offset++]; + i++; + } + int needRead = _chunkLength - i; + if (needRead > 0) { + _is.read(res, i, needRead); + } + + if (bos != null) { + bos.write(res); + res = bos.toByteArray(); + } + + for (i = 0; i < res.length; i++) { + res[i] = (byte) (res[i] & 0xff); + } + + _chunkLength = 0; + return res; } case 0x20: diff --git a/src/test/java/com/caucho/hessian/io/Hessian2InputTest.java b/src/test/java/com/caucho/hessian/io/Hessian2InputTest.java new file mode 100644 index 0000000..e911df8 --- /dev/null +++ b/src/test/java/com/caucho/hessian/io/Hessian2InputTest.java @@ -0,0 +1,95 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.caucho.hessian.io; + +import org.junit.Assert; +import org.junit.Test; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +public class Hessian2InputTest { + + SerializerFactory serializerFactory = new SerializerFactory(); + + int[] sizeList = new int[] { + 0, 2, 16, 512, 1024, + 0x8000, 0x8000 + 1, + 64 * 1024, 64 * 1024 * 1024 + }; + + @Test + public void testSerialize() { + for (int i = 0; i < sizeList.length; i++) { + byte[] originBytes = generateLargeByteArray(sizeList[i]); + byte[] encodeBytes = hessianEncodeByte(originBytes); + byte[] decodeBytes = hessianDecodeByte(encodeBytes); + Assert.assertArrayEquals(originBytes, decodeBytes); + } + } + + @Test + public void testSerializeTime() { + byte[] originBytes = generateLargeByteArray(1024 * 1024); + byte[] encodeBytes = hessianEncodeByte(originBytes); + + long start = System.currentTimeMillis(); + for (int i = 0; i < 1000; i++) { + hessianDecodeByte(encodeBytes); + } + long end = System.currentTimeMillis(); + System.out.println("cost:" + (end - start)); + } + + private static byte[] generateLargeByteArray(int size) { + byte[] largeArray = new byte[size]; + for (int i = 0; i < size; i++) { + largeArray[i] = (byte) (i % 256); + } + return largeArray; + } + + private byte[] hessianEncodeByte(byte[] bytes) { + serializerFactory.setAllowNonSerializable(true); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + Hessian2Output output = new Hessian2Output(os); + output.setSerializerFactory(serializerFactory); + try { + output.writeObject(bytes); + output.close(); + } catch (IOException e) { + throw new RuntimeException(e); + } + return os.toByteArray(); + } + + private byte[] hessianDecodeByte(byte[] bytes) { + ByteArrayInputStream bis = new ByteArrayInputStream(bytes); + Hessian2Input input = new Hessian2Input(bis); + input.setSerializerFactory(serializerFactory); + byte[] decodeObject; + try { + decodeObject = (byte[]) input.readObject(); + input.close(); + } catch (IOException e) { + throw new RuntimeException(e); + } + return decodeObject; + } + +} \ No newline at end of file