diff --git a/src/main/java/org/elasticsearch/search/aggregations/bucket/BytesRefHash.java b/src/main/java/org/elasticsearch/search/aggregations/bucket/BytesRefHash.java
index 381088f5b55..baa51b426de 100644
--- a/src/main/java/org/elasticsearch/search/aggregations/bucket/BytesRefHash.java
+++ b/src/main/java/org/elasticsearch/search/aggregations/bucket/BytesRefHash.java
@@ -60,6 +60,7 @@ public final class BytesRefHash extends AbstractHash {
/**
* Return the key at 0 <e; index <e; capacity()
. The result is undefined if the slot is unused.
+ *
Beware that the content of the {@link BytesRef} may become invalid as soon as {@link #release()} is called
*/ public BytesRef get(long id, BytesRef dest) { final long startOffset = startOffsets.get(id); diff --git a/src/main/java/org/elasticsearch/search/aggregations/bucket/terms/StringTerms.java b/src/main/java/org/elasticsearch/search/aggregations/bucket/terms/StringTerms.java index b130e263a6a..668d8c3389c 100644 --- a/src/main/java/org/elasticsearch/search/aggregations/bucket/terms/StringTerms.java +++ b/src/main/java/org/elasticsearch/search/aggregations/bucket/terms/StringTerms.java @@ -57,7 +57,7 @@ public class StringTerms extends InternalTerms { public static class Bucket extends InternalTerms.Bucket { - final BytesRef termBytes; + BytesRef termBytes; public Bucket(BytesRef term, long docCount, InternalAggregations aggregations) { super(docCount, aggregations); diff --git a/src/main/java/org/elasticsearch/search/aggregations/bucket/terms/StringTermsAggregator.java b/src/main/java/org/elasticsearch/search/aggregations/bucket/terms/StringTermsAggregator.java index 7ef4626b4ac..7d54338a31a 100644 --- a/src/main/java/org/elasticsearch/search/aggregations/bucket/terms/StringTermsAggregator.java +++ b/src/main/java/org/elasticsearch/search/aggregations/bucket/terms/StringTermsAggregator.java @@ -234,6 +234,8 @@ public class StringTermsAggregator extends BucketsAggregator { final InternalTerms.Bucket[] list = new InternalTerms.Bucket[ordered.size()]; for (int i = ordered.size() - 1; i >= 0; --i) { final StringTerms.Bucket bucket = (StringTerms.Bucket) ordered.pop(); + // the terms are owned by the BytesRefHash, we need to pull a copy since the BytesRef hash data may be recycled at some point + bucket.termBytes = BytesRef.deepCopyOf(bucket.termBytes); bucket.aggregations = bucketAggregations(bucket.bucketOrd); list[i] = bucket; } diff --git a/src/test/java/org/elasticsearch/cache/recycler/MockPageCacheRecycler.java b/src/test/java/org/elasticsearch/cache/recycler/MockPageCacheRecycler.java index 42639690a66..082be6d82b9 100644 --- a/src/test/java/org/elasticsearch/cache/recycler/MockPageCacheRecycler.java +++ b/src/test/java/org/elasticsearch/cache/recycler/MockPageCacheRecycler.java @@ -27,6 +27,7 @@ import org.elasticsearch.common.settings.Settings; import org.elasticsearch.test.TestCluster; import org.elasticsearch.threadpool.ThreadPool; +import java.lang.reflect.Array; import java.util.Random; import java.util.concurrent.ConcurrentMap; @@ -51,7 +52,7 @@ public class MockPageCacheRecycler extends PageCacheRecycler { random = new Random(seed); } - private static