提交 0c1a0c12 authored 作者: Thomas Mueller's avatar Thomas Mueller

improve out of memory message

上级 1d514d5b
...@@ -9,6 +9,8 @@ package org.h2.compress; ...@@ -9,6 +9,8 @@ package org.h2.compress;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import org.h2.util.ByteUtils;
/** /**
* An input stream to read from an LZF stream. * An input stream to read from an LZF stream.
* The data is automatically expanded. * The data is automatically expanded.
...@@ -30,7 +32,7 @@ public class LZFInputStream extends InputStream { ...@@ -30,7 +32,7 @@ public class LZFInputStream extends InputStream {
} }
private byte[] ensureSize(byte[] buff, int len) { private byte[] ensureSize(byte[] buff, int len) {
return buff == null || buff.length < len ? new byte[len] : buff; return buff == null || buff.length < len ? ByteUtils.newBytes(len) : buff;
} }
private void fillBuffer() throws IOException { private void fillBuffer() throws IOException {
......
...@@ -40,6 +40,7 @@ import org.h2.table.TableFilter; ...@@ -40,6 +40,7 @@ import org.h2.table.TableFilter;
import org.h2.tools.CompressTool; import org.h2.tools.CompressTool;
import org.h2.tools.Csv; import org.h2.tools.Csv;
import org.h2.util.AutoCloseInputStream; import org.h2.util.AutoCloseInputStream;
import org.h2.util.ByteUtils;
import org.h2.util.DateTimeUtils; import org.h2.util.DateTimeUtils;
import org.h2.util.FileUtils; import org.h2.util.FileUtils;
import org.h2.util.MathUtils; import org.h2.util.MathUtils;
...@@ -1118,7 +1119,7 @@ public class Function extends Expression implements FunctionCall { ...@@ -1118,7 +1119,7 @@ public class Function extends Expression implements FunctionCall {
private byte[] getPaddedArrayCopy(byte[] data, int blockSize) { private byte[] getPaddedArrayCopy(byte[] data, int blockSize) {
int size = MathUtils.roundUp(data.length, blockSize); int size = MathUtils.roundUp(data.length, blockSize);
byte[] newData = new byte[size]; byte[] newData = ByteUtils.newBytes(size);
System.arraycopy(data, 0, newData, 0, data.length); System.arraycopy(data, 0, newData, 0, data.length);
return newData; return newData;
} }
......
...@@ -21,6 +21,7 @@ import org.h2.store.DiskFile; ...@@ -21,6 +21,7 @@ import org.h2.store.DiskFile;
import org.h2.store.FileStore; import org.h2.store.FileStore;
import org.h2.store.Record; import org.h2.store.Record;
import org.h2.store.Storage; import org.h2.store.Storage;
import org.h2.util.ByteUtils;
import org.h2.util.FileUtils; import org.h2.util.FileUtils;
import org.h2.util.MathUtils; import org.h2.util.MathUtils;
import org.h2.util.ObjectArray; import org.h2.util.ObjectArray;
...@@ -216,7 +217,7 @@ public class LogFile { ...@@ -216,7 +217,7 @@ public class LogFile {
DataPage s = DataPage.create(database, buff); DataPage s = DataPage.create(database, buff);
int blocks = Math.abs(s.readInt()); int blocks = Math.abs(s.readInt());
if (blocks > 1) { if (blocks > 1) {
byte[] b2 = new byte[blocks * BLOCK_SIZE]; byte[] b2 = ByteUtils.newBytes(blocks * BLOCK_SIZE);
System.arraycopy(buff, 0, b2, 0, BLOCK_SIZE); System.arraycopy(buff, 0, b2, 0, BLOCK_SIZE);
buff = b2; buff = b2;
file.readFully(buff, BLOCK_SIZE, blocks * BLOCK_SIZE - BLOCK_SIZE); file.readFully(buff, BLOCK_SIZE, blocks * BLOCK_SIZE - BLOCK_SIZE);
...@@ -306,7 +307,7 @@ public class LogFile { ...@@ -306,7 +307,7 @@ public class LogFile {
break; break;
} }
int sumLength = in.readInt(); int sumLength = in.readInt();
byte[] summary = new byte[sumLength]; byte[] summary = ByteUtils.newBytes(sumLength);
if (sumLength > 0) { if (sumLength > 0) {
in.read(summary, 0, sumLength); in.read(summary, 0, sumLength);
} }
......
...@@ -34,6 +34,7 @@ import org.h2.constant.SysProperties; ...@@ -34,6 +34,7 @@ import org.h2.constant.SysProperties;
import org.h2.engine.ConnectionInfo; import org.h2.engine.ConnectionInfo;
import org.h2.jdbc.JdbcConnection; import org.h2.jdbc.JdbcConnection;
import org.h2.message.Message; import org.h2.message.Message;
import org.h2.util.ByteUtils;
import org.h2.util.IOUtils; import org.h2.util.IOUtils;
import org.h2.util.JdbcUtils; import org.h2.util.JdbcUtils;
import org.h2.util.ObjectUtils; import org.h2.util.ObjectUtils;
...@@ -132,7 +133,7 @@ public class PgServerThread implements Runnable { ...@@ -132,7 +133,7 @@ public class PgServerThread implements Runnable {
} }
int len = dataInRaw.readInt(); int len = dataInRaw.readInt();
len -= 4; len -= 4;
byte[] data = new byte[len]; byte[] data = ByteUtils.newBytes(len);
dataInRaw.readFully(data, 0, len); dataInRaw.readFully(data, 0, len);
dataIn = new DataInputStream(new ByteArrayInputStream(data, 0, len)); dataIn = new DataInputStream(new ByteArrayInputStream(data, 0, len));
switch (x) { switch (x) {
...@@ -244,7 +245,7 @@ public class PgServerThread implements Runnable { ...@@ -244,7 +245,7 @@ public class PgServerThread implements Runnable {
int paramCount = readShort(); int paramCount = readShort();
for (int i = 0; i < paramCount; i++) { for (int i = 0; i < paramCount; i++) {
int paramLen = readInt(); int paramLen = readInt();
byte[] d2 = new byte[paramLen]; byte[] d2 = ByteUtils.newBytes(paramLen);
readFully(d2); readFully(d2);
try { try {
setParameter(portal.prep, i, d2, formatCodes); setParameter(portal.prep, i, d2, formatCodes);
......
...@@ -62,6 +62,7 @@ import org.h2.tools.Restore; ...@@ -62,6 +62,7 @@ import org.h2.tools.Restore;
import org.h2.tools.RunScript; import org.h2.tools.RunScript;
import org.h2.tools.Script; import org.h2.tools.Script;
import org.h2.tools.SimpleResultSet; import org.h2.tools.SimpleResultSet;
import org.h2.util.ByteUtils;
import org.h2.util.IOUtils; import org.h2.util.IOUtils;
import org.h2.util.JdbcUtils; import org.h2.util.JdbcUtils;
import org.h2.util.MathUtils; import org.h2.util.MathUtils;
...@@ -402,7 +403,7 @@ class WebThread extends Thread implements DatabaseEventListener { ...@@ -402,7 +403,7 @@ class WebThread extends Thread implements DatabaseEventListener {
} }
} }
if (session != null && len > 0) { if (session != null && len > 0) {
byte[] bytes = new byte[len]; byte[] bytes = ByteUtils.newBytes(len);
for (int pos = 0; pos < len;) { for (int pos = 0; pos < len;) {
pos += input.read(bytes, pos, len - pos); pos += input.read(bytes, pos, len - pos);
} }
......
...@@ -15,6 +15,7 @@ import java.sql.Timestamp; ...@@ -15,6 +15,7 @@ import java.sql.Timestamp;
import org.h2.constant.SysProperties; import org.h2.constant.SysProperties;
import org.h2.engine.Constants; import org.h2.engine.Constants;
import org.h2.message.Message; import org.h2.message.Message;
import org.h2.util.ByteUtils;
import org.h2.util.MathUtils; import org.h2.util.MathUtils;
import org.h2.value.Value; import org.h2.value.Value;
import org.h2.value.ValueArray; import org.h2.value.ValueArray;
...@@ -200,7 +201,7 @@ public abstract class DataPage { ...@@ -200,7 +201,7 @@ public abstract class DataPage {
*/ */
public void checkCapacity(int plus) { public void checkCapacity(int plus) {
if (pos + plus >= data.length) { if (pos + plus >= data.length) {
byte[] d = new byte[(data.length + plus) * 2]; byte[] d = ByteUtils.newBytes((data.length + plus) * 2);
// must copy everything, because pos could be 0 and data may be // must copy everything, because pos could be 0 and data may be
// still required // still required
System.arraycopy(data, 0, d, 0, data.length); System.arraycopy(data, 0, d, 0, data.length);
...@@ -545,13 +546,13 @@ public abstract class DataPage { ...@@ -545,13 +546,13 @@ public abstract class DataPage {
} }
case Value.JAVA_OBJECT: { case Value.JAVA_OBJECT: {
int len = readInt(); int len = readInt();
byte[] b = createByteArray(len); byte[] b = ByteUtils.newBytes(len);
read(b, 0, len); read(b, 0, len);
return ValueJavaObject.getNoCopy(b); return ValueJavaObject.getNoCopy(b);
} }
case Value.BYTES: { case Value.BYTES: {
int len = readInt(); int len = readInt();
byte[] b = createByteArray(len); byte[] b = ByteUtils.newBytes(len);
read(b, 0, len); read(b, 0, len);
return ValueBytes.getNoCopy(b); return ValueBytes.getNoCopy(b);
} }
...@@ -571,7 +572,7 @@ public abstract class DataPage { ...@@ -571,7 +572,7 @@ public abstract class DataPage {
case Value.CLOB: { case Value.CLOB: {
int smallLen = readInt(); int smallLen = readInt();
if (smallLen >= 0) { if (smallLen >= 0) {
byte[] small = createByteArray(smallLen); byte[] small = ByteUtils.newBytes(smallLen);
read(small, 0, smallLen); read(small, 0, smallLen);
return ValueLob.createSmallLob(dataType, small); return ValueLob.createSmallLob(dataType, small);
} }
...@@ -605,16 +606,6 @@ public abstract class DataPage { ...@@ -605,16 +606,6 @@ public abstract class DataPage {
} }
} }
private byte[] createByteArray(int len) {
try {
return new byte[len];
} catch (OutOfMemoryError e) {
Error e2 = new OutOfMemoryError("Requested memory: " + len);
e2.initCause(e);
throw e2;
}
}
/** /**
* Fill up the buffer with empty space and an (initially empty) checksum * Fill up the buffer with empty space and an (initially empty) checksum
* until the size is a multiple of Constants.FILE_BLOCK_SIZE. * until the size is a multiple of Constants.FILE_BLOCK_SIZE.
......
...@@ -28,6 +28,7 @@ import org.h2.log.RedoLogRecord; ...@@ -28,6 +28,7 @@ import org.h2.log.RedoLogRecord;
import org.h2.message.Message; import org.h2.message.Message;
import org.h2.message.Trace; import org.h2.message.Trace;
import org.h2.util.BitField; import org.h2.util.BitField;
import org.h2.util.ByteUtils;
import org.h2.util.Cache; import org.h2.util.Cache;
import org.h2.util.Cache2Q; import org.h2.util.Cache2Q;
import org.h2.util.CacheLRU; import org.h2.util.CacheLRU;
...@@ -584,7 +585,7 @@ public class DiskFile implements CacheWriter { ...@@ -584,7 +585,7 @@ public class DiskFile implements CacheWriter {
throw Message.getInternalError("0 blocks to read pos=" + pos); throw Message.getInternalError("0 blocks to read pos=" + pos);
} }
if (blockCount > 1) { if (blockCount > 1) {
byte[] b2 = new byte[blockCount * BLOCK_SIZE]; byte[] b2 = ByteUtils.newBytes(blockCount * BLOCK_SIZE);
System.arraycopy(buff, 0, b2, 0, BLOCK_SIZE); System.arraycopy(buff, 0, b2, 0, BLOCK_SIZE);
buff = b2; buff = b2;
file.readFully(buff, BLOCK_SIZE, blockCount * BLOCK_SIZE - BLOCK_SIZE); file.readFully(buff, BLOCK_SIZE, blockCount * BLOCK_SIZE - BLOCK_SIZE);
......
...@@ -14,6 +14,7 @@ import org.h2.constant.SysProperties; ...@@ -14,6 +14,7 @@ import org.h2.constant.SysProperties;
import org.h2.engine.Constants; import org.h2.engine.Constants;
import org.h2.message.Message; import org.h2.message.Message;
import org.h2.tools.CompressTool; import org.h2.tools.CompressTool;
import org.h2.util.ByteUtils;
/** /**
* An input stream that is backed by a file store. * An input stream that is backed by a file store.
...@@ -119,7 +120,7 @@ public class FileStoreInputStream extends InputStream { ...@@ -119,7 +120,7 @@ public class FileStoreInputStream extends InputStream {
page.readInt(); page.readInt();
if (compress != null) { if (compress != null) {
int uncompressed = page.readInt(); int uncompressed = page.readInt();
byte[] buff = new byte[remainingInBuffer]; byte[] buff = ByteUtils.newBytes(remainingInBuffer);
page.read(buff, 0, remainingInBuffer); page.read(buff, 0, remainingInBuffer);
page.reset(); page.reset();
page.checkCapacity(uncompressed); page.checkCapacity(uncompressed);
......
...@@ -9,6 +9,8 @@ package org.h2.store.fs; ...@@ -9,6 +9,8 @@ package org.h2.store.fs;
import java.io.EOFException; import java.io.EOFException;
import java.io.IOException; import java.io.IOException;
import org.h2.util.ByteUtils;
/** /**
* In this file system, files are kept fully in memory until stored. * In this file system, files are kept fully in memory until stored.
*/ */
...@@ -55,7 +57,7 @@ public class FileObjectDatabase implements FileObject { ...@@ -55,7 +57,7 @@ public class FileObjectDatabase implements FileObject {
public void setFileLength(long newLength) { public void setFileLength(long newLength) {
this.length = (int) newLength; this.length = (int) newLength;
if (length != data.length) { if (length != data.length) {
byte[] n = new byte[length]; byte[] n = ByteUtils.newBytes(length);
System.arraycopy(data, 0, n, 0, Math.min(data.length, n.length)); System.arraycopy(data, 0, n, 0, Math.min(data.length, n.length));
data = n; data = n;
changed = true; changed = true;
...@@ -73,7 +75,7 @@ public class FileObjectDatabase implements FileObject { ...@@ -73,7 +75,7 @@ public class FileObjectDatabase implements FileObject {
public void write(byte[] b, int off, int len) { public void write(byte[] b, int off, int len) {
if (pos + len > data.length) { if (pos + len > data.length) {
int newLen = Math.max(data.length * 2, pos + len); int newLen = Math.max(data.length * 2, pos + len);
byte[] n = new byte[newLen]; byte[] n = ByteUtils.newBytes(newLen);
System.arraycopy(data, 0, n, 0, length); System.arraycopy(data, 0, n, 0, length);
data = n; data = n;
} }
......
...@@ -26,6 +26,7 @@ import org.h2.compress.LZFInputStream; ...@@ -26,6 +26,7 @@ import org.h2.compress.LZFInputStream;
import org.h2.compress.LZFOutputStream; import org.h2.compress.LZFOutputStream;
import org.h2.constant.ErrorCode; import org.h2.constant.ErrorCode;
import org.h2.message.Message; import org.h2.message.Message;
import org.h2.util.ByteUtils;
import org.h2.util.StringUtils; import org.h2.util.StringUtils;
/** /**
...@@ -43,10 +44,10 @@ public class CompressTool { ...@@ -43,10 +44,10 @@ public class CompressTool {
private static byte[] getBuffer(int min) { private static byte[] getBuffer(int min) {
if (min > MAX_BUFFER_SIZE) { if (min > MAX_BUFFER_SIZE) {
return new byte[min]; return ByteUtils.newBytes(min);
} }
if (buffer == null || buffer.length < min) { if (buffer == null || buffer.length < min) {
buffer = new byte[min]; buffer = ByteUtils.newBytes(min);
} }
return buffer; return buffer;
} }
...@@ -77,7 +78,7 @@ public class CompressTool { ...@@ -77,7 +78,7 @@ public class CompressTool {
Compressor compress = getCompressor(algorithm); Compressor compress = getCompressor(algorithm);
byte[] buff = getBuffer((len < 100 ? len + 100 : len) * 2); byte[] buff = getBuffer((len < 100 ? len + 100 : len) * 2);
int newLen = compress(in, in.length, compress, buff); int newLen = compress(in, in.length, compress, buff);
byte[] out = new byte[newLen]; byte[] out = ByteUtils.newBytes(newLen);
System.arraycopy(buff, 0, out, 0, newLen); System.arraycopy(buff, 0, out, 0, newLen);
return out; return out;
} }
...@@ -111,7 +112,7 @@ public class CompressTool { ...@@ -111,7 +112,7 @@ public class CompressTool {
try { try {
int len = readInt(in, 1); int len = readInt(in, 1);
int start = 1 + getLength(len); int start = 1 + getLength(len);
byte[] buff = new byte[len]; byte[] buff = ByteUtils.newBytes(len);
compress.expand(in, start, in.length - start, buff, 0, len); compress.expand(in, start, in.length - start, buff, 0, len);
return buff; return buff;
} catch (Exception e) { } catch (Exception e) {
......
...@@ -490,7 +490,7 @@ public class Recover extends Tool implements DataHandler { ...@@ -490,7 +490,7 @@ public class Recover extends Tool implements DataHandler {
s = DataPage.create(this, buff); s = DataPage.create(this, buff);
blocks = Math.abs(s.readInt()); blocks = Math.abs(s.readInt());
if (blocks > 1) { if (blocks > 1) {
byte[] b2 = new byte[blocks * blockSize]; byte[] b2 = ByteUtils.newBytes(blocks * blockSize);
System.arraycopy(buff, 0, b2, 0, blockSize); System.arraycopy(buff, 0, b2, 0, blockSize);
buff = b2; buff = b2;
try { try {
...@@ -525,7 +525,7 @@ public class Recover extends Tool implements DataHandler { ...@@ -525,7 +525,7 @@ public class Recover extends Tool implements DataHandler {
case 'S': { case 'S': {
char fileType = (char) s.readByte(); char fileType = (char) s.readByte();
int sumLength = s.readInt(); int sumLength = s.readInt();
byte[] summary = new byte[sumLength]; byte[] summary = ByteUtils.newBytes(sumLength);
if (sumLength > 0) { if (sumLength > 0) {
s.read(summary, 0, sumLength); s.read(summary, 0, sumLength);
} }
......
...@@ -238,4 +238,23 @@ public class ByteUtils { ...@@ -238,4 +238,23 @@ public class ByteUtils {
return copy; return copy;
} }
/**
* Create an array of bytes with the given size. If this is not possible
* because not enough memory is available, an OutOfMemoryError with the
* requested size in the message is thrown.
*
* @param len the number of bytes requested
* @return the byte array
* @throws OutOfMemoryError
*/
public static byte[] newBytes(int len) {
try {
return new byte[len];
} catch (OutOfMemoryError e) {
Error e2 = new OutOfMemoryError("Requested memory: " + len);
e2.initCause(e);
throw e2;
}
}
} }
...@@ -33,6 +33,7 @@ import org.h2.engine.SessionInterface; ...@@ -33,6 +33,7 @@ import org.h2.engine.SessionInterface;
import org.h2.message.Message; import org.h2.message.Message;
import org.h2.message.TraceSystem; import org.h2.message.TraceSystem;
import org.h2.tools.SimpleResultSet; import org.h2.tools.SimpleResultSet;
import org.h2.util.ByteUtils;
import org.h2.util.ExactUTF8InputStreamReader; import org.h2.util.ExactUTF8InputStreamReader;
import org.h2.util.IOUtils; import org.h2.util.IOUtils;
import org.h2.util.NetUtils; import org.h2.util.NetUtils;
...@@ -273,7 +274,7 @@ public class Transfer { ...@@ -273,7 +274,7 @@ public class Transfer {
if (len == -1) { if (len == -1) {
return null; return null;
} }
byte[] b = new byte[len]; byte[] b = ByteUtils.newBytes(len);
in.readFully(b); in.readFully(b);
return b; return b;
} }
......
...@@ -342,10 +342,10 @@ public class ValueLob extends Value { ...@@ -342,10 +342,10 @@ public class ValueLob extends Value {
remaining = length; remaining = length;
} }
int len = getBufferSize(handler, compress, remaining); int len = getBufferSize(handler, compress, remaining);
byte[] buff = new byte[len]; byte[] buff = ByteUtils.newBytes(len);
len = IOUtils.readFully(in, buff, 0, len); len = IOUtils.readFully(in, buff, 0, len);
if (len <= handler.getMaxLengthInplaceLob()) { if (len <= handler.getMaxLengthInplaceLob()) {
byte[] small = new byte[len]; byte[] small = ByteUtils.newBytes(len);
System.arraycopy(buff, 0, small, 0, len); System.arraycopy(buff, 0, small, 0, len);
return ValueLob.createSmallLob(Value.BLOB, small); return ValueLob.createSmallLob(Value.BLOB, small);
} }
...@@ -693,7 +693,7 @@ public class ValueLob extends Value { ...@@ -693,7 +693,7 @@ public class ValueLob extends Value {
int len = getBufferSize(handler, compress, Long.MAX_VALUE); int len = getBufferSize(handler, compress, Long.MAX_VALUE);
int tabId = tableId; int tabId = tableId;
if (type == Value.BLOB) { if (type == Value.BLOB) {
createFromStream(new byte[len], 0, getInputStream(), Long.MAX_VALUE, handler); createFromStream(ByteUtils.newBytes(len), 0, getInputStream(), Long.MAX_VALUE, handler);
} else { } else {
createFromReader(new char[len], 0, getReader(), Long.MAX_VALUE, handler); createFromReader(new char[len], 0, getReader(), Long.MAX_VALUE, handler);
} }
......
...@@ -266,8 +266,6 @@ java org.h2.test.TestAll timer ...@@ -266,8 +266,6 @@ java org.h2.test.TestAll timer
/* /*
move DataPage.createByteArray to ByteUtils, improve message
run the performance tests as part of the unit test run the performance tests as part of the unit test
switch to JDK 1.6 by default switch to JDK 1.6 by default
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论