diff --git a/caffeine/src/main/java/com/github/benmanes/caffeine/cache/BoundedLocalCache.java b/caffeine/src/main/java/com/github/benmanes/caffeine/cache/BoundedLocalCache.java index 1494328296..838537bdea 100644 --- a/caffeine/src/main/java/com/github/benmanes/caffeine/cache/BoundedLocalCache.java +++ b/caffeine/src/main/java/com/github/benmanes/caffeine/cache/BoundedLocalCache.java @@ -1634,7 +1634,7 @@ V putSlow(K key, V value, int newWeight, boolean notifyWriter, boolean onlyIfAbs nodeKey[0] = n.getKey(); oldValue[0] = n.getValue(); oldWeight[0] = n.getWeight(); - if ((nodeKey == null) || (oldValue[0] == null)) { + if ((nodeKey[0] == null) || (oldValue[0] == null)) { cause[0] = RemovalCause.COLLECTED; } else if (hasExpired(n, now)) { cause[0] = RemovalCause.EXPIRED; @@ -1994,7 +1994,7 @@ V doComputeIfAbsent(K key, Object keyRef, nodeKey[0] = n.getKey(); weight[0] = n.getWeight(); oldValue[0] = n.getValue(); - if ((nodeKey == null) || (oldValue[0] == null)) { + if ((nodeKey[0] == null) || (oldValue[0] == null)) { cause[0] = RemovalCause.COLLECTED; } else if (hasExpired(n, now)) { cause[0] = RemovalCause.EXPIRED; @@ -2141,7 +2141,7 @@ V remap(K key, Object keyRef, BiFunction rema synchronized (n) { nodeKey[0] = n.getKey(); oldValue[0] = n.getValue(); - if ((nodeKey == null) || (oldValue[0] == null)) { + if ((nodeKey[0] == null) || (oldValue[0] == null)) { cause[0] = RemovalCause.COLLECTED; } else if (hasExpired(n, now)) { cause[0] = RemovalCause.EXPIRED; diff --git a/caffeine/src/main/java/com/github/benmanes/caffeine/cache/CaffeineSpec.java b/caffeine/src/main/java/com/github/benmanes/caffeine/cache/CaffeineSpec.java index 7d45e72831..bd3a87310f 100644 --- a/caffeine/src/main/java/com/github/benmanes/caffeine/cache/CaffeineSpec.java +++ b/caffeine/src/main/java/com/github/benmanes/caffeine/cache/CaffeineSpec.java @@ -182,7 +182,7 @@ void configure(String key, @Nullable String value) { maximumWeight(key, value); return; case "weakKeys": - weakKeys(key, value); + weakKeys(value); return; case "weakValues": valueStrength(key, value, Strength.WEAK); @@ -200,7 +200,7 @@ void configure(String key, @Nullable String value) { refreshAfterWrite(key, value); return; case "recordStats": - recordStats(key, value); + recordStats(value); return; default: throw new IllegalArgumentException("Unknown key " + key); @@ -233,7 +233,7 @@ void maximumWeight(String key, String value) { } /** Configures the keys as weak references. */ - void weakKeys(String key, @Nullable String value) { + void weakKeys(@Nullable String value) { requireArgument(value == null, "weak keys does not take a value"); requireArgument(keyStrength == null, "weak keys was already set"); keyStrength = Strength.WEAK; @@ -268,7 +268,7 @@ void refreshAfterWrite(String key, String value) { } /** Configures the value as weak or soft references. */ - void recordStats(String key, @Nullable String value) { + void recordStats(@Nullable String value) { requireArgument(value == null, "record stats does not take a value"); requireArgument(!recordStats, "record stats was already set"); recordStats = true; diff --git a/gradle/code_quality.gradle b/gradle/code_quality.gradle index 6d32dab1f9..26d8be23c7 100644 --- a/gradle/code_quality.gradle +++ b/gradle/code_quality.gradle @@ -2,6 +2,7 @@ * Configurations for code quality analysis */ apply plugin: 'org.kordamp.gradle.stats' +apply plugin: 'one.util.huntbugs' apply plugin: 'checkstyle' apply plugin: 'findbugs' apply plugin: 'jacoco' @@ -32,6 +33,12 @@ checkstyle { config = resources.text.fromArchiveEntry(configurations.checkstyleConfig, 'google_checks.xml') } +huntbugs { + classSimpleFilter { classname -> + !classname.contains('Header') && !classname.contains('Mpsc') && !classname.contains('Factory') + } +} + findbugs { effort = 'max' excludeFilter = file("${rootDir}/config/findbugs/exclude.xml") diff --git a/gradle/dependencies.gradle b/gradle/dependencies.gradle index 49a543daff..215f30e008 100644 --- a/gradle/dependencies.gradle +++ b/gradle/dependencies.gradle @@ -73,6 +73,8 @@ ext { coveralls: '2.6.3', extra_conf: '3.1.0', error_prone: '0.0.8', + huntbugs_core: '0.0.11', + huntbugs_plugin: '0.3.5', jmh: '0.3.0', nexus: '2.3.1', pmd: '5.5.1', @@ -164,6 +166,10 @@ ext { coveralls: "org.kt3k.gradle.plugin:coveralls-gradle-plugin:${plugin_versions.coveralls}", extra_conf: "com.netflix.nebula:gradle-extra-configurations-plugin:${plugin_versions.extra_conf}", error_prone: "net.ltgt.gradle:gradle-errorprone-plugin:${plugin_versions.error_prone}", + huntbugs: [ + "one.util:huntbugs:${plugin_versions.huntbugs_core}", + "gradle.plugin.one.util.huntbugs:huntbugs-gradle-plugin:${plugin_versions.huntbugs_plugin}", + ], jmh: "gradle.plugin.me.champeau.gradle:jmh-gradle-plugin:${plugin_versions.jmh}", nexus: "com.bmuschko:gradle-nexus-plugin:${plugin_versions.nexus}", semantic_versioning: "io.ehdev:gradle-semantic-versioning:${plugin_versions.semantic_versioning}", diff --git a/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/admission/table/RandomRemovalFrequencyTable.java b/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/admission/table/RandomRemovalFrequencyTable.java index 1332bb7fe8..f8605c3568 100644 --- a/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/admission/table/RandomRemovalFrequencyTable.java +++ b/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/admission/table/RandomRemovalFrequencyTable.java @@ -81,7 +81,7 @@ public void increment(long e) { // just a model. if (currSum == maxSum) { List array = new ArrayList<>(table.keySet()); - long itemToRemove = array.get(random.nextInt(array.size())); + Long itemToRemove = array.get(random.nextInt(array.size())); value = table.remove(itemToRemove); if (value > 1) { diff --git a/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/admission/tinycache/HashFunctionParser.java b/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/admission/tinycache/HashFunctionParser.java index cf4951a4a8..918e88d337 100644 --- a/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/admission/tinycache/HashFunctionParser.java +++ b/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/admission/tinycache/HashFunctionParser.java @@ -50,7 +50,7 @@ public HashedItem createHash(long item) { h ^= item; h *= m; - fpaux.fingerprint = (byte) (h & fpMask); + fpaux.fingerprint = (byte) h; // the next line is a dirty fix as I do not want the value of 0 as a fingerprint. // It can be eliminated if we want very short fingerprints. fpaux.fingerprint = (fpaux.fingerprint == 0L) ? 1 : fpaux.fingerprint; diff --git a/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/admission/tinycache/TinyCacheAdapter.java b/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/admission/tinycache/TinyCacheAdapter.java index ab5d343d69..d55ae61637 100644 --- a/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/admission/tinycache/TinyCacheAdapter.java +++ b/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/admission/tinycache/TinyCacheAdapter.java @@ -27,8 +27,6 @@ public final class TinyCacheAdapter implements Frequency { // the actual data structure. TinyCacheSketch tcs; - // number of (independent sets) - int nrSets; // size between cache and sample. static final int sampleFactor = 10; // max frequency estimation of an item. @@ -39,7 +37,7 @@ public final class TinyCacheAdapter implements Frequency { */ public TinyCacheAdapter(Config config) { BasicSettings settings = new BasicSettings(config); - nrSets = sampleFactor * settings.maximumSize() / 64; + int nrSets = sampleFactor * settings.maximumSize() / 64; // number of (independent sets) tcs = new TinyCacheSketch(nrSets, 64,settings.randomSeed()); } diff --git a/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/admission/tinycache/TinyCacheWithGhostCache.java b/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/admission/tinycache/TinyCacheWithGhostCache.java index 599b49e2b0..497b91b8f1 100644 --- a/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/admission/tinycache/TinyCacheWithGhostCache.java +++ b/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/admission/tinycache/TinyCacheWithGhostCache.java @@ -26,13 +26,14 @@ */ @SuppressWarnings("PMD.AvoidDollarSigns") public final class TinyCacheWithGhostCache { + private static final int sampleSize = 10; + public final long[] chainIndex; public final long[] isLastIndex; private final HashFunctionParser hashFunc; private final int itemsPerSet; private final long[] cache; private final Random rnd; - private final int sampleSize; private final TinyCacheSketch ghostCache; public TinyCacheWithGhostCache(int nrSets, int itemsPerSet, int randomSeed) { @@ -41,7 +42,6 @@ public TinyCacheWithGhostCache(int nrSets, int itemsPerSet, int randomSeed) { hashFunc = new HashFunctionParser(nrSets); this.itemsPerSet = itemsPerSet; cache = new long[nrSets * itemsPerSet]; - sampleSize = 10; ghostCache = new TinyCacheSketch(nrSets * sampleSize, itemsPerSet, randomSeed + 1); rnd = new Random(randomSeed); } diff --git a/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/policy/linked/MultiQueuePolicy.java b/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/policy/linked/MultiQueuePolicy.java index 4c6e3ced6a..86ca2995a1 100644 --- a/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/policy/linked/MultiQueuePolicy.java +++ b/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/policy/linked/MultiQueuePolicy.java @@ -138,6 +138,10 @@ private void evict() { break; } } + if (victim == null) { + return; + } + victim.remove(); data.remove(victim.key); out.put(victim.key, victim);