lucene-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jpou...@apache.org
Subject [2/2] lucene-solr:master: LUCENE-8165: Ban copyOf and copyOfRange.
Date Thu, 07 Jun 2018 08:08:37 GMT
LUCENE-8165: Ban copyOf and copyOfRange.

These methods are lenient with out-of-bounds indices.

Signed-off-by: Adrien Grand <jpountz@gmail.com>


Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/8a6f1bf5
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/8a6f1bf5
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/8a6f1bf5

Branch: refs/heads/master
Commit: 8a6f1bf5ada407ce75ce7b12a88e8a681d529825
Parents: f8131e4
Author: Nhat Nguyen <nhat.nguyen@elastic.co>
Authored: Thu Jun 7 09:33:44 2018 +0200
Committer: Adrien Grand <jpountz@gmail.com>
Committed: Thu Jun 7 10:08:21 2018 +0200

----------------------------------------------------------------------
 .../lucene/analysis/hunspell/Dictionary.java    |   8 +-
 .../miscellaneous/WordDelimiterFilter.java      |   7 +-
 .../lucene/analysis/synonym/SynonymFilter.java  |   4 +-
 .../analysis/synonym/WordnetSynonymParser.java  |   7 +-
 .../analysis/ngram/NGramTokenizerTest.java      |   3 +-
 .../codecs/blockterms/BlockTermsWriter.java     |  10 +-
 .../codecs/simpletext/SimpleTextBKDWriter.java  |  10 +-
 .../simpletext/SimpleTextSegmentInfoFormat.java |   3 +-
 .../CompressingStoredFieldsIndexReader.java     |  25 ++-
 .../CompressingStoredFieldsWriter.java          |   5 +-
 .../CompressingTermVectorsWriter.java           |   8 +-
 .../lucene/index/SortedSetDocValuesWriter.java  |   2 +-
 .../apache/lucene/index/SortingLeafReader.java  |   6 +-
 .../apache/lucene/search/BlendedTermQuery.java  |   8 +-
 .../apache/lucene/search/CachingCollector.java  |   9 +-
 .../org/apache/lucene/search/MaxScoreCache.java |   2 +-
 .../org/apache/lucene/search/PhraseQuery.java   |   2 +-
 .../apache/lucene/search/PointInSetQuery.java   |   2 +-
 .../apache/lucene/search/PointRangeQuery.java   |   5 +-
 .../apache/lucene/search/spans/SpanWeight.java  |   4 +-
 .../java/org/apache/lucene/util/ArrayUtil.java  | 200 ++++++++++++++++++-
 .../java/org/apache/lucene/util/BytesRef.java   |   9 +-
 .../org/apache/lucene/util/BytesRefBuilder.java |   4 +-
 .../java/org/apache/lucene/util/CharsRef.java   |   3 +-
 .../org/apache/lucene/util/CharsRefBuilder.java |   4 +-
 .../org/apache/lucene/util/DocIdSetBuilder.java |   5 +-
 .../java/org/apache/lucene/util/IntsRef.java    |   4 +-
 .../java/org/apache/lucene/util/LongsRef.java   |   4 +-
 .../java/org/apache/lucene/util/PagedBytes.java |   7 +-
 .../org/apache/lucene/util/RoaringDocIdSet.java |   3 +-
 .../apache/lucene/util/SparseFixedBitSet.java   |   3 +-
 .../org/apache/lucene/util/StringHelper.java    |   2 +-
 .../automaton/DaciukMihovAutomatonBuilder.java  |   4 +-
 .../org/apache/lucene/util/bkd/BKDWriter.java   |  10 +-
 .../apache/lucene/util/bkd/HeapPointWriter.java |   7 +-
 .../util/packed/DeltaPackedLongValues.java      |   9 +-
 .../lucene/util/packed/MonotonicLongValues.java |  11 +-
 .../lucene/util/packed/PackedLongValues.java    |   6 +-
 .../lucene/analysis/TestCharacterUtils.java     |   4 +-
 .../AbstractTestCompressionMode.java            |  11 +-
 .../lucene/codecs/lucene50/TestForUtil.java     |  14 +-
 .../lucene/index/TestPerSegmentDeletes.java     |   3 +-
 .../org/apache/lucene/search/TestBoolean2.java  |   4 +-
 .../lucene/search/TestDoubleValuesSource.java   |   3 +-
 .../lucene/search/TestLongValuesSource.java     |   3 +-
 .../apache/lucene/search/TestPhraseQuery.java   |   3 +-
 .../TestSimpleExplanationsWithFillerDocs.java   |   5 +-
 .../apache/lucene/util/BaseSortTestCase.java    |   4 +-
 .../lucene/util/StressRamUsageEstimator.java    |   5 +-
 .../org/apache/lucene/util/TestArrayUtil.java   |  87 ++++++++
 .../org/apache/lucene/util/TestBytesRef.java    |   8 +
 .../org/apache/lucene/util/TestCharsRef.java    |   8 +
 .../org/apache/lucene/util/TestIntsRef.java     |   8 +
 .../apache/lucene/util/TestLSBRadixSorter.java  |   4 +-
 .../org/apache/lucene/util/TestLongsRef.java    |  47 +++++
 .../apache/lucene/util/TestMSBRadixSorter.java  |   4 +-
 .../lucene/util/TestStringMSBRadixSorter.java   |   4 +-
 .../lucene/util/packed/TestPackedInts.java      |   5 +-
 .../lucene/expressions/TestExpressionSorts.java |   3 +-
 .../lucene/search/intervals/IntervalQuery.java  |   4 +-
 .../lucene/document/TestHalfFloatPoint.java     |   2 +-
 .../spatial/prefix/tree/QuadPrefixTree.java     |   4 +-
 .../lucene/spatial/DistanceStrategyTest.java    |   4 +-
 .../suggest/document/TestContextQuery.java      |   3 +-
 .../index/BaseStoredFieldsFormatTestCase.java   |   2 +-
 .../lucene/search/BlockScoreQueryWrapper.java   |  10 +-
 .../util/automaton/AutomatonTestUtil.java       |   4 +-
 lucene/tools/forbiddenApis/lucene.txt           |  24 +++
 68 files changed, 517 insertions(+), 202 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8a6f1bf5/lucene/analysis/common/src/java/org/apache/lucene/analysis/hunspell/Dictionary.java
----------------------------------------------------------------------
diff --git a/lucene/analysis/common/src/java/org/apache/lucene/analysis/hunspell/Dictionary.java b/lucene/analysis/common/src/java/org/apache/lucene/analysis/hunspell/Dictionary.java
index 7885daa..f42aac3 100644
--- a/lucene/analysis/common/src/java/org/apache/lucene/analysis/hunspell/Dictionary.java
+++ b/lucene/analysis/common/src/java/org/apache/lucene/analysis/hunspell/Dictionary.java
@@ -62,7 +62,6 @@ import org.apache.lucene.util.IntsRefBuilder;
 import org.apache.lucene.util.OfflineSorter.ByteSequencesReader;
 import org.apache.lucene.util.OfflineSorter.ByteSequencesWriter;
 import org.apache.lucene.util.OfflineSorter;
-import org.apache.lucene.util.RamUsageEstimator;
 import org.apache.lucene.util.automaton.CharacterRunAutomaton;
 import org.apache.lucene.util.automaton.RegExp;
 import org.apache.lucene.util.fst.Builder;
@@ -927,10 +926,7 @@ public class Dictionary {
         if (hasStemExceptions && end+1 < line.length()) {
           String stemException = parseStemException(line.substring(end+1));
           if (stemException != null) {
-            if (stemExceptionCount == stemExceptions.length) {
-              int newSize = ArrayUtil.oversize(stemExceptionCount+1, RamUsageEstimator.NUM_BYTES_OBJECT_REF);
-              stemExceptions = Arrays.copyOf(stemExceptions, newSize);
-            }
+            stemExceptions = ArrayUtil.grow(stemExceptions, stemExceptionCount+1);
             stemExceptionID = stemExceptionCount+1; // we use '0' to indicate no exception for the form
             stemExceptions[stemExceptionCount++] = stemException;
           }
@@ -1125,7 +1121,7 @@ public class Dictionary {
       }
 
       if (upto < flags.length) {
-        flags = Arrays.copyOf(flags, upto);
+        flags = ArrayUtil.copyOfSubArray(flags, 0, upto);
       }
       return flags;
     }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8a6f1bf5/lucene/analysis/common/src/java/org/apache/lucene/analysis/miscellaneous/WordDelimiterFilter.java
----------------------------------------------------------------------
diff --git a/lucene/analysis/common/src/java/org/apache/lucene/analysis/miscellaneous/WordDelimiterFilter.java b/lucene/analysis/common/src/java/org/apache/lucene/analysis/miscellaneous/WordDelimiterFilter.java
index 16edb3d..4124e84 100644
--- a/lucene/analysis/common/src/java/org/apache/lucene/analysis/miscellaneous/WordDelimiterFilter.java
+++ b/lucene/analysis/common/src/java/org/apache/lucene/analysis/miscellaneous/WordDelimiterFilter.java
@@ -17,7 +17,6 @@
 package org.apache.lucene.analysis.miscellaneous;
 
 import java.io.IOException;
-import java.util.Arrays;
 
 import org.apache.lucene.analysis.CharArraySet;
 import org.apache.lucene.analysis.TokenFilter;
@@ -427,9 +426,9 @@ public final class WordDelimiterFilter extends TokenFilter {
   private void buffer() {
     if (bufferedLen == buffered.length) {
       int newSize = ArrayUtil.oversize(bufferedLen+1, 8);
-      buffered = Arrays.copyOf(buffered, newSize);
-      startOff = Arrays.copyOf(startOff, newSize);
-      posInc = Arrays.copyOf(posInc, newSize);
+      buffered = ArrayUtil.growExact(buffered, newSize);
+      startOff = ArrayUtil.growExact(startOff, newSize);
+      posInc = ArrayUtil.growExact(posInc, newSize);
     }
     startOff[bufferedLen] = offsetAttribute.startOffset();
     posInc[bufferedLen] = posIncAttribute.getPositionIncrement();

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8a6f1bf5/lucene/analysis/common/src/java/org/apache/lucene/analysis/synonym/SynonymFilter.java
----------------------------------------------------------------------
diff --git a/lucene/analysis/common/src/java/org/apache/lucene/analysis/synonym/SynonymFilter.java b/lucene/analysis/common/src/java/org/apache/lucene/analysis/synonym/SynonymFilter.java
index ec2676f..a51edb5 100644
--- a/lucene/analysis/common/src/java/org/apache/lucene/analysis/synonym/SynonymFilter.java
+++ b/lucene/analysis/common/src/java/org/apache/lucene/analysis/synonym/SynonymFilter.java
@@ -17,7 +17,6 @@
 package org.apache.lucene.analysis.synonym;
 
 import java.io.IOException;
-import java.util.Arrays;
 
 import org.apache.lucene.analysis.TokenFilter;
 import org.apache.lucene.analysis.TokenStream;
@@ -33,7 +32,6 @@ import org.apache.lucene.util.AttributeSource;
 import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.CharsRef;
 import org.apache.lucene.util.CharsRefBuilder;
-import org.apache.lucene.util.RamUsageEstimator;
 import org.apache.lucene.util.fst.FST;
 
 /**
@@ -206,7 +204,7 @@ public final class SynonymFilter extends TokenFilter {
 
     public void add(char[] output, int offset, int len, int endOffset, int posLength) {
       if (count == outputs.length) {
-        outputs = Arrays.copyOf(outputs, ArrayUtil.oversize(1+count, RamUsageEstimator.NUM_BYTES_OBJECT_REF));
+        outputs = ArrayUtil.grow(outputs, count+1);
       }
       if (count == endOffsets.length) {
         final int[] next = new int[ArrayUtil.oversize(1+count, Integer.BYTES)];

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8a6f1bf5/lucene/analysis/common/src/java/org/apache/lucene/analysis/synonym/WordnetSynonymParser.java
----------------------------------------------------------------------
diff --git a/lucene/analysis/common/src/java/org/apache/lucene/analysis/synonym/WordnetSynonymParser.java b/lucene/analysis/common/src/java/org/apache/lucene/analysis/synonym/WordnetSynonymParser.java
index b74e371..a4183d7 100644
--- a/lucene/analysis/common/src/java/org/apache/lucene/analysis/synonym/WordnetSynonymParser.java
+++ b/lucene/analysis/common/src/java/org/apache/lucene/analysis/synonym/WordnetSynonymParser.java
@@ -21,9 +21,9 @@ import java.io.IOException;
 import java.io.LineNumberReader;
 import java.io.Reader;
 import java.text.ParseException;
-import java.util.Arrays;
 
 import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.util.ArrayUtil;
 import org.apache.lucene.util.CharsRef;
 import org.apache.lucene.util.CharsRefBuilder;
 
@@ -59,10 +59,7 @@ public class WordnetSynonymParser extends SynonymMap.Parser {
           synsetSize = 0;
         }
 
-        if (synset.length <= synsetSize+1) {
-          synset = Arrays.copyOf(synset, synset.length * 2);
-        }
-        
+        synset = ArrayUtil.grow(synset, synsetSize + 1);
         synset[synsetSize] = parseSynonym(line, new CharsRefBuilder());
         synsetSize++;
         lastSynSetID = synSetID;

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8a6f1bf5/lucene/analysis/common/src/test/org/apache/lucene/analysis/ngram/NGramTokenizerTest.java
----------------------------------------------------------------------
diff --git a/lucene/analysis/common/src/test/org/apache/lucene/analysis/ngram/NGramTokenizerTest.java b/lucene/analysis/common/src/test/org/apache/lucene/analysis/ngram/NGramTokenizerTest.java
index 46a0c1c..cb54fa2 100644
--- a/lucene/analysis/common/src/test/org/apache/lucene/analysis/ngram/NGramTokenizerTest.java
+++ b/lucene/analysis/common/src/test/org/apache/lucene/analysis/ngram/NGramTokenizerTest.java
@@ -29,6 +29,7 @@ import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
 import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;
 import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute;
 import org.apache.lucene.analysis.tokenattributes.PositionLengthAttribute;
+import org.apache.lucene.util.ArrayUtil;
 import org.apache.lucene.util.TestUtil;
 
 import com.carrotsearch.randomizedtesting.generators.RandomStrings;
@@ -179,7 +180,7 @@ public class NGramTokenizerTest extends BaseTokenStreamTestCase {
           }
         }
         assertTrue(grams.incrementToken());
-        assertArrayEquals(Arrays.copyOfRange(codePoints, start, end), toCodePoints(termAtt));
+        assertArrayEquals(ArrayUtil.copyOfSubArray(codePoints, start, end), toCodePoints(termAtt));
         assertEquals(1, posIncAtt.getPositionIncrement());
         assertEquals(1, posLenAtt.getPositionLength());
         assertEquals(offsets[start], offsetAtt.startOffset());

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8a6f1bf5/lucene/codecs/src/java/org/apache/lucene/codecs/blockterms/BlockTermsWriter.java
----------------------------------------------------------------------
diff --git a/lucene/codecs/src/java/org/apache/lucene/codecs/blockterms/BlockTermsWriter.java b/lucene/codecs/src/java/org/apache/lucene/codecs/blockterms/BlockTermsWriter.java
index 9ed87b5..9de9d73 100644
--- a/lucene/codecs/src/java/org/apache/lucene/codecs/blockterms/BlockTermsWriter.java
+++ b/lucene/codecs/src/java/org/apache/lucene/codecs/blockterms/BlockTermsWriter.java
@@ -20,7 +20,6 @@ package org.apache.lucene.codecs.blockterms;
 import java.io.Closeable;
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
 
 import org.apache.lucene.codecs.BlockTermState;
@@ -44,7 +43,6 @@ import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.BytesRefBuilder;
 import org.apache.lucene.util.FixedBitSet;
 import org.apache.lucene.util.IOUtils;
-import org.apache.lucene.util.RamUsageEstimator;
 
 // TODO: currently we encode all terms between two indexed
 // terms as a block; but, we could decouple the two, ie
@@ -260,11 +258,9 @@ public class BlockTermsWriter extends FieldsConsumer implements Closeable {
         //System.out.println("  index term!");
       }
 
-      if (pendingTerms.length == pendingCount) {
-        pendingTerms = Arrays.copyOf(pendingTerms, ArrayUtil.oversize(pendingCount+1, RamUsageEstimator.NUM_BYTES_OBJECT_REF));
-        for(int i=pendingCount;i<pendingTerms.length;i++) {
-          pendingTerms[i] = new TermEntry();
-        }
+      pendingTerms = ArrayUtil.grow(pendingTerms, pendingCount + 1);
+      for (int i = pendingCount; i < pendingTerms.length; i++) {
+        pendingTerms[i] = new TermEntry();
       }
       final TermEntry te = pendingTerms[pendingCount];
       te.term.copyBytes(text);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8a6f1bf5/lucene/codecs/src/java/org/apache/lucene/codecs/simpletext/SimpleTextBKDWriter.java
----------------------------------------------------------------------
diff --git a/lucene/codecs/src/java/org/apache/lucene/codecs/simpletext/SimpleTextBKDWriter.java b/lucene/codecs/src/java/org/apache/lucene/codecs/simpletext/SimpleTextBKDWriter.java
index 034202b..cd74aca 100644
--- a/lucene/codecs/src/java/org/apache/lucene/codecs/simpletext/SimpleTextBKDWriter.java
+++ b/lucene/codecs/src/java/org/apache/lucene/codecs/simpletext/SimpleTextBKDWriter.java
@@ -505,7 +505,7 @@ final class SimpleTextBKDWriter implements Closeable {
 
       if (leafBlockFPs.size() > 0) {
         // Save the first (minimum) value in each leaf block except the first, to build the split value index in the end:
-        leafBlockStartValues.add(Arrays.copyOf(leafValues, packedBytesLength));
+        leafBlockStartValues.add(ArrayUtil.copyOfSubArray(leafValues, 0, packedBytesLength));
       }
       leafBlockFPs.add(out.getFilePointer());
       checkMaxLeafNodeCount(leafBlockFPs.size());
@@ -539,8 +539,8 @@ final class SimpleTextBKDWriter implements Closeable {
           return scratch;
         }
       };
-      assert valuesInOrderAndBounds(leafCount, 0, Arrays.copyOf(leafValues, packedBytesLength),
-          Arrays.copyOfRange(leafValues, (leafCount - 1) * packedBytesLength, leafCount * packedBytesLength),
+      assert valuesInOrderAndBounds(leafCount, 0, ArrayUtil.copyOfSubArray(leafValues, 0, packedBytesLength),
+          ArrayUtil.copyOfSubArray(leafValues, (leafCount - 1) * packedBytesLength, leafCount * packedBytesLength),
           packedValues, leafDocs, 0);
       writeLeafBlockPackedValues(out, commonPrefixLengths, leafCount, 0, packedValues);
     }
@@ -1206,8 +1206,8 @@ final class SimpleTextBKDWriter implements Closeable {
       reader.getValue(mid, scratchBytesRef1);
       System.arraycopy(scratchBytesRef1.bytes, scratchBytesRef1.offset + splitDim * bytesPerDim, splitPackedValues, address + 1, bytesPerDim);
 
-      byte[] minSplitPackedValue = Arrays.copyOf(minPackedValue, packedBytesLength);
-      byte[] maxSplitPackedValue = Arrays.copyOf(maxPackedValue, packedBytesLength);
+      byte[] minSplitPackedValue = ArrayUtil.copyOfSubArray(minPackedValue, 0, packedBytesLength);
+      byte[] maxSplitPackedValue = ArrayUtil.copyOfSubArray(maxPackedValue, 0, packedBytesLength);
       System.arraycopy(scratchBytesRef1.bytes, scratchBytesRef1.offset + splitDim * bytesPerDim,
           minSplitPackedValue, splitDim * bytesPerDim, bytesPerDim);
       System.arraycopy(scratchBytesRef1.bytes, scratchBytesRef1.offset + splitDim * bytesPerDim,

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8a6f1bf5/lucene/codecs/src/java/org/apache/lucene/codecs/simpletext/SimpleTextSegmentInfoFormat.java
----------------------------------------------------------------------
diff --git a/lucene/codecs/src/java/org/apache/lucene/codecs/simpletext/SimpleTextSegmentInfoFormat.java b/lucene/codecs/src/java/org/apache/lucene/codecs/simpletext/SimpleTextSegmentInfoFormat.java
index 8a71c6d..6d5bfe4 100644
--- a/lucene/codecs/src/java/org/apache/lucene/codecs/simpletext/SimpleTextSegmentInfoFormat.java
+++ b/lucene/codecs/src/java/org/apache/lucene/codecs/simpletext/SimpleTextSegmentInfoFormat.java
@@ -42,6 +42,7 @@ import org.apache.lucene.store.Directory;
 import org.apache.lucene.store.IOContext;
 import org.apache.lucene.store.IndexInput;
 import org.apache.lucene.store.IndexOutput;
+import org.apache.lucene.util.ArrayUtil;
 import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.BytesRefBuilder;
 import org.apache.lucene.util.StringHelper;
@@ -158,7 +159,7 @@ public class SimpleTextSegmentInfoFormat extends SegmentInfoFormat {
       
       SimpleTextUtil.readLine(input, scratch);
       assert StringHelper.startsWith(scratch.get(), SI_ID);
-      final byte[] id = Arrays.copyOfRange(scratch.bytes(), SI_ID.length, scratch.length());
+      final byte[] id = ArrayUtil.copyOfSubArray(scratch.bytes(), SI_ID.length, scratch.length());
       
       if (!Arrays.equals(segmentID, id)) {
         throw new CorruptIndexException("file mismatch, expected: " + StringHelper.idToString(segmentID)

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8a6f1bf5/lucene/core/src/java/org/apache/lucene/codecs/compressing/CompressingStoredFieldsIndexReader.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/codecs/compressing/CompressingStoredFieldsIndexReader.java b/lucene/core/src/java/org/apache/lucene/codecs/compressing/CompressingStoredFieldsIndexReader.java
index 0685d79..61410b6 100644
--- a/lucene/core/src/java/org/apache/lucene/codecs/compressing/CompressingStoredFieldsIndexReader.java
+++ b/lucene/core/src/java/org/apache/lucene/codecs/compressing/CompressingStoredFieldsIndexReader.java
@@ -21,7 +21,6 @@ import static org.apache.lucene.util.BitUtil.zigZagDecode;
 
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
@@ -73,12 +72,12 @@ public final class CompressingStoredFieldsIndexReader implements Cloneable, Acco
       }
       if (blockCount == docBases.length) {
         final int newSize = ArrayUtil.oversize(blockCount + 1, 8);
-        docBases = Arrays.copyOf(docBases, newSize);
-        startPointers = Arrays.copyOf(startPointers, newSize);
-        avgChunkDocs = Arrays.copyOf(avgChunkDocs, newSize);
-        avgChunkSizes = Arrays.copyOf(avgChunkSizes, newSize);
-        docBasesDeltas = Arrays.copyOf(docBasesDeltas, newSize);
-        startPointersDeltas = Arrays.copyOf(startPointersDeltas, newSize);
+        docBases = ArrayUtil.growExact(docBases, newSize);
+        startPointers = ArrayUtil.growExact(startPointers, newSize);
+        avgChunkDocs = ArrayUtil.growExact(avgChunkDocs, newSize);
+        avgChunkSizes = ArrayUtil.growExact(avgChunkSizes, newSize);
+        docBasesDeltas = ArrayUtil.growExact(docBasesDeltas, newSize);
+        startPointersDeltas = ArrayUtil.growExact(startPointersDeltas, newSize);
       }
 
       // doc bases
@@ -102,12 +101,12 @@ public final class CompressingStoredFieldsIndexReader implements Cloneable, Acco
       ++blockCount;
     }
 
-    this.docBases = Arrays.copyOf(docBases, blockCount);
-    this.startPointers = Arrays.copyOf(startPointers, blockCount);
-    this.avgChunkDocs = Arrays.copyOf(avgChunkDocs, blockCount);
-    this.avgChunkSizes = Arrays.copyOf(avgChunkSizes, blockCount);
-    this.docBasesDeltas = Arrays.copyOf(docBasesDeltas, blockCount);
-    this.startPointersDeltas = Arrays.copyOf(startPointersDeltas, blockCount);
+    this.docBases = ArrayUtil.copyOfSubArray(docBases, 0, blockCount);
+    this.startPointers = ArrayUtil.copyOfSubArray(startPointers, 0, blockCount);
+    this.avgChunkDocs = ArrayUtil.copyOfSubArray(avgChunkDocs, 0, blockCount);
+    this.avgChunkSizes = ArrayUtil.copyOfSubArray(avgChunkSizes, 0, blockCount);
+    this.docBasesDeltas = ArrayUtil.copyOfSubArray(docBasesDeltas, 0, blockCount);
+    this.startPointersDeltas = ArrayUtil.copyOfSubArray(startPointersDeltas, 0, blockCount);
   }
 
   private int block(int docID) {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8a6f1bf5/lucene/core/src/java/org/apache/lucene/codecs/compressing/CompressingStoredFieldsWriter.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/codecs/compressing/CompressingStoredFieldsWriter.java b/lucene/core/src/java/org/apache/lucene/codecs/compressing/CompressingStoredFieldsWriter.java
index 8cd8ccb..5b8eb9e 100644
--- a/lucene/core/src/java/org/apache/lucene/codecs/compressing/CompressingStoredFieldsWriter.java
+++ b/lucene/core/src/java/org/apache/lucene/codecs/compressing/CompressingStoredFieldsWriter.java
@@ -19,7 +19,6 @@ package org.apache.lucene.codecs.compressing;
 
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
 
 import org.apache.lucene.codecs.CodecUtil;
@@ -158,8 +157,8 @@ public final class CompressingStoredFieldsWriter extends StoredFieldsWriter {
   public void finishDocument() throws IOException {
     if (numBufferedDocs == this.numStoredFields.length) {
       final int newLength = ArrayUtil.oversize(numBufferedDocs + 1, 4);
-      this.numStoredFields = Arrays.copyOf(this.numStoredFields, newLength);
-      endOffsets = Arrays.copyOf(endOffsets, newLength);
+      this.numStoredFields = ArrayUtil.growExact(this.numStoredFields, newLength);
+      endOffsets = ArrayUtil.growExact(endOffsets, newLength);
     }
     this.numStoredFields[numBufferedDocs] = numStoredFieldsInDoc;
     numStoredFieldsInDoc = 0;

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8a6f1bf5/lucene/core/src/java/org/apache/lucene/codecs/compressing/CompressingTermVectorsWriter.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/codecs/compressing/CompressingTermVectorsWriter.java b/lucene/core/src/java/org/apache/lucene/codecs/compressing/CompressingTermVectorsWriter.java
index ee948c3..4f8d004 100644
--- a/lucene/core/src/java/org/apache/lucene/codecs/compressing/CompressingTermVectorsWriter.java
+++ b/lucene/core/src/java/org/apache/lucene/codecs/compressing/CompressingTermVectorsWriter.java
@@ -176,8 +176,8 @@ public final class CompressingTermVectorsWriter extends TermVectorsWriter {
       if (hasOffsets) {
         if (offStart + totalPositions == startOffsetsBuf.length) {
           final int newLength = ArrayUtil.oversize(offStart + totalPositions, 4);
-          startOffsetsBuf = Arrays.copyOf(startOffsetsBuf, newLength);
-          lengthsBuf = Arrays.copyOf(lengthsBuf, newLength);
+          startOffsetsBuf = ArrayUtil.growExact(startOffsetsBuf, newLength);
+          lengthsBuf = ArrayUtil.growExact(lengthsBuf, newLength);
         }
         startOffsetsBuf[offStart + totalPositions] = startOffset;
         lengthsBuf[offStart + totalPositions] = length;
@@ -705,8 +705,8 @@ public final class CompressingTermVectorsWriter extends TermVectorsWriter {
       final int offStart = curField.offStart + curField.totalPositions;
       if (offStart + numProx > startOffsetsBuf.length) {
         final int newLength = ArrayUtil.oversize(offStart + numProx, 4);
-        startOffsetsBuf = Arrays.copyOf(startOffsetsBuf, newLength);
-        lengthsBuf = Arrays.copyOf(lengthsBuf, newLength);
+        startOffsetsBuf = ArrayUtil.growExact(startOffsetsBuf, newLength);
+        lengthsBuf = ArrayUtil.growExact(lengthsBuf, newLength);
       }
       int lastOffset = 0, startOffset, endOffset;
       for (int i = 0; i < numProx; ++i) {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8a6f1bf5/lucene/core/src/java/org/apache/lucene/index/SortedSetDocValuesWriter.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/index/SortedSetDocValuesWriter.java b/lucene/core/src/java/org/apache/lucene/index/SortedSetDocValuesWriter.java
index 700090a..71a14a5 100644
--- a/lucene/core/src/java/org/apache/lucene/index/SortedSetDocValuesWriter.java
+++ b/lucene/core/src/java/org/apache/lucene/index/SortedSetDocValuesWriter.java
@@ -164,7 +164,7 @@ class SortedSetDocValuesWriter extends DocValuesWriter {
         }
         docOrds[upto++] = ord;
       }
-      ords[newDocID] = Arrays.copyOfRange(docOrds, 0, upto);
+      ords[newDocID] = ArrayUtil.copyOfSubArray(docOrds, 0, upto);
     }
     return ords;
   }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8a6f1bf5/lucene/core/src/java/org/apache/lucene/index/SortingLeafReader.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/index/SortingLeafReader.java b/lucene/core/src/java/org/apache/lucene/index/SortingLeafReader.java
index eb9f7ed..55e4d20 100644
--- a/lucene/core/src/java/org/apache/lucene/index/SortingLeafReader.java
+++ b/lucene/core/src/java/org/apache/lucene/index/SortingLeafReader.java
@@ -890,8 +890,8 @@ class SortingLeafReader extends FilterLeafReader {
       while ((doc = in.nextDoc()) != DocIdSetIterator.NO_MORE_DOCS) {
         if (i == docs.length) {
           final int newLength = ArrayUtil.oversize(i + 1, 4);
-          docs = Arrays.copyOf(docs, newLength);
-          offsets = Arrays.copyOf(offsets, newLength);
+          docs = ArrayUtil.growExact(docs, newLength);
+          offsets = ArrayUtil.growExact(offsets, newLength);
         }
         docs[i] = docMap.oldToNew(doc);
         offsets[i] = out.getFilePointer();
@@ -1230,7 +1230,7 @@ class SortingLeafReader extends FilterLeafReader {
             }
             docOrds[upto++] = ord;
           }
-          ords[newDocID] = Arrays.copyOfRange(docOrds, 0, upto);
+          ords[newDocID] = ArrayUtil.copyOfSubArray(docOrds, 0, upto);
         }
         cachedSortedSetDVs.put(field, ords);
       }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8a6f1bf5/lucene/core/src/java/org/apache/lucene/search/BlendedTermQuery.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/BlendedTermQuery.java b/lucene/core/src/java/org/apache/lucene/search/BlendedTermQuery.java
index cca6675..8f85e25 100644
--- a/lucene/core/src/java/org/apache/lucene/search/BlendedTermQuery.java
+++ b/lucene/core/src/java/org/apache/lucene/search/BlendedTermQuery.java
@@ -102,9 +102,9 @@ public final class BlendedTermQuery extends Query {
     /** Build the {@link BlendedTermQuery}. */
     public BlendedTermQuery build() {
       return new BlendedTermQuery(
-          Arrays.copyOf(terms, numTerms),
-          Arrays.copyOf(boosts, numTerms),
-          Arrays.copyOf(contexts, numTerms),
+          ArrayUtil.copyOfSubArray(terms, 0, numTerms),
+          ArrayUtil.copyOfSubArray(boosts, 0, numTerms),
+          ArrayUtil.copyOfSubArray(contexts, 0, numTerms),
           rewriteMethod);
     }
 
@@ -263,7 +263,7 @@ public final class BlendedTermQuery extends Query {
 
   @Override
   public final Query rewrite(IndexReader reader) throws IOException {
-    final TermStates[] contexts = Arrays.copyOf(this.contexts, this.contexts.length);
+    final TermStates[] contexts = ArrayUtil.copyOfSubArray(this.contexts, 0, this.contexts.length);
     for (int i = 0; i < contexts.length; ++i) {
       if (contexts[i] == null || contexts[i].wasBuiltFor(reader.getContext()) == false) {
         contexts[i] = TermStates.build(reader.getContext(), terms[i], true);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8a6f1bf5/lucene/core/src/java/org/apache/lucene/search/CachingCollector.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/CachingCollector.java b/lucene/core/src/java/org/apache/lucene/search/CachingCollector.java
index 3bed88d..6681c59 100644
--- a/lucene/core/src/java/org/apache/lucene/search/CachingCollector.java
+++ b/lucene/core/src/java/org/apache/lucene/search/CachingCollector.java
@@ -18,7 +18,6 @@ package org.apache.lucene.search;
 
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
 
 import org.apache.lucene.index.LeafReaderContext;
@@ -213,7 +212,7 @@ public abstract class CachingCollector extends FilterCollector {
     }
 
     protected void grow(int newLen) {
-      docs = Arrays.copyOf(docs, newLen);
+      docs = ArrayUtil.growExact(docs, newLen);
     }
 
     protected void invalidate() {
@@ -250,7 +249,7 @@ public abstract class CachingCollector extends FilterCollector {
     }
 
     int[] cachedDocs() {
-      return docs == null ? null : Arrays.copyOf(docs, docCount);
+      return docs == null ? null : ArrayUtil.copyOfSubArray(docs, 0, docCount);
     }
 
   }
@@ -274,7 +273,7 @@ public abstract class CachingCollector extends FilterCollector {
     @Override
     protected void grow(int newLen) {
       super.grow(newLen);
-      scores = Arrays.copyOf(scores, newLen);
+      scores = ArrayUtil.growExact(scores, newLen);
     }
 
     @Override
@@ -290,7 +289,7 @@ public abstract class CachingCollector extends FilterCollector {
     }
 
     float[] cachedScores() {
-      return docs == null ? null : Arrays.copyOf(scores, docCount);
+      return docs == null ? null : ArrayUtil.copyOfSubArray(scores, 0, docCount);
     }
   }
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8a6f1bf5/lucene/core/src/java/org/apache/lucene/search/MaxScoreCache.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/MaxScoreCache.java b/lucene/core/src/java/org/apache/lucene/search/MaxScoreCache.java
index 17e4efc..51fee1a 100644
--- a/lucene/core/src/java/org/apache/lucene/search/MaxScoreCache.java
+++ b/lucene/core/src/java/org/apache/lucene/search/MaxScoreCache.java
@@ -53,7 +53,7 @@ final class MaxScoreCache {
     if (maxScoreCache.length < size) {
       int oldLength = maxScoreCache.length;
       maxScoreCache = ArrayUtil.grow(maxScoreCache, size);
-      maxScoreCacheUpTo = Arrays.copyOf(maxScoreCacheUpTo, maxScoreCache.length);
+      maxScoreCacheUpTo = ArrayUtil.growExact(maxScoreCacheUpTo, maxScoreCache.length);
       Arrays.fill(maxScoreCacheUpTo, oldLength, maxScoreCacheUpTo.length, -1);
     }
   }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8a6f1bf5/lucene/core/src/java/org/apache/lucene/search/PhraseQuery.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/PhraseQuery.java b/lucene/core/src/java/org/apache/lucene/search/PhraseQuery.java
index 16642e5..70d2e09 100644
--- a/lucene/core/src/java/org/apache/lucene/search/PhraseQuery.java
+++ b/lucene/core/src/java/org/apache/lucene/search/PhraseQuery.java
@@ -413,7 +413,7 @@ public class PhraseQuery extends Query {
           }
         }
         if (termUpTo > 0) {
-          return similarity.scorer(boost, searcher.collectionStatistics(field), Arrays.copyOf(termStats, termUpTo));
+          return similarity.scorer(boost, searcher.collectionStatistics(field), ArrayUtil.copyOfSubArray(termStats, 0, termUpTo));
         } else {
           return null; // no terms at all, we won't use similarity
         }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8a6f1bf5/lucene/core/src/java/org/apache/lucene/search/PointInSetQuery.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/PointInSetQuery.java b/lucene/core/src/java/org/apache/lucene/search/PointInSetQuery.java
index 689d64a..149fa20 100644
--- a/lucene/core/src/java/org/apache/lucene/search/PointInSetQuery.java
+++ b/lucene/core/src/java/org/apache/lucene/search/PointInSetQuery.java
@@ -333,7 +333,7 @@ public abstract class PointInSetQuery extends Query {
 
             upto++;
             BytesRef next = iterator.next();
-            return Arrays.copyOfRange(next.bytes, next.offset, next.length);
+            return BytesRef.deepCopyOf(next).bytes;
           }
         };
       }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8a6f1bf5/lucene/core/src/java/org/apache/lucene/search/PointRangeQuery.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/PointRangeQuery.java b/lucene/core/src/java/org/apache/lucene/search/PointRangeQuery.java
index 7e48383..3af001b 100644
--- a/lucene/core/src/java/org/apache/lucene/search/PointRangeQuery.java
+++ b/lucene/core/src/java/org/apache/lucene/search/PointRangeQuery.java
@@ -26,6 +26,7 @@ import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.PointValues;
 import org.apache.lucene.index.PointValues.IntersectVisitor;
 import org.apache.lucene.index.PointValues.Relation;
+import org.apache.lucene.util.ArrayUtil;
 import org.apache.lucene.util.BitSetIterator;
 import org.apache.lucene.util.DocIdSetBuilder;
 import org.apache.lucene.util.FixedBitSet;
@@ -392,9 +393,9 @@ public abstract class PointRangeQuery extends Query {
       int startOffset = bytesPerDim * i;
 
       sb.append('[');
-      sb.append(toString(i, Arrays.copyOfRange(lowerPoint, startOffset, startOffset + bytesPerDim)));
+      sb.append(toString(i, ArrayUtil.copyOfSubArray(lowerPoint, startOffset, startOffset + bytesPerDim)));
       sb.append(" TO ");
-      sb.append(toString(i, Arrays.copyOfRange(upperPoint, startOffset, startOffset + bytesPerDim)));
+      sb.append(toString(i, ArrayUtil.copyOfSubArray(upperPoint, startOffset, startOffset + bytesPerDim)));
       sb.append(']');
     }
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8a6f1bf5/lucene/core/src/java/org/apache/lucene/search/spans/SpanWeight.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/spans/SpanWeight.java b/lucene/core/src/java/org/apache/lucene/search/spans/SpanWeight.java
index 35c36d7..0313d56 100644
--- a/lucene/core/src/java/org/apache/lucene/search/spans/SpanWeight.java
+++ b/lucene/core/src/java/org/apache/lucene/search/spans/SpanWeight.java
@@ -18,7 +18,6 @@ package org.apache.lucene.search.spans;
 
 
 import java.io.IOException;
-import java.util.Arrays;
 import java.util.Map;
 
 import org.apache.lucene.index.LeafReaderContext;
@@ -32,6 +31,7 @@ import org.apache.lucene.search.LeafSimScorer;
 import org.apache.lucene.search.TermStatistics;
 import org.apache.lucene.search.Weight;
 import org.apache.lucene.search.similarities.Similarity;
+import org.apache.lucene.util.ArrayUtil;
 
 /**
  * Expert-only.  Public for use by other weight implementations
@@ -103,7 +103,7 @@ public abstract class SpanWeight extends Weight {
     }
     CollectionStatistics collectionStats = searcher.collectionStatistics(query.getField());
     if (termUpTo > 0) {
-      return similarity.scorer(boost, collectionStats, Arrays.copyOf(termStats, termUpTo));
+      return similarity.scorer(boost, collectionStats, ArrayUtil.copyOfSubArray(termStats, 0, termUpTo));
     } else {
       return null; // no terms at all exist, we won't use similarity
     }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8a6f1bf5/lucene/core/src/java/org/apache/lucene/util/ArrayUtil.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/util/ArrayUtil.java b/lucene/core/src/java/org/apache/lucene/util/ArrayUtil.java
index 3c5897f..f6bab10 100644
--- a/lucene/core/src/java/org/apache/lucene/util/ArrayUtil.java
+++ b/lucene/core/src/java/org/apache/lucene/util/ArrayUtil.java
@@ -16,7 +16,7 @@
  */
 package org.apache.lucene.util;
 
-import java.util.Arrays;
+import java.lang.reflect.Array;
 import java.util.Comparator;
 
 /**
@@ -211,94 +211,172 @@ public final class ArrayUtil {
     }
   }
 
+  /** Returns a new array whose size is exact the specified {@code newLength} without over-allocating */
+  public static <T> T[] growExact(T[] array, int newLength) {
+    Class<? extends Object[]> type = array.getClass();
+    @SuppressWarnings("unchecked")
+    T[] copy = (type == Object[].class)
+        ? (T[]) new Object[newLength]
+        : (T[]) Array.newInstance(type.getComponentType(), newLength);
+    System.arraycopy(array, 0, copy, 0, array.length);
+    return copy;
+  }
+
+  /** Returns an array whose size is at least {@code minSize}, generally over-allocating exponentially */
   public static <T> T[] grow(T[] array, int minSize) {
-    assert minSize >= 0: "size must be positive (got " + minSize + "): likely integer overflow?";
+    assert minSize >= 0 : "size must be positive (got " + minSize + "): likely integer overflow?";
     if (array.length < minSize) {
-      return Arrays.copyOf(array, oversize(minSize, RamUsageEstimator.NUM_BYTES_OBJECT_REF));
+      final int newLength = oversize(minSize, RamUsageEstimator.NUM_BYTES_OBJECT_REF);
+      return growExact(array, newLength);
     } else
       return array;
   }
 
+  /** Returns a new array whose size is exact the specified {@code newLength} without over-allocating */
+  public static short[] growExact(short[] array, int newLength) {
+    short[] copy = new short[newLength];
+    System.arraycopy(array, 0, copy, 0, array.length);
+    return copy;
+  }
+
+  /** Returns an array whose size is at least {@code minSize}, generally over-allocating exponentially */
   public static short[] grow(short[] array, int minSize) {
     assert minSize >= 0: "size must be positive (got " + minSize + "): likely integer overflow?";
     if (array.length < minSize) {
-      return Arrays.copyOf(array, oversize(minSize, Short.BYTES));
+      return growExact(array, oversize(minSize, Short.BYTES));
     } else
       return array;
   }
 
+  /** Returns a larger array, generally over-allocating exponentially */
   public static short[] grow(short[] array) {
     return grow(array, 1 + array.length);
   }
-  
+
+  /** Returns a new array whose size is exact the specified {@code newLength} without over-allocating */
+  public static float[] growExact(float[] array, int newLength) {
+    float[] copy = new float[newLength];
+    System.arraycopy(array, 0, copy, 0, array.length);
+    return copy;
+  }
+
+  /** Returns an array whose size is at least {@code minSize}, generally over-allocating exponentially */
   public static float[] grow(float[] array, int minSize) {
     assert minSize >= 0: "size must be positive (got " + minSize + "): likely integer overflow?";
     if (array.length < minSize) {
-      return Arrays.copyOf(array, oversize(minSize, Float.BYTES));
+      float[] copy = new float[oversize(minSize, Float.BYTES)];
+      System.arraycopy(array, 0, copy, 0, array.length);
+      return copy;
     } else
       return array;
   }
 
+  /** Returns a larger array, generally over-allocating exponentially */
   public static float[] grow(float[] array) {
     return grow(array, 1 + array.length);
   }
 
+  /** Returns a new array whose size is exact the specified {@code newLength} without over-allocating */
+  public static double[] growExact(double[] array, int newLength) {
+    double[] copy = new double[newLength];
+    System.arraycopy(array, 0, copy, 0, array.length);
+    return copy;
+  }
+
+  /** Returns an array whose size is at least {@code minSize}, generally over-allocating exponentially */
   public static double[] grow(double[] array, int minSize) {
     assert minSize >= 0: "size must be positive (got " + minSize + "): likely integer overflow?";
     if (array.length < minSize) {
-      return Arrays.copyOf(array, oversize(minSize, Double.BYTES));
+      return growExact(array, oversize(minSize, Double.BYTES));
     } else
       return array;
   }
 
+  /** Returns a larger array, generally over-allocating exponentially */
   public static double[] grow(double[] array) {
     return grow(array, 1 + array.length);
   }
 
+  /** Returns a new array whose size is exact the specified {@code newLength} without over-allocating */
+  public static int[] growExact(int[] array, int newLength) {
+    int[] copy = new int[newLength];
+    System.arraycopy(array, 0, copy, 0, array.length);
+    return copy;
+  }
+
+  /** Returns an array whose size is at least {@code minSize}, generally over-allocating exponentially */
   public static int[] grow(int[] array, int minSize) {
     assert minSize >= 0: "size must be positive (got " + minSize + "): likely integer overflow?";
     if (array.length < minSize) {
-      return Arrays.copyOf(array, oversize(minSize, Integer.BYTES));
+      return growExact(array, oversize(minSize, Integer.BYTES));
     } else
       return array;
   }
 
+  /** Returns a larger array, generally over-allocating exponentially */
   public static int[] grow(int[] array) {
     return grow(array, 1 + array.length);
   }
 
+  /** Returns a new array whose size is exact the specified {@code newLength} without over-allocating */
+  public static long[] growExact(long[] array, int newLength) {
+    long[] copy = new long[newLength];
+    System.arraycopy(array, 0, copy, 0, array.length);
+    return copy;
+  }
+
+  /** Returns an array whose size is at least {@code minSize}, generally over-allocating exponentially */
   public static long[] grow(long[] array, int minSize) {
     assert minSize >= 0: "size must be positive (got " + minSize + "): likely integer overflow?";
     if (array.length < minSize) {
-      return Arrays.copyOf(array, oversize(minSize, Long.BYTES));
+      return growExact(array, oversize(minSize, Long.BYTES));
     } else
       return array;
   }
 
+  /** Returns a larger array, generally over-allocating exponentially */
   public static long[] grow(long[] array) {
     return grow(array, 1 + array.length);
   }
 
+  /** Returns a new array whose size is exact the specified {@code newLength} without over-allocating */
+  public static byte[] growExact(byte[] array, int newLength) {
+    byte[] copy = new byte[newLength];
+    System.arraycopy(array, 0, copy, 0, array.length);
+    return copy;
+  }
+
+  /** Returns an array whose size is at least {@code minSize}, generally over-allocating exponentially */
   public static byte[] grow(byte[] array, int minSize) {
     assert minSize >= 0: "size must be positive (got " + minSize + "): likely integer overflow?";
     if (array.length < minSize) {
-      return Arrays.copyOf(array, oversize(minSize, Byte.BYTES));
+      return growExact(array, oversize(minSize, Byte.BYTES));
     } else
       return array;
   }
 
+  /** Returns a larger array, generally over-allocating exponentially */
   public static byte[] grow(byte[] array) {
     return grow(array, 1 + array.length);
   }
 
+  /** Returns a new array whose size is exact the specified {@code newLength} without over-allocating */
+  public static char[] growExact(char[] array, int newLength) {
+    char[] copy = new char[newLength];
+    System.arraycopy(array, 0, copy, 0, array.length);
+    return copy;
+  }
+
+  /** Returns an array whose size is at least {@code minSize}, generally over-allocating exponentially */
   public static char[] grow(char[] array, int minSize) {
     assert minSize >= 0: "size must be positive (got " + minSize + "): likely integer overflow?";
     if (array.length < minSize) {
-      return Arrays.copyOf(array, oversize(minSize, Character.BYTES));
+      return growExact(array, oversize(minSize, Character.BYTES));
     } else
       return array;
   }
 
+  /** Returns a larger array, generally over-allocating exponentially */
   public static char[] grow(char[] array) {
     return grow(array, 1 + array.length);
   }
@@ -429,4 +507,104 @@ public final class ArrayUtil {
     }.select(from, to, k);
   }
 
+  /**
+   * Copies the specified range of the given array into a new sub array.
+   * @param array the input array
+   * @param from  the initial index of range to be copied (inclusive)
+   * @param to    the final index of range to be copied (exclusive)
+   */
+  public static byte[] copyOfSubArray(byte[] array, int from, int to) {
+    final byte[] copy = new byte[to-from];
+    System.arraycopy(array, from, copy, 0, to-from);
+    return copy;
+  }
+
+  /**
+   * Copies the specified range of the given array into a new sub array.
+   * @param array the input array
+   * @param from  the initial index of range to be copied (inclusive)
+   * @param to    the final index of range to be copied (exclusive)
+   */
+  public static char[] copyOfSubArray(char[] array, int from, int to) {
+    final char[] copy = new char[to-from];
+    System.arraycopy(array, from, copy, 0, to-from);
+    return copy;
+  }
+
+  /**
+   * Copies the specified range of the given array into a new sub array.
+   * @param array the input array
+   * @param from  the initial index of range to be copied (inclusive)
+   * @param to    the final index of range to be copied (exclusive)
+   */
+  public static short[] copyOfSubArray(short[] array, int from, int to) {
+    final short[] copy = new short[to-from];
+    System.arraycopy(array, from, copy, 0, to-from);
+    return copy;
+  }
+
+  /**
+   * Copies the specified range of the given array into a new sub array.
+   * @param array the input array
+   * @param from  the initial index of range to be copied (inclusive)
+   * @param to    the final index of range to be copied (exclusive)
+   */
+  public static int[] copyOfSubArray(int[] array, int from, int to) {
+    final int[] copy = new int[to-from];
+    System.arraycopy(array, from, copy, 0, to-from);
+    return copy;
+  }
+
+  /**
+   * Copies the specified range of the given array into a new sub array.
+   * @param array the input array
+   * @param from  the initial index of range to be copied (inclusive)
+   * @param to    the final index of range to be copied (exclusive)
+   */
+  public static long[] copyOfSubArray(long[] array, int from, int to) {
+    final long[] copy = new long[to-from];
+    System.arraycopy(array, from, copy, 0, to-from);
+    return copy;
+  }
+
+  /**
+   * Copies the specified range of the given array into a new sub array.
+   * @param array the input array
+   * @param from  the initial index of range to be copied (inclusive)
+   * @param to    the final index of range to be copied (exclusive)
+   */
+  public static float[] copyOfSubArray(float[] array, int from, int to) {
+    final float[] copy = new float[to-from];
+    System.arraycopy(array, from, copy, 0, to-from);
+    return copy;
+  }
+
+  /**
+   * Copies the specified range of the given array into a new sub array.
+   * @param array the input array
+   * @param from  the initial index of range to be copied (inclusive)
+   * @param to    the final index of range to be copied (exclusive)
+   */
+  public static double[] copyOfSubArray(double[] array, int from, int to) {
+    final double[] copy = new double[to-from];
+    System.arraycopy(array, from, copy, 0, to-from);
+    return copy;
+  }
+
+  /**
+   * Copies the specified range of the given array into a new sub array.
+   * @param array the input array
+   * @param from  the initial index of range to be copied (inclusive)
+   * @param to    the final index of range to be copied (exclusive)
+   */
+  public static <T> T[] copyOfSubArray(T[] array, int from, int to) {
+    final int subLength = to - from;
+    final Class<? extends Object[]> type = array.getClass();
+    @SuppressWarnings("unchecked")
+    final T[] copy = (type == Object[].class)
+        ? (T[]) new Object[subLength]
+        : (T[]) Array.newInstance(type.getComponentType(), subLength);
+    System.arraycopy(array, from, copy, 0, subLength);
+    return copy;
+  }
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8a6f1bf5/lucene/core/src/java/org/apache/lucene/util/BytesRef.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/util/BytesRef.java b/lucene/core/src/java/org/apache/lucene/util/BytesRef.java
index 42c4e87..a9a05e6 100644
--- a/lucene/core/src/java/org/apache/lucene/util/BytesRef.java
+++ b/lucene/core/src/java/org/apache/lucene/util/BytesRef.java
@@ -16,9 +16,6 @@
  */
 package org.apache.lucene.util;
 
-
-import java.util.Arrays;
-
 /** Represents byte[], as a slice (offset + length) into an
  *  existing byte[].  The {@link #bytes} member should never be null;
  *  use {@link #EMPTY_BYTES} if necessary.
@@ -172,11 +169,7 @@ public final class BytesRef implements Comparable<BytesRef>,Cloneable {
    * and an offset of zero.
    */
   public static BytesRef deepCopyOf(BytesRef other) {
-    BytesRef copy = new BytesRef();
-    copy.bytes = Arrays.copyOfRange(other.bytes, other.offset, other.offset + other.length);
-    copy.offset = 0;
-    copy.length = other.length;
-    return copy;
+    return new BytesRef(ArrayUtil.copyOfSubArray(other.bytes, other.offset, other.offset + other.length), 0, other.length);
   }
   
   /** 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8a6f1bf5/lucene/core/src/java/org/apache/lucene/util/BytesRefBuilder.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/util/BytesRefBuilder.java b/lucene/core/src/java/org/apache/lucene/util/BytesRefBuilder.java
index 08fda91..6abd866 100644
--- a/lucene/core/src/java/org/apache/lucene/util/BytesRefBuilder.java
+++ b/lucene/core/src/java/org/apache/lucene/util/BytesRefBuilder.java
@@ -17,8 +17,6 @@
 package org.apache.lucene.util;
 
 
-import java.util.Arrays;
-
 /**
  * A builder for {@link BytesRef} instances.
  * @lucene.internal
@@ -170,7 +168,7 @@ public class BytesRefBuilder {
    * Build a new {@link BytesRef} that has the same content as this buffer.
    */
   public BytesRef toBytesRef() {
-    return new BytesRef(Arrays.copyOf(ref.bytes, ref.length));
+    return new BytesRef(ArrayUtil.copyOfSubArray(ref.bytes, 0, ref.length));
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8a6f1bf5/lucene/core/src/java/org/apache/lucene/util/CharsRef.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/util/CharsRef.java b/lucene/core/src/java/org/apache/lucene/util/CharsRef.java
index eb839a8..7cb8ce9 100644
--- a/lucene/core/src/java/org/apache/lucene/util/CharsRef.java
+++ b/lucene/core/src/java/org/apache/lucene/util/CharsRef.java
@@ -17,7 +17,6 @@
 package org.apache.lucene.util;
 
 
-import java.util.Arrays;
 import java.util.Comparator;
 
 /**
@@ -202,7 +201,7 @@ public final class CharsRef implements Comparable<CharsRef>, CharSequence, Clone
    * and an offset of zero.
    */
   public static CharsRef deepCopyOf(CharsRef other) {
-    return new CharsRef(Arrays.copyOfRange(other.chars, other.offset, other.offset + other.length), 0, other.length);
+    return new CharsRef(ArrayUtil.copyOfSubArray(other.chars, other.offset, other.offset + other.length), 0, other.length);
   }
   
   /** 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8a6f1bf5/lucene/core/src/java/org/apache/lucene/util/CharsRefBuilder.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/util/CharsRefBuilder.java b/lucene/core/src/java/org/apache/lucene/util/CharsRefBuilder.java
index 09830e6..fdc16f4 100644
--- a/lucene/core/src/java/org/apache/lucene/util/CharsRefBuilder.java
+++ b/lucene/core/src/java/org/apache/lucene/util/CharsRefBuilder.java
@@ -17,8 +17,6 @@
 package org.apache.lucene.util;
 
 
-import java.util.Arrays;
-
 /**
  * A builder for {@link CharsRef} instances.
  * @lucene.internal
@@ -153,7 +151,7 @@ public class CharsRefBuilder implements Appendable {
 
   /** Build a new {@link CharsRef} that has the same content as this builder. */
   public CharsRef toCharsRef() {
-    return new CharsRef(Arrays.copyOf(ref.chars, ref.length), 0, ref.length);
+    return new CharsRef(ArrayUtil.copyOfSubArray(ref.chars, 0, ref.length), 0, ref.length);
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8a6f1bf5/lucene/core/src/java/org/apache/lucene/util/DocIdSetBuilder.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/util/DocIdSetBuilder.java b/lucene/core/src/java/org/apache/lucene/util/DocIdSetBuilder.java
index 954614b..e57292b 100644
--- a/lucene/core/src/java/org/apache/lucene/util/DocIdSetBuilder.java
+++ b/lucene/core/src/java/org/apache/lucene/util/DocIdSetBuilder.java
@@ -18,7 +18,6 @@ package org.apache.lucene.util;
 
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
 
 import org.apache.lucene.index.PointValues;
@@ -226,7 +225,7 @@ public final class DocIdSetBuilder {
   }
 
   private void growBuffer(Buffer buffer, int additionalCapacity) {
-    buffer.array = Arrays.copyOf(buffer.array, buffer.array.length + additionalCapacity);
+    buffer.array = ArrayUtil.growExact(buffer.array, buffer.array.length + additionalCapacity);
     totalAllocated += additionalCapacity;
   }
 
@@ -297,7 +296,7 @@ public final class DocIdSetBuilder {
     }
     int[] docs = largestBuffer.array;
     if (docs.length < totalLength + 1) {
-      docs = Arrays.copyOf(docs, totalLength + 1);
+      docs = ArrayUtil.growExact(docs, totalLength + 1);
     }
     totalLength = largestBuffer.length;
     for (Buffer buffer : buffers) {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8a6f1bf5/lucene/core/src/java/org/apache/lucene/util/IntsRef.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/util/IntsRef.java b/lucene/core/src/java/org/apache/lucene/util/IntsRef.java
index aa7bbce..0c6cfa5 100644
--- a/lucene/core/src/java/org/apache/lucene/util/IntsRef.java
+++ b/lucene/core/src/java/org/apache/lucene/util/IntsRef.java
@@ -16,8 +16,6 @@
  */
 package org.apache.lucene.util;
 
-import java.util.Arrays;
-
 
 /** Represents int[], as a slice (offset + length) into an
  *  existing int[].  The {@link #ints} member should never be null; use
@@ -127,7 +125,7 @@ public final class IntsRef implements Comparable<IntsRef>, Cloneable {
    * and an offset of zero.
    */
   public static IntsRef deepCopyOf(IntsRef other) {
-    return new IntsRef(Arrays.copyOfRange(other.ints, other.offset, other.offset + other.length), 0, other.length);
+    return new IntsRef(ArrayUtil.copyOfSubArray(other.ints, other.offset, other.offset + other.length), 0, other.length);
   }
   
   /** 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8a6f1bf5/lucene/core/src/java/org/apache/lucene/util/LongsRef.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/util/LongsRef.java b/lucene/core/src/java/org/apache/lucene/util/LongsRef.java
index 952d189..e4ca3ef 100644
--- a/lucene/core/src/java/org/apache/lucene/util/LongsRef.java
+++ b/lucene/core/src/java/org/apache/lucene/util/LongsRef.java
@@ -16,8 +16,6 @@
  */
 package org.apache.lucene.util;
 
-import java.util.Arrays;
-
 
 /** Represents long[], as a slice (offset + length) into an
  *  existing long[].  The {@link #longs} member should never be null; use
@@ -126,7 +124,7 @@ public final class LongsRef implements Comparable<LongsRef>, Cloneable {
    * and an offset of zero.
    */
   public static LongsRef deepCopyOf(LongsRef other) {
-    return new LongsRef(Arrays.copyOfRange(other.longs, other.offset, other.offset + other.length), 0, other.length);
+    return new LongsRef(ArrayUtil.copyOfSubArray(other.longs, other.offset, other.offset + other.length), 0, other.length);
   }
   
   /** 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8a6f1bf5/lucene/core/src/java/org/apache/lucene/util/PagedBytes.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/util/PagedBytes.java b/lucene/core/src/java/org/apache/lucene/util/PagedBytes.java
index ad26f85..e07046c 100644
--- a/lucene/core/src/java/org/apache/lucene/util/PagedBytes.java
+++ b/lucene/core/src/java/org/apache/lucene/util/PagedBytes.java
@@ -18,7 +18,6 @@ package org.apache.lucene.util;
 
 
 import java.io.IOException;
-import java.util.Arrays;
 
 import org.apache.lucene.store.DataInput;
 import org.apache.lucene.store.DataOutput;
@@ -62,7 +61,7 @@ public final class PagedBytes implements Accountable {
     private final long bytesUsedPerBlock;
 
     private Reader(PagedBytes pagedBytes) {
-      blocks = Arrays.copyOf(pagedBytes.blocks, pagedBytes.numBlocks);
+      blocks = ArrayUtil.copyOfSubArray(pagedBytes.blocks, 0, pagedBytes.numBlocks);
       blockBits = pagedBytes.blockBits;
       blockMask = pagedBytes.blockMask;
       blockSize = pagedBytes.blockSize;
@@ -154,9 +153,7 @@ public final class PagedBytes implements Accountable {
   }
 
   private void addBlock(byte[] block) {
-    if (blocks.length == numBlocks) {
-      blocks = Arrays.copyOf(blocks, ArrayUtil.oversize(numBlocks, RamUsageEstimator.NUM_BYTES_OBJECT_REF));
-    }
+    blocks = ArrayUtil.grow(blocks, numBlocks + 1);
     blocks[numBlocks++] = block;
   }
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8a6f1bf5/lucene/core/src/java/org/apache/lucene/util/RoaringDocIdSet.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/util/RoaringDocIdSet.java b/lucene/core/src/java/org/apache/lucene/util/RoaringDocIdSet.java
index 9709c30..5f704bb 100644
--- a/lucene/core/src/java/org/apache/lucene/util/RoaringDocIdSet.java
+++ b/lucene/core/src/java/org/apache/lucene/util/RoaringDocIdSet.java
@@ -18,7 +18,6 @@ package org.apache.lucene.util;
 
 
 import java.io.IOException;
-import java.util.Arrays;
 
 import org.apache.lucene.search.DocIdSet;
 import org.apache.lucene.search.DocIdSetIterator;
@@ -73,7 +72,7 @@ public class RoaringDocIdSet extends DocIdSet {
         // Use sparse encoding
         assert denseBuffer == null;
         if (currentBlockCardinality > 0) {
-          sets[currentBlock] = new ShortArrayDocIdSet(Arrays.copyOf(buffer, currentBlockCardinality));
+          sets[currentBlock] = new ShortArrayDocIdSet(ArrayUtil.copyOfSubArray(buffer, 0, currentBlockCardinality));
         }
       } else {
         assert denseBuffer != null;

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8a6f1bf5/lucene/core/src/java/org/apache/lucene/util/SparseFixedBitSet.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/util/SparseFixedBitSet.java b/lucene/core/src/java/org/apache/lucene/util/SparseFixedBitSet.java
index 0324291..4fcbbef 100644
--- a/lucene/core/src/java/org/apache/lucene/util/SparseFixedBitSet.java
+++ b/lucene/core/src/java/org/apache/lucene/util/SparseFixedBitSet.java
@@ -18,7 +18,6 @@ package org.apache.lucene.util;
 
 
 import java.io.IOException;
-import java.util.Arrays;
 
 import org.apache.lucene.search.DocIdSetIterator;
 
@@ -372,7 +371,7 @@ public class SparseFixedBitSet extends BitSet implements Bits, Accountable {
       // fast path: if we currently have nothing in the block, just copy the data
       // this especially happens all the time if you call OR on an empty set
       indices[i4096] = index;
-      this.bits[i4096] = Arrays.copyOf(bits, nonZeroLongCount);
+      this.bits[i4096] = ArrayUtil.copyOfSubArray(bits, 0, nonZeroLongCount);
       this.nonZeroLongCount += nonZeroLongCount;
       return;
     }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8a6f1bf5/lucene/core/src/java/org/apache/lucene/util/StringHelper.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/util/StringHelper.java b/lucene/core/src/java/org/apache/lucene/util/StringHelper.java
index 4c6d4fa..bdab07b 100644
--- a/lucene/core/src/java/org/apache/lucene/util/StringHelper.java
+++ b/lucene/core/src/java/org/apache/lucene/util/StringHelper.java
@@ -307,7 +307,7 @@ public abstract class StringHelper {
     if (bits.length > ID_LENGTH) {
       assert bits.length == ID_LENGTH + 1;
       assert bits[0] == 0;
-      return Arrays.copyOfRange(bits, 1, bits.length);
+      return ArrayUtil.copyOfSubArray(bits, 1, bits.length);
     } else {
       byte[] result = new byte[ID_LENGTH];
       System.arraycopy(bits, 0, result, result.length - bits.length, bits.length);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8a6f1bf5/lucene/core/src/java/org/apache/lucene/util/automaton/DaciukMihovAutomatonBuilder.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/util/automaton/DaciukMihovAutomatonBuilder.java b/lucene/core/src/java/org/apache/lucene/util/automaton/DaciukMihovAutomatonBuilder.java
index 704a6c4..60ec865 100644
--- a/lucene/core/src/java/org/apache/lucene/util/automaton/DaciukMihovAutomatonBuilder.java
+++ b/lucene/core/src/java/org/apache/lucene/util/automaton/DaciukMihovAutomatonBuilder.java
@@ -137,8 +137,8 @@ public final class DaciukMihovAutomatonBuilder {
       assert Arrays.binarySearch(labels, label) < 0 : "State already has transition labeled: "
           + label;
       
-      labels = Arrays.copyOf(labels, labels.length + 1);
-      states = Arrays.copyOf(states, states.length + 1);
+      labels = ArrayUtil.growExact(labels, labels.length + 1);
+      states = ArrayUtil.growExact(states, states.length + 1);
 
       labels[labels.length - 1] = label;
       return states[states.length - 1] = new State();

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8a6f1bf5/lucene/core/src/java/org/apache/lucene/util/bkd/BKDWriter.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/util/bkd/BKDWriter.java b/lucene/core/src/java/org/apache/lucene/util/bkd/BKDWriter.java
index 7f55895..fb7e1ce 100644
--- a/lucene/core/src/java/org/apache/lucene/util/bkd/BKDWriter.java
+++ b/lucene/core/src/java/org/apache/lucene/util/bkd/BKDWriter.java
@@ -656,7 +656,7 @@ public class BKDWriter implements Closeable {
 
       if (leafBlockFPs.size() > 0) {
         // Save the first (minimum) value in each leaf block except the first, to build the split value index in the end:
-        leafBlockStartValues.add(Arrays.copyOf(leafValues, packedBytesLength));
+        leafBlockStartValues.add(ArrayUtil.copyOfSubArray(leafValues, 0, packedBytesLength));
       }
       leafBlockFPs.add(out.getFilePointer());
       checkMaxLeafNodeCount(leafBlockFPs.size());
@@ -687,8 +687,8 @@ public class BKDWriter implements Closeable {
           return scratchBytesRef1;
         }
       };
-      assert valuesInOrderAndBounds(leafCount, 0, Arrays.copyOf(leafValues, packedBytesLength),
-          Arrays.copyOfRange(leafValues, (leafCount - 1) * packedBytesLength, leafCount * packedBytesLength),
+      assert valuesInOrderAndBounds(leafCount, 0, ArrayUtil.copyOfSubArray(leafValues, 0, packedBytesLength),
+          ArrayUtil.copyOfSubArray(leafValues, (leafCount - 1) * packedBytesLength, leafCount * packedBytesLength),
           packedValues, leafDocs, 0);
       writeLeafBlockPackedValues(scratchOut, commonPrefixLengths, leafCount, 0, packedValues);
       out.writeBytes(scratchOut.getBytes(), 0, scratchOut.getPosition());
@@ -1591,8 +1591,8 @@ public class BKDWriter implements Closeable {
       reader.getValue(mid, scratchBytesRef1);
       System.arraycopy(scratchBytesRef1.bytes, scratchBytesRef1.offset + splitDim * bytesPerDim, splitPackedValues, address + 1, bytesPerDim);
 
-      byte[] minSplitPackedValue = Arrays.copyOf(minPackedValue, packedBytesLength);
-      byte[] maxSplitPackedValue = Arrays.copyOf(maxPackedValue, packedBytesLength);
+      byte[] minSplitPackedValue = ArrayUtil.copyOfSubArray(minPackedValue, 0, packedBytesLength);
+      byte[] maxSplitPackedValue = ArrayUtil.copyOfSubArray(maxPackedValue, 0, packedBytesLength);
       System.arraycopy(scratchBytesRef1.bytes, scratchBytesRef1.offset + splitDim * bytesPerDim,
           minSplitPackedValue, splitDim * bytesPerDim, bytesPerDim);
       System.arraycopy(scratchBytesRef1.bytes, scratchBytesRef1.offset + splitDim * bytesPerDim,

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8a6f1bf5/lucene/core/src/java/org/apache/lucene/util/bkd/HeapPointWriter.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/util/bkd/HeapPointWriter.java b/lucene/core/src/java/org/apache/lucene/util/bkd/HeapPointWriter.java
index e102651..eb1d48b 100644
--- a/lucene/core/src/java/org/apache/lucene/util/bkd/HeapPointWriter.java
+++ b/lucene/core/src/java/org/apache/lucene/util/bkd/HeapPointWriter.java
@@ -18,7 +18,6 @@ package org.apache.lucene.util.bkd;
 
 import java.io.Closeable;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
 
 import org.apache.lucene.util.ArrayUtil;
@@ -116,12 +115,12 @@ public final class HeapPointWriter implements PointWriter {
     if (docIDs.length == nextWrite) {
       int nextSize = Math.min(maxSize, ArrayUtil.oversize(nextWrite+1, Integer.BYTES));
       assert nextSize > nextWrite: "nextSize=" + nextSize + " vs nextWrite=" + nextWrite;
-      docIDs = Arrays.copyOf(docIDs, nextSize);
+      docIDs = ArrayUtil.growExact(docIDs, nextSize);
       if (singleValuePerDoc == false) {
         if (ordsLong != null) {
-          ordsLong = Arrays.copyOf(ordsLong, nextSize);
+          ordsLong = ArrayUtil.growExact(ordsLong, nextSize);
         } else {
-          ords = Arrays.copyOf(ords, nextSize);
+          ords = ArrayUtil.growExact(ords, nextSize);
         }
       }
     }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8a6f1bf5/lucene/core/src/java/org/apache/lucene/util/packed/DeltaPackedLongValues.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/util/packed/DeltaPackedLongValues.java b/lucene/core/src/java/org/apache/lucene/util/packed/DeltaPackedLongValues.java
index 80534da..6aabb07 100644
--- a/lucene/core/src/java/org/apache/lucene/util/packed/DeltaPackedLongValues.java
+++ b/lucene/core/src/java/org/apache/lucene/util/packed/DeltaPackedLongValues.java
@@ -17,8 +17,7 @@
 package org.apache.lucene.util.packed;
 
 
-import java.util.Arrays;
-
+import org.apache.lucene.util.ArrayUtil;
 import org.apache.lucene.util.RamUsageEstimator;
 import org.apache.lucene.util.packed.PackedInts.Reader;
 
@@ -70,8 +69,8 @@ class DeltaPackedLongValues extends PackedLongValues {
     public DeltaPackedLongValues build() {
       finish();
       pending = null;
-      final PackedInts.Reader[] values = Arrays.copyOf(this.values, valuesOff);
-      final long[] mins = Arrays.copyOf(this.mins, valuesOff);
+      final PackedInts.Reader[] values = ArrayUtil.copyOfSubArray(this.values, 0, valuesOff);
+      final long[] mins = ArrayUtil.copyOfSubArray(this.mins, 0, valuesOff);
       final long ramBytesUsed = DeltaPackedLongValues.BASE_RAM_BYTES_USED
           + RamUsageEstimator.sizeOf(values) + RamUsageEstimator.sizeOf(mins);
       return new DeltaPackedLongValues(pageShift, pageMask, values, mins, size, ramBytesUsed);
@@ -94,7 +93,7 @@ class DeltaPackedLongValues extends PackedLongValues {
     void grow(int newBlockCount) {
       super.grow(newBlockCount);
       ramBytesUsed -= RamUsageEstimator.sizeOf(mins);
-      mins = Arrays.copyOf(mins, newBlockCount);
+      mins = ArrayUtil.growExact(mins, newBlockCount);
       ramBytesUsed += RamUsageEstimator.sizeOf(mins);
     }
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8a6f1bf5/lucene/core/src/java/org/apache/lucene/util/packed/MonotonicLongValues.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/util/packed/MonotonicLongValues.java b/lucene/core/src/java/org/apache/lucene/util/packed/MonotonicLongValues.java
index 09b3ecd..89ad5ab 100644
--- a/lucene/core/src/java/org/apache/lucene/util/packed/MonotonicLongValues.java
+++ b/lucene/core/src/java/org/apache/lucene/util/packed/MonotonicLongValues.java
@@ -17,10 +17,9 @@
 package org.apache.lucene.util.packed;
 
 
-import java.util.Arrays;
-
 import static org.apache.lucene.util.packed.MonotonicBlockPackedReader.expected;
 
+import org.apache.lucene.util.ArrayUtil;
 import org.apache.lucene.util.RamUsageEstimator;
 import org.apache.lucene.util.packed.PackedInts.Reader;
 
@@ -72,9 +71,9 @@ class MonotonicLongValues extends DeltaPackedLongValues {
     public MonotonicLongValues build() {
       finish();
       pending = null;
-      final PackedInts.Reader[] values = Arrays.copyOf(this.values, valuesOff);
-      final long[] mins = Arrays.copyOf(this.mins, valuesOff);
-      final float[] averages = Arrays.copyOf(this.averages, valuesOff);
+      final PackedInts.Reader[] values = ArrayUtil.copyOfSubArray(this.values, 0, valuesOff);
+      final long[] mins = ArrayUtil.copyOfSubArray(this.mins, 0, valuesOff);
+      final float[] averages = ArrayUtil.copyOfSubArray(this.averages, 0, valuesOff);
       final long ramBytesUsed = MonotonicLongValues.BASE_RAM_BYTES_USED
           + RamUsageEstimator.sizeOf(values) + RamUsageEstimator.sizeOf(mins)
           + RamUsageEstimator.sizeOf(averages);
@@ -95,7 +94,7 @@ class MonotonicLongValues extends DeltaPackedLongValues {
     void grow(int newBlockCount) {
       super.grow(newBlockCount);
       ramBytesUsed -= RamUsageEstimator.sizeOf(averages);
-      averages = Arrays.copyOf(averages, newBlockCount);
+      averages = ArrayUtil.growExact(averages, newBlockCount);
       ramBytesUsed += RamUsageEstimator.sizeOf(averages);
     }
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8a6f1bf5/lucene/core/src/java/org/apache/lucene/util/packed/PackedLongValues.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/util/packed/PackedLongValues.java b/lucene/core/src/java/org/apache/lucene/util/packed/PackedLongValues.java
index 0daf062..19788b7 100644
--- a/lucene/core/src/java/org/apache/lucene/util/packed/PackedLongValues.java
+++ b/lucene/core/src/java/org/apache/lucene/util/packed/PackedLongValues.java
@@ -19,8 +19,6 @@ package org.apache.lucene.util.packed;
 
 import static org.apache.lucene.util.packed.PackedInts.checkBlockSize;
 
-import java.util.Arrays;
-
 import org.apache.lucene.util.Accountable;
 import org.apache.lucene.util.ArrayUtil;
 import org.apache.lucene.util.LongValues;
@@ -194,7 +192,7 @@ public class PackedLongValues extends LongValues implements Accountable {
     public PackedLongValues build() {
       finish();
       pending = null;
-      final PackedInts.Reader[] values = Arrays.copyOf(this.values, valuesOff);
+      final PackedInts.Reader[] values = ArrayUtil.copyOfSubArray(this.values, 0, valuesOff);
       final long ramBytesUsed = PackedLongValues.BASE_RAM_BYTES_USED + RamUsageEstimator.sizeOf(values);
       return new PackedLongValues(pageShift, pageMask, values, size, ramBytesUsed);
     }
@@ -273,7 +271,7 @@ public class PackedLongValues extends LongValues implements Accountable {
 
     void grow(int newBlockCount) {
       ramBytesUsed -= RamUsageEstimator.shallowSizeOf(values);
-      values = Arrays.copyOf(values, newBlockCount);
+      values = ArrayUtil.growExact(values, newBlockCount);
       ramBytesUsed += RamUsageEstimator.shallowSizeOf(values);
     }
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8a6f1bf5/lucene/core/src/test/org/apache/lucene/analysis/TestCharacterUtils.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/analysis/TestCharacterUtils.java b/lucene/core/src/test/org/apache/lucene/analysis/TestCharacterUtils.java
index 53b3f56..438e5e3 100644
--- a/lucene/core/src/test/org/apache/lucene/analysis/TestCharacterUtils.java
+++ b/lucene/core/src/test/org/apache/lucene/analysis/TestCharacterUtils.java
@@ -20,9 +20,9 @@ package org.apache.lucene.analysis;
 import java.io.IOException;
 import java.io.Reader;
 import java.io.StringReader;
-import java.util.Arrays;
 
 import org.apache.lucene.analysis.CharacterUtils.CharacterBuffer;
+import org.apache.lucene.util.ArrayUtil;
 import org.apache.lucene.util.LuceneTestCase;
 import org.apache.lucene.util.TestUtil;
 import org.junit.Test;
@@ -42,7 +42,7 @@ public class TestCharacterUtils extends LuceneTestCase {
     final int codePointCount = CharacterUtils.toCodePoints(orig, o1, orig.length - o1, buf, o2);
     final int charCount = CharacterUtils.toChars(buf, o2, codePointCount, restored, o3);
     assertEquals(orig.length - o1, charCount);
-    assertArrayEquals(Arrays.copyOfRange(orig, o1, o1 + charCount), Arrays.copyOfRange(restored, o3, o3 + charCount));
+    assertArrayEquals(ArrayUtil.copyOfSubArray(orig, o1, o1 + charCount), ArrayUtil.copyOfSubArray(restored, o3, o3 + charCount));
   }
 
   @Test

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8a6f1bf5/lucene/core/src/test/org/apache/lucene/codecs/compressing/AbstractTestCompressionMode.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/codecs/compressing/AbstractTestCompressionMode.java b/lucene/core/src/test/org/apache/lucene/codecs/compressing/AbstractTestCompressionMode.java
index 045b19a..62d06d8 100644
--- a/lucene/core/src/test/org/apache/lucene/codecs/compressing/AbstractTestCompressionMode.java
+++ b/lucene/core/src/test/org/apache/lucene/codecs/compressing/AbstractTestCompressionMode.java
@@ -22,6 +22,7 @@ import java.util.Arrays;
 
 import org.apache.lucene.store.ByteArrayDataInput;
 import org.apache.lucene.store.ByteArrayDataOutput;
+import org.apache.lucene.util.ArrayUtil;
 import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.LuceneTestCase;
 import org.apache.lucene.util.TestUtil;
@@ -60,7 +61,7 @@ public abstract class AbstractTestCompressionMode extends LuceneTestCase {
     ByteArrayDataOutput out = new ByteArrayDataOutput(compressed);
     compressor.compress(decompressed, off, len, out);
     final int compressedLen = out.getPosition();
-    return Arrays.copyOf(compressed, compressedLen);
+    return ArrayUtil.copyOfSubArray(compressed, 0, compressedLen);
   }
 
   byte[] decompress(byte[] compressed, int originalLength) throws IOException {
@@ -71,14 +72,14 @@ public abstract class AbstractTestCompressionMode extends LuceneTestCase {
   static byte[] decompress(Decompressor decompressor, byte[] compressed, int originalLength) throws IOException {
     final BytesRef bytes = new BytesRef();
     decompressor.decompress(new ByteArrayDataInput(compressed), originalLength, 0, originalLength, bytes);
-    return Arrays.copyOfRange(bytes.bytes, bytes.offset, bytes.offset + bytes.length);
+    return BytesRef.deepCopyOf(bytes).bytes;
   }
 
   byte[] decompress(byte[] compressed, int originalLength, int offset, int length) throws IOException {
     Decompressor decompressor = mode.newDecompressor();
     final BytesRef bytes = new BytesRef();
     decompressor.decompress(new ByteArrayDataInput(compressed), originalLength, offset, length, bytes);
-    return Arrays.copyOfRange(bytes.bytes, bytes.offset, bytes.offset + bytes.length);
+    return BytesRef.deepCopyOf(bytes).bytes;
   }
 
   public void testDecompress() throws IOException {
@@ -89,7 +90,7 @@ public abstract class AbstractTestCompressionMode extends LuceneTestCase {
       final int len = random().nextBoolean() ? decompressed.length - off : TestUtil.nextInt(random(), 0, decompressed.length - off);
       final byte[] compressed = compress(decompressed, off, len);
       final byte[] restored = decompress(compressed, len);
-      assertArrayEquals(Arrays.copyOfRange(decompressed, off, off+len), restored);
+      assertArrayEquals(ArrayUtil.copyOfSubArray(decompressed, off, off+len), restored);
     }
   }
 
@@ -106,7 +107,7 @@ public abstract class AbstractTestCompressionMode extends LuceneTestCase {
         length = random().nextInt(decompressed.length - offset);
       }
       final byte[] restored = decompress(compressed, decompressed.length, offset, length);
-      assertArrayEquals(Arrays.copyOfRange(decompressed, offset, offset + length), restored);
+      assertArrayEquals(ArrayUtil.copyOfSubArray(decompressed, offset, offset + length), restored);
     }
   }
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8a6f1bf5/lucene/core/src/test/org/apache/lucene/codecs/lucene50/TestForUtil.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/codecs/lucene50/TestForUtil.java b/lucene/core/src/test/org/apache/lucene/codecs/lucene50/TestForUtil.java
index 3fe003e..e13645f 100644
--- a/lucene/core/src/test/org/apache/lucene/codecs/lucene50/TestForUtil.java
+++ b/lucene/core/src/test/org/apache/lucene/codecs/lucene50/TestForUtil.java
@@ -22,13 +22,13 @@ import static org.apache.lucene.codecs.lucene50.ForUtil.MAX_DATA_SIZE;
 import static org.apache.lucene.codecs.lucene50.ForUtil.MAX_ENCODED_SIZE;
 
 import java.io.IOException;
-import java.util.Arrays;
 
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.store.IOContext;
 import org.apache.lucene.store.IndexInput;
 import org.apache.lucene.store.IndexOutput;
 import org.apache.lucene.store.RAMDirectory;
+import org.apache.lucene.util.ArrayUtil;
 import org.apache.lucene.util.LuceneTestCase;
 import org.apache.lucene.util.packed.PackedInts;
 
@@ -39,7 +39,7 @@ public class TestForUtil extends LuceneTestCase {
   public void testEncodeDecode() throws IOException {
     final int iterations = RandomNumbers.randomIntBetween(random(), 1, 1000);
     final float acceptableOverheadRatio = random().nextFloat();
-    final int[] values = new int[(iterations - 1) * BLOCK_SIZE + ForUtil.MAX_DATA_SIZE];
+    final int[] values = new int[iterations * BLOCK_SIZE];
     for (int i = 0; i < iterations; ++i) {
       final int bpv = random().nextInt(32);
       if (bpv == 0) {
@@ -64,9 +64,9 @@ public class TestForUtil extends LuceneTestCase {
       final ForUtil forUtil = new ForUtil(acceptableOverheadRatio, out);
       
       for (int i = 0; i < iterations; ++i) {
-        forUtil.writeBlock(
-            Arrays.copyOfRange(values, i * BLOCK_SIZE, values.length),
-            new byte[MAX_ENCODED_SIZE], out);
+        // Although values after BLOCK_SIZE are garbage, we need to allocate extra bytes to avoid AIOOBE.
+        int[] block = ArrayUtil.grow(ArrayUtil.copyOfSubArray(values, i*BLOCK_SIZE, (i+1)*BLOCK_SIZE));
+        forUtil.writeBlock(ArrayUtil.grow(block, MAX_DATA_SIZE), new byte[MAX_ENCODED_SIZE], out);
       }
       endPointer = out.getFilePointer();
       out.close();
@@ -83,8 +83,8 @@ public class TestForUtil extends LuceneTestCase {
         }
         final int[] restored = new int[MAX_DATA_SIZE];
         forUtil.readBlock(in, new byte[MAX_ENCODED_SIZE], restored);
-        assertArrayEquals(Arrays.copyOfRange(values, i * BLOCK_SIZE, (i + 1) * BLOCK_SIZE),
-            Arrays.copyOf(restored, BLOCK_SIZE));
+        assertArrayEquals(ArrayUtil.copyOfSubArray(values, i*BLOCK_SIZE, (i+1)*BLOCK_SIZE),
+            ArrayUtil.copyOfSubArray(restored, 0, BLOCK_SIZE));
       }
       assertEquals(endPointer, in.getFilePointer());
       in.close();

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8a6f1bf5/lucene/core/src/test/org/apache/lucene/index/TestPerSegmentDeletes.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/index/TestPerSegmentDeletes.java b/lucene/core/src/test/org/apache/lucene/index/TestPerSegmentDeletes.java
index 4da5059..6e2bd13 100644
--- a/lucene/core/src/test/org/apache/lucene/index/TestPerSegmentDeletes.java
+++ b/lucene/core/src/test/org/apache/lucene/index/TestPerSegmentDeletes.java
@@ -18,7 +18,6 @@ package org.apache.lucene.index;
 
 
 import java.io.IOException;
-import java.util.Arrays;
 import java.util.Map;
 import java.util.Random;
 
@@ -238,7 +237,7 @@ public class TestPerSegmentDeletes extends LuceneTestCase {
       docs = ArrayUtil.grow(docs, numDocs + 1);
       docs[numDocs + 1] = docID;
     }
-    return Arrays.copyOf(docs, numDocs);
+    return ArrayUtil.copyOfSubArray(docs, 0, numDocs);
   }
 
   public static class RangeMergePolicy extends MergePolicy {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8a6f1bf5/lucene/core/src/test/org/apache/lucene/search/TestBoolean2.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestBoolean2.java b/lucene/core/src/test/org/apache/lucene/search/TestBoolean2.java
index a9e2891..66b895a 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestBoolean2.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestBoolean2.java
@@ -19,7 +19,6 @@ package org.apache.lucene.search;
 
 
 import java.io.IOException;
-import java.util.Arrays;
 import java.util.Collections;
 import java.util.Random;
 
@@ -38,6 +37,7 @@ import org.apache.lucene.index.Term;
 import org.apache.lucene.search.similarities.ClassicSimilarity;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.store.IOContext;
+import org.apache.lucene.util.ArrayUtil;
 import org.apache.lucene.util.LuceneTestCase;
 import org.apache.lucene.util.TestUtil;
 import org.junit.AfterClass;
@@ -227,7 +227,7 @@ public class TestBoolean2 extends LuceneTestCase {
 
     // adjust the expected doc numbers according to our filler docs
     if (0 < NUM_FILLER_DOCS) {
-      expDocNrs = Arrays.copyOf(expDocNrs, expDocNrs.length);
+      expDocNrs = ArrayUtil.copyOfSubArray(expDocNrs, 0, expDocNrs.length);
       for (int i=0; i < expDocNrs.length; i++) {
         expDocNrs[i] = PRE_FILLER_DOCS + ((NUM_FILLER_DOCS + 1) * expDocNrs[i]);
       }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8a6f1bf5/lucene/core/src/test/org/apache/lucene/search/TestDoubleValuesSource.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestDoubleValuesSource.java b/lucene/core/src/test/org/apache/lucene/search/TestDoubleValuesSource.java
index 5a5a3ae..49b0e11 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestDoubleValuesSource.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestDoubleValuesSource.java
@@ -31,6 +31,7 @@ import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.store.Directory;
+import org.apache.lucene.util.ArrayUtil;
 import org.apache.lucene.util.English;
 import org.apache.lucene.util.LuceneTestCase;
 import org.apache.lucene.util.TestUtil;
@@ -122,7 +123,7 @@ public class TestDoubleValuesSource extends LuceneTestCase {
     };
     Collections.shuffle(Arrays.asList(fields), random());
     int numSorts = TestUtil.nextInt(random(), 1, fields.length);
-    return new Sort(Arrays.copyOfRange(fields, 0, numSorts));
+    return new Sort(ArrayUtil.copyOfSubArray(fields, 0, numSorts));
   }
 
   // Take a Sort, and replace any field sorts with Sortables

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8a6f1bf5/lucene/core/src/test/org/apache/lucene/search/TestLongValuesSource.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestLongValuesSource.java b/lucene/core/src/test/org/apache/lucene/search/TestLongValuesSource.java
index 8b20be5..4c77e7e 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestLongValuesSource.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestLongValuesSource.java
@@ -27,6 +27,7 @@ import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.store.Directory;
+import org.apache.lucene.util.ArrayUtil;
 import org.apache.lucene.util.English;
 import org.apache.lucene.util.LuceneTestCase;
 import org.apache.lucene.util.TestUtil;
@@ -103,7 +104,7 @@ public class TestLongValuesSource extends LuceneTestCase {
     };
     Collections.shuffle(Arrays.asList(fields), random());
     int numSorts = TestUtil.nextInt(random(), 1, fields.length);
-    return new Sort(Arrays.copyOfRange(fields, 0, numSorts));
+    return new Sort(ArrayUtil.copyOfSubArray(fields, 0, numSorts));
   }
 
   // Take a Sort, and replace any field sorts with Sortables

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8a6f1bf5/lucene/core/src/test/org/apache/lucene/search/TestPhraseQuery.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestPhraseQuery.java b/lucene/core/src/test/org/apache/lucene/search/TestPhraseQuery.java
index eb31128..7bd235e 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestPhraseQuery.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestPhraseQuery.java
@@ -45,6 +45,7 @@ import org.apache.lucene.index.Term;
 import org.apache.lucene.search.similarities.BM25Similarity;
 import org.apache.lucene.search.similarities.ClassicSimilarity;
 import org.apache.lucene.store.Directory;
+import org.apache.lucene.util.ArrayUtil;
 import org.apache.lucene.util.LuceneTestCase;
 import org.apache.lucene.util.TestUtil;
 import org.junit.AfterClass;
@@ -731,7 +732,7 @@ public class TestPhraseQuery extends LuceneTestCase {
   public void testTopPhrases() throws IOException {
     Directory dir = newDirectory();
     IndexWriter w = new IndexWriter(dir, newIndexWriterConfig());
-    String[] docs = Arrays.copyOf(DOCS, DOCS.length);
+    String[] docs = ArrayUtil.copyOfSubArray(DOCS, 0, DOCS.length);
     Collections.shuffle(Arrays.asList(docs), random());
     for (String value : DOCS) {
       Document doc = new Document();


Mime
View raw message