diff --git a/source/net/yacy/kelondro/blob/MapView.java b/source/net/yacy/kelondro/blob/MapView.java index d37db3f37..9125c0ec4 100644 --- a/source/net/yacy/kelondro/blob/MapView.java +++ b/source/net/yacy/kelondro/blob/MapView.java @@ -116,11 +116,12 @@ public class MapView { return bb.toString(); } - private static Map bytes2map(byte[] b) throws IOException { + private static Map bytes2map(byte[] b) throws IOException, RowSpaceExceededException { final BufferedReader br = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(b))); final Map map = new HashMap(); String line; int pos; + try { while ((line = br.readLine()) != null) { // very slow readLine???? line = line.trim(); if (line.equals("# EOF")) return map; @@ -129,6 +130,9 @@ public class MapView { if (pos < 0) continue; map.put(line.substring(0, pos), line.substring(pos + 1)); } + } catch (OutOfMemoryError e) { + throw new RowSpaceExceededException(0, "readLine probably uses too much RAM", e); + } return map; } @@ -229,7 +233,11 @@ public class MapView { // read object final byte[] b = blob.get(keyb); if (b == null) return null; - map = bytes2map(b); + try { + map = bytes2map(b); + } catch (RowSpaceExceededException e) { + throw new IOException(e.getMessage()); + } // write map to cache cache.put(key, map); @@ -245,7 +253,11 @@ public class MapView { b = blob.get(keyb); } if (b == null) return null; - return bytes2map(b); + try { + return bytes2map(b); + } catch (RowSpaceExceededException e) { + throw new IOException(e.getMessage()); + } } } diff --git a/source/net/yacy/kelondro/index/RowSpaceExceededException.java b/source/net/yacy/kelondro/index/RowSpaceExceededException.java index f9002af49..597ac90d1 100644 --- a/source/net/yacy/kelondro/index/RowSpaceExceededException.java +++ b/source/net/yacy/kelondro/index/RowSpaceExceededException.java @@ -45,6 +45,14 @@ public class RowSpaceExceededException extends Exception { this.forUsage = forUsage; } + public RowSpaceExceededException(long neededRAM, String forUsage, Throwable t) { + super(Long.toString(neededRAM) + " bytes needed for " + forUsage + ": " + MemoryControl.available() + " free at " + (new Date()).toString(), t); + this.time = System.currentTimeMillis(); + this.availableRAM = MemoryControl.available(); + this.neededRAM = neededRAM; + this.forUsage = forUsage; + } + public String getUsage() { return forUsage; }