在使用协议缓冲区时,什么可能导致java.lang.OutOfMemoryError出现在这里?
运行下面的代码会导致Java堆空间出现异常在使用协议缓冲区时,什么可能导致java.lang.OutOfMemoryError出现在这里?,java,redis,protocol-buffers,jedis,Java,Redis,Protocol Buffers,Jedis,运行下面的代码会导致Java堆空间出现异常 来自.NET并掌握GC在那里工作的方式,我想知道在尝试运行以下内容时,在内存管理方面是否需要考虑: public static void main(String[] args) throws NumberFormatException, ParseException, IOException { Jedis jedis = new Jedis("<HostName>"); TimeSeriesPoints retriev
来自.NET并掌握GC在那里工作的方式,我想知道在尝试运行以下内容时,在内存管理方面是否需要考虑:
public static void main(String[] args) throws NumberFormatException, ParseException, IOException {
Jedis jedis = new Jedis("<HostName>");
TimeSeriesPoints retrieved = null;
while(!finished) {
try {
finished = true;
List<String> keys = getNextFiftyKeys();
String[] cacheKeys = new String[keys.size()];
List<String> cacheResults = jedis.mget(keys.toArray(cacheKeys));
List<TimeSeries> cachedTimeSeries = new ArrayList<TimeSeries>();
for(String cacheResult : cacheResults){
try {
retrieved = TimeSeriesPoints.parseFrom(cacheResult.getBytes());
TimeSeries timeSeries = new TimeSeries(retrieved.getName(), retrieved.getPointsList());
cachedTimeSeries.add(timeSeries);
}
catch (InvalidProtocolBufferException e) {
e.printStackTrace();
}
}
long pointsCount = 0;
for(TimeSeries timeSeries : cachedTimeSeries){
pointsCount += timeSeries.points.length;
}
System.out.println("retrieved: " + cachedTimeSeries.size());
System.out.println("points:" + pointsCount);
}
}
publicstaticvoidmain(String[]args)抛出NumberFormatException、ParseException、IOException{
绝地武士=新绝地武士(“”);
检索到的TimeSeriesPoints=null;
当(!完成){
试一试{
完成=正确;
List keys=getNextFiftyKeys();
String[]cacheKeys=新字符串[keys.size()];
List cacheResults=jedis.mget(keys.toArray(cacheKeys));
List cachedTimeSeries=new ArrayList();
for(字符串cacheResult:cacheResults){
试一试{
retrieved=TimeSeriesPoints.parseFrom(cacheResult.getBytes());
TimeSeries TimeSeries=新的TimeSeries(检索到的.getName(),检索到的.getPointsList());
cachedTimeSeries.add(timeSeries);
}
捕获(无效的RotocolBufferException e){
e、 printStackTrace();
}
}
long pointscont=0;
对于(TimeSeries TimeSeries:cachedTimeSeries){
pointsCount+=timeSeries.points.length;
}
System.out.println(“检索:“+cachedTimeSeries.size());
System.out.println(“点:“+pointscont”);
}
}
在TimeSeriesPoints.parseFrom抛出异常,堆栈跟踪如下。不确定确切原因
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Unknown Source)
at java.util.Arrays.copyOf(Unknown Source)
at java.util.ArrayList.ensureCapacity(Unknown Source)
at java.util.ArrayList.add(Unknown Source)
at com.wimiro.caching.TimeSeriesProtos$TimeSeriesPoints.<init>(TimeSeriesProtos.java:115)
at com.wimiro.caching.TimeSeriesProtos$TimeSeriesPoints.<init>(TimeSeriesProtos.java:82)
at com.wimiro.caching.TimeSeriesProtos$TimeSeriesPoints$1.parsePartialFrom(TimeSeriesProtos.java:151)
at com.wimiro.caching.TimeSeriesProtos$TimeSeriesPoints$1.parsePartialFrom(TimeSeriesProtos.java:1)
at com.google.protobuf.AbstractParser.parsePartialFrom(AbstractParser.java:141)
at com.google.protobuf.AbstractParser.parseFrom(AbstractParser.java:176)
at com.google.protobuf.AbstractParser.parseFrom(AbstractParser.java:188)
at com.google.protobuf.AbstractParser.parseFrom(AbstractParser.java:193)
at com.google.protobuf.AbstractParser.parseFrom(AbstractParser.java:49)
at com.wimiro.caching.TimeSeriesProtos$TimeSeriesPoints.parseFrom(TimeSeriesProtos.java:958)
at program.main(program.java:77)
线程“main”java.lang.OutOfMemoryError中的异常:java堆空间
位于java.util.Arrays.copyOf(未知源)
位于java.util.Arrays.copyOf(未知源)
位于java.util.ArrayList.ensureCapacity(未知源)
位于java.util.ArrayList.add(未知源)
在com.wimiro.caching.TimeSeriesProtos$TimeSeriesPoints.(TimeSeriesProtos.java:115)
位于com.wimiro.caching.TimeSeriesProtos$TimeSeriesPoints。(TimeSeriesProtos.java:82)
在com.wimiro.caching.TimeSeriesProtos$TimeSeriesPoints$1.parsePartialFrom(TimeSeriesProtos.java:151)上
在com.wimiro.caching.TimeSeriesProtos$TimeSeriesPoints$1.parsePartialFrom(TimeSeriesProtos.java:1)
位于com.google.protobuf.AbstractParser.parsePartialFrom(AbstractParser.java:141)
位于com.google.protobuf.AbstractParser.parseFrom(AbstractParser.java:176)
位于com.google.protobuf.AbstractParser.parseFrom(AbstractParser.java:188)
位于com.google.protobuf.AbstractParser.parseFrom(AbstractParser.java:193)
位于com.google.protobuf.AbstractParser.parseFrom(AbstractParser.java:49)
位于com.wimiro.caching.TimeSeriesProtos$TimeSeriesPoints.parseFrom(TimeSeriesProtos.java:958)
位于program.main(program.java:77)
这会导致尝试读取800个时间序列(每个都有大约4000个数据点)的失败。因为在本例中,我一次只处理50个时间序列,所以我不希望内存占用显著增加
在.NET中,我做这件事并不困难。那么,是时候学习一些Java了。我需要读些什么?您正在尝试从Java字符串(UTF-16)中获取字节数组,该字符串是从jedis(使用SafeCoder将UTF-16转换为bytearray)获得的,后者调用redis(C char 8位编码).我认为这是问题的根源,您的java字符串可能不正确,这导致protobuf失败 你应该尝试使用绝地武士的字节数组签名:
final List<byte[]> mget = jedis.mget(byteArray1, byteArray2, ...);
final List mget=jedis.mget(byteArray1,byteArray2,…);
然后尝试在字节数组上使用protobuf。另外,请检查如何使用jedis在redis中插入数据,在所有情况下,建议将字节数组签名与二进制数据一起使用。protobuf Java不幸地对重复的基元类型使用了非常低效的编码——每个元素都被装箱。例如,a
repeated int32
is表示为ArrayList
。理论上,这可以在protobuf实现中进行优化,但我知道上一次没有这样做。我猜您的问题就是由此产生的
如果还没有,请尝试增加JVM的最大堆大小(例如2GB的
-Xmx2g
。您可以添加TimeSeriesPoints.parseFrom(…)的代码吗?它有漏洞吗?它在protobuf-java2.5.0.jar中。如果这里有漏洞,那将是相当令人惊讶的。jedis.mget返回列表,而问题似乎在于TimeSeriesPoints。parseFrom@ofraski不,mget上存在重载。您可以直接使用ByteArray,从而绕过字符串和字节数据之间的转换错误。