From 32680b8f73631fe2f3139a123473b10ad6579681 Mon Sep 17 00:00:00 2001 From: nlevitt Date: Thu, 20 Oct 2011 02:21:54 +0000 Subject: [PATCH] Fix for HER-1960 kryo buffer can hog memory, lead to oome (bug report, patch from Kenji) * KryoBinding.java wrap ObjectBuffers with WeakReference so that can be garbage collected if necessary (when recreated they'll be back at the default size of 16k) --- .../java/org/archive/bdb/KryoBinding.java | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/commons/src/main/java/org/archive/bdb/KryoBinding.java b/commons/src/main/java/org/archive/bdb/KryoBinding.java index e9202d46..70002973 100644 --- a/commons/src/main/java/org/archive/bdb/KryoBinding.java +++ b/commons/src/main/java/org/archive/bdb/KryoBinding.java @@ -18,6 +18,8 @@ */ package org.archive.bdb; +import java.lang.ref.WeakReference; + import com.esotericsoftware.kryo.Kryo; import com.esotericsoftware.kryo.ObjectBuffer; import com.sleepycat.bind.EntryBinding; @@ -33,10 +35,10 @@ public class KryoBinding implements EntryBinding { protected Class baseClass; protected AutoKryo kryo = new AutoKryo(); - protected ThreadLocal threadBuffer = new ThreadLocal() { + protected ThreadLocal> threadBuffer = new ThreadLocal>() { @Override - protected ObjectBuffer initialValue() { - return new ObjectBuffer(kryo,16*1024,Integer.MAX_VALUE); + protected WeakReference initialValue() { + return new WeakReference(new ObjectBuffer(kryo,16*1024,Integer.MAX_VALUE)); } }; @@ -61,17 +63,27 @@ public class KryoBinding implements EntryBinding { return kryo; } + private ObjectBuffer getBuffer() { + WeakReference ref = threadBuffer.get(); + ObjectBuffer ob = ref.get(); + if (ob == null) { + ob = new ObjectBuffer(kryo,16*1024,Integer.MAX_VALUE); + threadBuffer.set(new WeakReference(ob)); + } + return ob; + } + /** * Copies superclass simply to allow different source for FastOoutputStream. * * @see com.sleepycat.bind.serial.SerialBinding#entryToObject */ public void objectToEntry(K object, DatabaseEntry entry) { - entry.setData(threadBuffer.get().writeObjectData(object)); + entry.setData(getBuffer().writeObjectData(object)); } @Override public K entryToObject(DatabaseEntry entry) { - return threadBuffer.get().readObjectData(entry.getData(), baseClass); + return getBuffer().readObjectData(entry.getData(), baseClass); } }