diff --git a/src/freenet/config/SubConfig.java b/src/freenet/config/SubConfig.java index 8a2f5d28ab..7fc66d54d9 100644 --- a/src/freenet/config/SubConfig.java +++ b/src/freenet/config/SubConfig.java @@ -172,7 +172,8 @@ public int getInt(String optionName) { synchronized(this) { o = (IntOption) map.get(optionName); } - return o.getValue(); + // return fallback value for ignored options (null). This avoids breaking plugins which try to get ignored options. + return o == null ? -1 : o.getValue(); } public long getLong(String optionName) { @@ -180,7 +181,8 @@ public long getLong(String optionName) { synchronized(this) { o = (LongOption) map.get(optionName); } - return o.getValue(); + // return fallback value for ignored options (null). This avoids breaking plugins which try to get ignored options. + return o == null ? -1L : o.getValue(); } public boolean getBoolean(String optionName) { @@ -188,7 +190,8 @@ public boolean getBoolean(String optionName) { synchronized(this) { o = (BooleanOption) map.get(optionName); } - return o.getValue(); + // return fallback value for ignored options (null). This avoids breaking plugins which try to get ignored options. + return o == null ? false : o.getValue(); } public String getString(String optionName) { @@ -196,7 +199,8 @@ public String getString(String optionName) { synchronized(this) { o = (StringOption) map.get(optionName); } - return o.getValue().trim(); + // return fallback value for ignored options (null). This avoids breaking plugins which try to get ignored options. + return o == null ? "" : o.getValue().trim(); } public String[] getStringArr(String optionName) { @@ -204,7 +208,8 @@ public String[] getStringArr(String optionName) { synchronized(this) { o = (StringArrOption) map.get(optionName); } - return o.getValue(); + // return fallback value for ignored options (null). This avoids breaking plugins which try to get ignored options. + return o == null ? new String[]{} : o.getValue(); } public short getShort(String optionName) { @@ -212,7 +217,8 @@ public short getShort(String optionName) { synchronized(this) { o = (ShortOption) map.get(optionName); } - return o.getValue(); + // return fallback value for ignored options (null). This avoids breaking plugins which try to get ignored options. + return o == null ? -1 : o.getValue(); } public Option removeOption(String optionName) { diff --git a/src/freenet/node/MemoryChecker.java b/src/freenet/node/MemoryChecker.java index 1892338076..47bab6829e 100644 --- a/src/freenet/node/MemoryChecker.java +++ b/src/freenet/node/MemoryChecker.java @@ -14,8 +14,7 @@ public class MemoryChecker implements Runnable { private volatile boolean goon = false; private final Ticker ps; private int aggressiveGCModificator; - private RunningAverage avgFreeMemory; - + public MemoryChecker(Ticker ps, int modificator){ this.ps = ps; this.aggressiveGCModificator = modificator; @@ -48,61 +47,14 @@ public void run() { long totalMemory = r.totalMemory(); long freeMemory = r.freeMemory(); - long maxMemory = r.maxMemory(); Logger.normal(this, "Memory in use: "+SizeUtil.formatSize((totalMemory-freeMemory))); - if (totalMemory == maxMemory || maxMemory == Long.MAX_VALUE) { - // jvm have allocated maximum memory - // totalMemory never decrease, so check it only for once - if (avgFreeMemory == null) - avgFreeMemory = new SimpleRunningAverage(3, freeMemory); - else - avgFreeMemory.report(freeMemory); - - if (avgFreeMemory.countReports() >= 3 && avgFreeMemory.currentValue() < 4 * 1024 * 1024) {// average free memory < 4 MB - Logger.normal(this, "Reached threshold, checking for low memory ..."); - System.gc(); - System.runFinalization(); - - try { - Thread.sleep(10); // Force a context switch, finalization need a CS to complete - } catch (InterruptedException e) { - } - - freeMemory = r.freeMemory(); - avgFreeMemory.report(freeMemory); - } - } - int sleeptime = aggressiveGCModificator; if(sleeptime <= 0) { // We are done ps.queueTimedJob(this, 120 * 250); // 30 sec - return; } else ps.queueTimedJob(this, 120L * sleeptime); - - // FIXME - // Do not remove until all known memory issues fixed, - // Especially #66 - // This probably reduces performance, but it makes - // memory usage *more predictable*. This will make - // tracking down the sort of nasty unpredictable OOMs - // we are getting much easier. - if(aggressiveGCModificator > 0) { - boolean logMINOR = Logger.shouldLog(LogLevel.MINOR, this); - long beforeGCUsedMemory = (r.totalMemory() - r.freeMemory()); - if(logMINOR) Logger.minor(this, "Memory in use before GC: "+beforeGCUsedMemory); - long beforeGCTime = System.currentTimeMillis(); - System.gc(); - System.runFinalization(); - long afterGCTime = System.currentTimeMillis(); - long afterGCUsedMemory = (r.totalMemory() - r.freeMemory()); - if(logMINOR) { - Logger.minor(this, "Memory in use after GC: "+afterGCUsedMemory); - Logger.minor(this, "GC completed after "+(afterGCTime - beforeGCTime)+"ms and \"recovered\" "+(beforeGCUsedMemory - afterGCUsedMemory)+" bytes, leaving "+afterGCUsedMemory+" bytes used"); - } - } } } diff --git a/src/freenet/node/NodeStats.java b/src/freenet/node/NodeStats.java index 986edcc440..2564af71e1 100644 --- a/src/freenet/node/NodeStats.java +++ b/src/freenet/node/NodeStats.java @@ -407,21 +407,7 @@ public void set(Integer val) throws InvalidConfigValueException { threadLimit = statsConfig.getInt("threadLimit"); // Yes it could be in seconds insteed of multiples of 0.12, but we don't want people to play with it :) - statsConfig.register("aggressiveGC", aggressiveGCModificator, sortOrder++, true, false, "NodeStat.aggressiveGC", "NodeStat.aggressiveGCLong", - new IntCallback() { - @Override - public Integer get() { - return aggressiveGCModificator; - } - @Override - public void set(Integer val) throws InvalidConfigValueException { - if (get().equals(val)) - return; - Logger.normal(this, "Changing aggressiveGCModificator to "+val); - aggressiveGCModificator = val; - } - },false); - aggressiveGCModificator = statsConfig.getInt("aggressiveGC"); + statsConfig.registerIgnoredOption("aggressiveGC"); myMemoryChecker = new MemoryChecker(node.getTicker(), aggressiveGCModificator); statsConfig.register("memoryChecker", true, sortOrder++, true, false, "NodeStat.memCheck", "NodeStat.memCheckLong",