创建具有大 (>1GB) BytesWritable 值大小的 SequenceFile 时出现 NegativeArraySizeException
Posted
技术标签:
【中文标题】创建具有大 (>1GB) BytesWritable 值大小的 SequenceFile 时出现 NegativeArraySizeException【英文标题】:NegativeArraySizeException when creating a SequenceFile with large (>1GB) BytesWritable value size 【发布时间】:2014-07-30 09:47:38 【问题描述】:我尝试了不同的方法来创建一个大型 Hadoop SequenceFile 只需一个短 (1GB) 值 (BytesWriteable)。
以下示例适用于开箱即用:
https://svn.apache.org/repos/asf/hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-jobclient/src/test/java/org/apache/hadoop/mapred/BigMapOutput.java
写入多个随机长度的键和值,总大小>3GB。
但是,这不是我想要做的。所以我使用 hadoop 2.2.0 API 将其修改为:
Path file = new Path("/input");
SequenceFile.Writer writer = SequenceFile.createWriter(conf,
SequenceFile.Writer.file(file),
SequenceFile.Writer.compression(CompressionType.NONE),
SequenceFile.Writer.keyClass(BytesWritable.class),
SequenceFile.Writer.valueClass(BytesWritable.class));
int numBytesToWrite = fileSizeInMB * 1024 * 1024;
BytesWritable randomKey = new BytesWritable();
BytesWritable randomValue = new BytesWritable();
randomKey.setSize(1);
randomValue.setSize(numBytesToWrite);
randomizeBytes(randomValue.getBytes(), 0, randomValue.getLength());
writer.append(randomKey, randomValue);
writer.close();
当 fileSizeInMB>700MB 时,我收到如下错误:
java.lang.NegativeArraySizeException
at org.apache.hadoop.io.BytesWritable.setCapacity(BytesWritable.java:144)
at org.apache.hadoop.io.BytesWritable.setSize(BytesWritable.java:123)
...
我看到正在讨论这个错误,但没有看到任何解决方案。请注意,int(2^32) 可以大到 2GB,它不应该在 700MB 时失败。
如果您有其他替代方法来创建如此大值的 SequenceFile,请告知。我尝试了其他方法,例如 IOutils.read 从输入流到字节 [],我得到了堆大小或 OOME。
【问题讨论】:
你好。我现在面临同样的问题。你解决了这个错误吗?请分享。 【参考方案1】:只需使用 ArrayPrimitiveWritable 代替。
在BytesWritable这里设置新容量会导致int溢出:
public void setSize(int size)
if (size > getCapacity())
setCapacity(size * 3 / 2);
this.size = size;
700 Mb * 3 > 2Gb = int 溢出!
因此,您无法将超过 700 Mb 的数据反序列化(但可以写入和序列化)到 BytesWritable。
【讨论】:
这个问题已经解决了;在current implementation 中,他们使用 longs 来避免不必要的溢出。【参考方案2】:如果您想使用BytesWritable
,可以选择之前将容量设置为足够高,这样您就可以使用2GB,而不仅仅是700MB:
randomValue.setCapacity(numBytesToWrite);
randomValue.setSize(numBytesToWrite); // will not resize now
这个错误最近已在 Hadoop 中修复,因此在新版本中即使没有它也应该可以工作:
public void setSize(int size)
if (size > getCapacity())
// Avoid overflowing the int too early by casting to a long.
long newSize = Math.min(Integer.MAX_VALUE, (3L * size) / 2L);
setCapacity((int) newSize);
this.size = size;
【讨论】:
以上是关于创建具有大 (>1GB) BytesWritable 值大小的 SequenceFile 时出现 NegativeArraySizeException的主要内容,如果未能解决你的问题,请参考以下文章