You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by us...@apache.org on 2018/02/04 13:14:10 UTC

[2/2] lucene-solr:branch_7x: Revert "LUCENE-7966: Build Multi-Release JARs to enable usage of optimized intrinsic methods from Java 9 for index bounds checking and array comparison/mismatch"

Revert "LUCENE-7966: Build Multi-Release JARs to enable usage of optimized intrinsic methods from Java 9 for index bounds checking and array comparison/mismatch"

This reverts commit 05a105a9f76b73b597931894dff392ad44243aa0.


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

Branch: refs/heads/branch_7x
Commit: 5f43dce1d06e1f5dcc8c5d306bb89c42e427d00d
Parents: 05a105a
Author: Uwe Schindler <us...@apache.org>
Authored: Sun Feb 4 14:13:49 2018 +0100
Committer: Uwe Schindler <us...@apache.org>
Committed: Sun Feb 4 14:13:49 2018 +0100

----------------------------------------------------------------------
 build.xml                                       |   1 -
 lucene/CHANGES.txt                              |   6 -
 lucene/build.xml                                |   2 +-
 .../blockterms/FixedGapTermsIndexWriter.java    |   8 +-
 .../SimpleTextStoredFieldsReader.java           |   5 +-
 lucene/common-build.xml                         |  48 +--
 lucene/core/build.xml                           |   9 -
 .../tokenattributes/CharTermAttributeImpl.java  |  19 +-
 .../CompressingTermVectorsWriter.java           |   8 +-
 .../apache/lucene/codecs/compressing/LZ4.java   |   8 +-
 .../lucene70/Lucene70DocValuesConsumer.java     |   8 +-
 .../org/apache/lucene/document/BinaryPoint.java |   4 +-
 .../org/apache/lucene/document/DoubleRange.java |  11 +-
 .../org/apache/lucene/document/FloatRange.java  |  11 +-
 .../org/apache/lucene/document/IntRange.java    |  11 +-
 .../org/apache/lucene/document/LongRange.java   |  11 +-
 .../java/org/apache/lucene/index/BitsSlice.java |   6 +-
 .../org/apache/lucene/index/CodecReader.java    |   5 +-
 .../apache/lucene/index/MergeReaderWrapper.java |   5 +-
 .../apache/lucene/index/PrefixCodedTerms.java   |  28 +-
 .../org/apache/lucene/search/BooleanScorer.java |   5 +-
 .../java/org/apache/lucene/util/ArrayUtil.java  |  52 ++++
 .../java/org/apache/lucene/util/BytesRef.java   |  39 ++-
 .../org/apache/lucene/util/BytesRefArray.java   |  36 ++-
 .../java/org/apache/lucene/util/CharsRef.java   | 102 +++++--
 .../org/apache/lucene/util/FutureArrays.java    | 268 ----------------
 .../org/apache/lucene/util/FutureObjects.java   |  70 -----
 .../java/org/apache/lucene/util/IntsRef.java    |  38 ++-
 .../java/org/apache/lucene/util/LongsRef.java   |  38 ++-
 .../org/apache/lucene/util/StringHelper.java    |  87 ++++--
 .../apache/lucene/util/automaton/Automaton.java |  25 +-
 .../TestCharTermAttributeImpl.java              |   3 +-
 .../org/apache/lucene/util/TestArrayUtil.java   |  16 +
 .../apache/lucene/util/TestFutureArrays.java    | 305 -------------------
 .../apache/lucene/util/TestFutureObjects.java   | 102 -------
 .../apache/lucene/util/TestStringHelper.java    |  13 -
 .../org/apache/lucene/util/TestUnicodeUtil.java |   3 +-
 .../lucene/facet/taxonomy/TaxonomyWriter.java   |   2 +-
 .../directory/DirectoryTaxonomyWriter.java      |   5 +-
 .../facet/taxonomy/TestTaxonomyCombined.java    |   6 +-
 lucene/module-build.xml                         |   9 -
 .../tools/src/groovy/patch-mrjar-classes.groovy |  73 -----
 solr/common-build.xml                           |   3 -
 43 files changed, 440 insertions(+), 1074 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5f43dce1/build.xml
----------------------------------------------------------------------
diff --git a/build.xml b/build.xml
index 2d300b5..a100e12 100755
--- a/build.xml
+++ b/build.xml
@@ -874,5 +874,4 @@ Test args: [${args}]</echo>
 
   <!-- useless targets (override common-build.xml): -->
   <target name="generate-test-reports"/>
-  <target name="patch-mrjar-classes"/>
 </project>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5f43dce1/lucene/CHANGES.txt
----------------------------------------------------------------------
diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt
index f59768d..7a27718 100644
--- a/lucene/CHANGES.txt
+++ b/lucene/CHANGES.txt
@@ -54,12 +54,6 @@ Improvements
 * LUCENE-8129: A Unicode set filter can now be specified when using ICUFoldingFilter.
   (Ere Maijala)
 
-* LUCENE-7966: Build Multi-Release JARs to enable usage of optimized intrinsic methods
-  from Java 9 for index bounds checking and array comparison/mismatch. This change
-  introduces Java 8 replacements for those Java 9 methods and patches the compiled
-  classes to use the optimized variants through the MR-JAR mechanism.
-  (Uwe Schindler, Robert Muir, Adrien Grand, Mike McCandless)
-
 Bug Fixes
 
 * LUCENE-8077: Fixed bug in how CheckIndex verifies doc-value iterators.

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5f43dce1/lucene/build.xml
----------------------------------------------------------------------
diff --git a/lucene/build.xml b/lucene/build.xml
index f2ce68d..3aa4e42 100644
--- a/lucene/build.xml
+++ b/lucene/build.xml
@@ -557,7 +557,7 @@
   </target>
 
   <!-- Override common-build.xml definition to check for the jar already being up-to-date -->
-  <target name="jar-core" depends="resolve-groovy,check-lucene-core-uptodate,compile-lucene-core" unless="lucene-core.uptodate">
+  <target name="jar-core" depends="check-lucene-core-uptodate,compile-lucene-core" unless="lucene-core.uptodate">
     <ant dir="${common.dir}/core" target="jar-core" inheritAll="false">
       <propertyset refid="uptodate.and.compiled.properties"/>
     </ant>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5f43dce1/lucene/codecs/src/java/org/apache/lucene/codecs/blockterms/FixedGapTermsIndexWriter.java
----------------------------------------------------------------------
diff --git a/lucene/codecs/src/java/org/apache/lucene/codecs/blockterms/FixedGapTermsIndexWriter.java b/lucene/codecs/src/java/org/apache/lucene/codecs/blockterms/FixedGapTermsIndexWriter.java
index abb4cb0..cdfd962 100644
--- a/lucene/codecs/src/java/org/apache/lucene/codecs/blockterms/FixedGapTermsIndexWriter.java
+++ b/lucene/codecs/src/java/org/apache/lucene/codecs/blockterms/FixedGapTermsIndexWriter.java
@@ -150,13 +150,7 @@ public class FixedGapTermsIndexWriter extends TermsIndexWriterBase {
 
     @Override
     public void add(BytesRef text, TermStats stats, long termsFilePointer) throws IOException {
-      final int indexedTermLength;
-      if (numIndexTerms == 0) {
-        // no previous term: no bytes to write
-        indexedTermLength = 0;
-      } else {
-        indexedTermLength = indexedTermPrefixLength(lastTerm.get(), text);
-      }
+      final int indexedTermLength = indexedTermPrefixLength(lastTerm.get(), text);
       //System.out.println("FGW: add text=" + text.utf8ToString() + " " + text + " fp=" + termsFilePointer);
 
       // write only the min prefix that shows the diff

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5f43dce1/lucene/codecs/src/java/org/apache/lucene/codecs/simpletext/SimpleTextStoredFieldsReader.java
----------------------------------------------------------------------
diff --git a/lucene/codecs/src/java/org/apache/lucene/codecs/simpletext/SimpleTextStoredFieldsReader.java b/lucene/codecs/src/java/org/apache/lucene/codecs/simpletext/SimpleTextStoredFieldsReader.java
index b457ca5..ead8ecc 100644
--- a/lucene/codecs/src/java/org/apache/lucene/codecs/simpletext/SimpleTextStoredFieldsReader.java
+++ b/lucene/codecs/src/java/org/apache/lucene/codecs/simpletext/SimpleTextStoredFieldsReader.java
@@ -36,7 +36,6 @@ import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.BytesRefBuilder;
 import org.apache.lucene.util.CharsRef;
 import org.apache.lucene.util.CharsRefBuilder;
-import org.apache.lucene.util.FutureArrays;
 import org.apache.lucene.util.IOUtils;
 import org.apache.lucene.util.RamUsageEstimator;
 import org.apache.lucene.util.StringHelper;
@@ -203,8 +202,8 @@ public class SimpleTextStoredFieldsReader extends StoredFieldsReader {
   }
   
   private boolean equalsAt(BytesRef a, BytesRef b, int bOffset) {
-    return a.length == b.length - bOffset &&
-        FutureArrays.equals(a.bytes, a.offset, a.offset + a.length, b.bytes, b.offset + bOffset, b.offset + b.length);
+    return a.length == b.length - bOffset && 
+        ArrayUtil.equals(a.bytes, a.offset, b.bytes, b.offset + bOffset, b.length - bOffset);
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5f43dce1/lucene/common-build.xml
----------------------------------------------------------------------
diff --git a/lucene/common-build.xml b/lucene/common-build.xml
index 7ce8d6f..f6f4da3 100644
--- a/lucene/common-build.xml
+++ b/lucene/common-build.xml
@@ -160,10 +160,6 @@
 
   <!-- Display at most this many failures as a summary at the end of junit4 run. -->
   <property name="tests.showNumFailures" value="10" />
-  
-  <!-- If we detect Java 9+, should we test the patched classes of the
-   multi-release JAR or still run with our own classes? -->
-  <property name="tests.withJava9Patches" value="true" />
 
   <property name="javac.deprecation" value="off"/>
   <property name="javac.debug" value="on"/>
@@ -550,48 +546,10 @@
     <!-- convenience target to compile core -->
   </target>
 
-  <!-- Special targets to patch all class files by replacing some method calls with new Java 9 methods: -->
-  <target name="-mrjar-classes-uptodate">
-    <uptodate property="mrjar-classes-uptodate" targetfile="${build.dir}/patch-mrjar.stamp">
-      <srcfiles dir= "${build.dir}/classes/java" includes="**/*.class"/>
-    </uptodate>
-  </target>
-  
-  <target xmlns:ivy="antlib:org.apache.ivy.ant" name="patch-mrjar-classes" depends="-mrjar-classes-uptodate,ivy-availability-check,ivy-configure,resolve-groovy,compile-core"
-    unless="mrjar-classes-uptodate" description="Patches compiled class files for usage with Java 9 in MR-JAR">
-    <loadproperties prefix="ivyversions" srcFile="${common.dir}/ivy-versions.properties"/>
-    <ivy:cachepath organisation="org.ow2.asm" module="asm-commons" revision="${ivyversions./org.ow2.asm/asm-commons}"
-      inline="true" conf="default" transitive="true" log="download-only" pathid="asm.classpath"/>
-    <groovy classpathref="asm.classpath" src="${common.dir}/tools/src/groovy/patch-mrjar-classes.groovy"/>
-    <touch file="${build.dir}/patch-mrjar.stamp"/>
-  </target>
-  
-  <target name="-mrjar-check" depends="patch-mrjar-classes">
-    <zipfileset id="mrjar-patched-files" prefix="META-INF/versions/9" dir="${build.dir}/classes/java9"/>
-    <condition property="has-mrjar-patched-files">
-      <resourcecount refid="mrjar-patched-files" when="greater" count="0" />
-    </condition>
-  </target>
-  
-  <target name="-mrjar-core" depends="-mrjar-check" if="has-mrjar-patched-files">
-    <jarify>
-      <filesets>
-        <zipfileset refid="mrjar-patched-files"/>
-      </filesets>
-      <jarify-additional-manifest-attributes>
-        <attribute name="Multi-Release" value="true"/>
-      </jarify-additional-manifest-attributes>
-    </jarify>
-  </target>
-  
-  <target name="-jar-core" depends="-mrjar-check" unless="has-mrjar-patched-files">
+  <target name="jar-core" depends="compile-core">
     <jarify/>
   </target>
-  
-  <target name="jar-core" depends="-mrjar-core,-jar-core"/>
 
-  <!-- Packaging targets: -->
-  
   <property name="lucene.tgz.file" location="${common.dir}/dist/lucene-${version}.tgz"/>
   <available file="${lucene.tgz.file}" property="lucene.tgz.exists"/>
   <property name="lucene.tgz.unpack.dir" location="${common.build.dir}/lucene.tgz.unpacked"/>
@@ -1495,8 +1453,8 @@ ${tests-output}/junit4-*.suites     - per-JVM executed suites
     </taskdef>
   </target>
 
-  <target name="test" depends="clover,compile-test,patch-mrjar-classes,install-junit4-taskdef,validate,-init-totals,-test,-check-totals" description="Runs unit tests"/>
-  <target name="beast" depends="clover,compile-test,patch-mrjar-classes,install-junit4-taskdef,validate,-init-totals,-beast,-check-totals" description="Runs unit tests in a loop (-Dbeast.iters=n)"/>
+  <target name="test" depends="clover,compile-test,install-junit4-taskdef,validate,-init-totals,-test,-check-totals" description="Runs unit tests"/>
+  <target name="beast" depends="clover,compile-test,install-junit4-taskdef,validate,-init-totals,-beast,-check-totals" description="Runs unit tests in a loop (-Dbeast.iters=n)"/>
 
   <target name="test-nocompile" depends="-clover.disable,install-junit4-taskdef,-init-totals,-test,-check-totals"
           description="Only runs unit tests.  Jars are not downloaded; compilation is not updated; and Clover is not enabled."/>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5f43dce1/lucene/core/build.xml
----------------------------------------------------------------------
diff --git a/lucene/core/build.xml b/lucene/core/build.xml
index 46183b0..d968798 100644
--- a/lucene/core/build.xml
+++ b/lucene/core/build.xml
@@ -31,19 +31,10 @@
 
   <path id="classpath"/>
   
-  <!-- if we run with Java 9+, we refer to the java9 classes directory and insert this before the main classpath (to "emulate" a MR-JAR): -->
-  <condition property="-test.classpath.java9.addon" value="${build.dir}/classes/java9" else="${build.dir}/classes/java">
-    <and>
-      <not><equals arg1="${build.java.runtime}" arg2="1.8"/></not>
-      <istrue value="${tests.withJava9Patches}"/>
-    </and>
-  </condition>
-
   <path id="test.classpath">
     <pathelement location="${common.dir}/build/codecs/classes/java"/>
     <pathelement location="${common.dir}/build/test-framework/classes/java"/>
     <path refid="junit-path"/>
-    <pathelement location="${-test.classpath.java9.addon}"/><!-- if it's a duplicate it gets removed by Ant! -->
     <pathelement location="${build.dir}/classes/java"/>
     <pathelement location="${build.dir}/classes/test"/>
   </path>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5f43dce1/lucene/core/src/java/org/apache/lucene/analysis/tokenattributes/CharTermAttributeImpl.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/analysis/tokenattributes/CharTermAttributeImpl.java b/lucene/core/src/java/org/apache/lucene/analysis/tokenattributes/CharTermAttributeImpl.java
index f28cc78..355f417 100644
--- a/lucene/core/src/java/org/apache/lucene/analysis/tokenattributes/CharTermAttributeImpl.java
+++ b/lucene/core/src/java/org/apache/lucene/analysis/tokenattributes/CharTermAttributeImpl.java
@@ -23,7 +23,6 @@ import org.apache.lucene.util.AttributeImpl;
 import org.apache.lucene.util.AttributeReflector;
 import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.BytesRefBuilder;
-import org.apache.lucene.util.FutureObjects;
 
 /** Default implementation of {@link CharTermAttribute}. */
 public class CharTermAttributeImpl extends AttributeImpl implements CharTermAttribute, TermToBytesRefAttribute, Cloneable {
@@ -72,7 +71,11 @@ public class CharTermAttributeImpl extends AttributeImpl implements CharTermAttr
 
   @Override
   public final CharTermAttribute setLength(int length) {
-    FutureObjects.checkFromIndexSize(0, length, termBuffer.length);
+    if (length < 0) {
+      throw new IllegalArgumentException("length " + length + " must not be negative");
+    }
+    if (length > termBuffer.length)
+      throw new IllegalArgumentException("length " + length + " exceeds the size of the termBuffer (" + termBuffer.length + ")");
     termLength = length;
     return this;
   }
@@ -99,13 +102,15 @@ public class CharTermAttributeImpl extends AttributeImpl implements CharTermAttr
   
   @Override
   public final char charAt(int index) {
-    FutureObjects.checkIndex(index, termLength);
+    if (index >= termLength)
+      throw new IndexOutOfBoundsException();
     return termBuffer[index];
   }
   
   @Override
   public final CharSequence subSequence(final int start, final int end) {
-    FutureObjects.checkFromToIndex(start, end, termLength);
+    if (start > termLength || end > termLength)
+      throw new IndexOutOfBoundsException();
     return new String(termBuffer, start, end - start);
   }
   
@@ -122,9 +127,9 @@ public class CharTermAttributeImpl extends AttributeImpl implements CharTermAttr
   public final CharTermAttribute append(CharSequence csq, int start, int end) {
     if (csq == null) // needed for Appendable compliance
       csq = "null";
-    // TODO: the optimized cases (jdk methods) will already do such checks, maybe re-organize this?
-    FutureObjects.checkFromToIndex(start, end, csq.length());
-    final int len = end - start;
+    final int len = end - start, csqlen = csq.length();
+    if (len < 0 || start > csqlen || end > csqlen)
+      throw new IndexOutOfBoundsException();
     if (len == 0)
       return this;
     resizeBuffer(termLength + len);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5f43dce1/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..26fe890 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
@@ -293,13 +293,7 @@ public final class CompressingTermVectorsWriter extends TermVectorsWriter {
   @Override
   public void startTerm(BytesRef term, int freq) throws IOException {
     assert freq >= 1;
-    final int prefix;
-    if (lastTerm.length == 0) {
-      // no previous term: no bytes to write
-      prefix = 0;
-    } else {
-      prefix = StringHelper.bytesDifference(lastTerm, term);
-    }
+    final int prefix = StringHelper.bytesDifference(lastTerm, term);
     curField.addTerm(freq, prefix, term.length - prefix);
     termSuffixes.writeBytes(term.bytes, term.offset + prefix, term.length - prefix);
     // copy last term

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5f43dce1/lucene/core/src/java/org/apache/lucene/codecs/compressing/LZ4.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/codecs/compressing/LZ4.java b/lucene/core/src/java/org/apache/lucene/codecs/compressing/LZ4.java
index cba625f..44bc82c 100644
--- a/lucene/core/src/java/org/apache/lucene/codecs/compressing/LZ4.java
+++ b/lucene/core/src/java/org/apache/lucene/codecs/compressing/LZ4.java
@@ -22,7 +22,6 @@ import java.util.Arrays;
 
 import org.apache.lucene.store.DataInput;
 import org.apache.lucene.store.DataOutput;
-import org.apache.lucene.util.FutureArrays;
 import org.apache.lucene.util.packed.PackedInts;
 
 /**
@@ -62,8 +61,11 @@ final class LZ4 {
 
   private static int commonBytes(byte[] b, int o1, int o2, int limit) {
     assert o1 < o2;
-    // never -1 because lengths always differ
-    return FutureArrays.mismatch(b, o1, limit, b, o2, limit);
+    int count = 0;
+    while (o2 < limit && b[o1++] == b[o2++]) {
+      ++count;
+    }
+    return count;
   }
 
   private static int commonBytesBackward(byte[] b, int o1, int o2, int l1, int l2) {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5f43dce1/lucene/core/src/java/org/apache/lucene/codecs/lucene70/Lucene70DocValuesConsumer.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/codecs/lucene70/Lucene70DocValuesConsumer.java b/lucene/core/src/java/org/apache/lucene/codecs/lucene70/Lucene70DocValuesConsumer.java
index e25e8e7..2dd68e9 100644
--- a/lucene/core/src/java/org/apache/lucene/codecs/lucene70/Lucene70DocValuesConsumer.java
+++ b/lucene/core/src/java/org/apache/lucene/codecs/lucene70/Lucene70DocValuesConsumer.java
@@ -504,13 +504,7 @@ final class Lucene70DocValuesConsumer extends DocValuesConsumer implements Close
     for (BytesRef term = iterator.next(); term != null; term = iterator.next()) {
       if ((ord & Lucene70DocValuesFormat.TERMS_DICT_REVERSE_INDEX_MASK) == 0) {
         writer.add(offset);
-        final int sortKeyLength;
-        if (ord == 0) {
-          // no previous term: no bytes to write
-          sortKeyLength = 0;
-        } else {
-          sortKeyLength = StringHelper.sortKeyLength(previous.get(), term);
-        }
+        int sortKeyLength = StringHelper.sortKeyLength(previous.get(), term);
         offset += sortKeyLength;
         data.writeBytes(term.bytes, term.offset, sortKeyLength);
       } else if ((ord & Lucene70DocValuesFormat.TERMS_DICT_REVERSE_INDEX_MASK) == Lucene70DocValuesFormat.TERMS_DICT_REVERSE_INDEX_MASK) {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5f43dce1/lucene/core/src/java/org/apache/lucene/document/BinaryPoint.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/document/BinaryPoint.java b/lucene/core/src/java/org/apache/lucene/document/BinaryPoint.java
index 693a00f..81ef092 100644
--- a/lucene/core/src/java/org/apache/lucene/document/BinaryPoint.java
+++ b/lucene/core/src/java/org/apache/lucene/document/BinaryPoint.java
@@ -26,7 +26,7 @@ import org.apache.lucene.search.PointInSetQuery;
 import org.apache.lucene.search.PointRangeQuery;
 import org.apache.lucene.search.Query;
 import org.apache.lucene.util.BytesRef;
-import org.apache.lucene.util.FutureArrays;
+import org.apache.lucene.util.StringHelper;
 
 /** 
  * An indexed binary field for fast range filters.  If you also
@@ -222,7 +222,7 @@ public final class BinaryPoint extends Field {
                 new Comparator<byte[]>() {
                   @Override
                   public int compare(byte[] a, byte[] b) {
-                    return FutureArrays.compareUnsigned(a, 0, a.length, b, 0, b.length);
+                    return StringHelper.compare(a.length, a, 0, b, 0);
                   }
                 });
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5f43dce1/lucene/core/src/java/org/apache/lucene/document/DoubleRange.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/document/DoubleRange.java b/lucene/core/src/java/org/apache/lucene/document/DoubleRange.java
index c1d2dc5..90a8eb9 100644
--- a/lucene/core/src/java/org/apache/lucene/document/DoubleRange.java
+++ b/lucene/core/src/java/org/apache/lucene/document/DoubleRange.java
@@ -19,7 +19,6 @@ package org.apache.lucene.document;
 import org.apache.lucene.document.RangeFieldQuery.QueryType;
 import org.apache.lucene.search.Query;
 import org.apache.lucene.util.BytesRef;
-import org.apache.lucene.util.FutureObjects;
 import org.apache.lucene.util.NumericUtils;
 
 /**
@@ -148,7 +147,10 @@ public class DoubleRange extends Field {
    * @return the decoded min value
    */
   public double getMin(int dimension) {
-    FutureObjects.checkIndex(dimension, type.pointDimensionCount()/2);
+    if (dimension < 0 || dimension >= type.pointDimensionCount()/2) {
+      throw new IllegalArgumentException("dimension request (" + dimension +
+          ") out of bounds for field (name=" + name + " dimensions=" + type.pointDimensionCount()/2 + "). ");
+    }
     return decodeMin(((BytesRef)fieldsData).bytes, dimension);
   }
 
@@ -158,7 +160,10 @@ public class DoubleRange extends Field {
    * @return the decoded max value
    */
   public double getMax(int dimension) {
-    FutureObjects.checkIndex(dimension, type.pointDimensionCount()/2);
+    if (dimension < 0 || dimension >= type.pointDimensionCount()/2) {
+      throw new IllegalArgumentException("dimension request (" + dimension +
+          ") out of bounds for field (name=" + name + " dimensions=" + type.pointDimensionCount()/2 + "). ");
+    }
     return decodeMax(((BytesRef)fieldsData).bytes, dimension);
   }
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5f43dce1/lucene/core/src/java/org/apache/lucene/document/FloatRange.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/document/FloatRange.java b/lucene/core/src/java/org/apache/lucene/document/FloatRange.java
index facf23b..8b40538 100644
--- a/lucene/core/src/java/org/apache/lucene/document/FloatRange.java
+++ b/lucene/core/src/java/org/apache/lucene/document/FloatRange.java
@@ -19,7 +19,6 @@ package org.apache.lucene.document;
 import org.apache.lucene.document.RangeFieldQuery.QueryType;
 import org.apache.lucene.search.Query;
 import org.apache.lucene.util.BytesRef;
-import org.apache.lucene.util.FutureObjects;
 import org.apache.lucene.util.NumericUtils;
 
 /**
@@ -148,7 +147,10 @@ public class FloatRange extends Field {
    * @return the decoded min value
    */
   public float getMin(int dimension) {
-    FutureObjects.checkIndex(dimension, type.pointDimensionCount()/2);
+    if (dimension < 0 || dimension >= type.pointDimensionCount()/2) {
+      throw new IllegalArgumentException("dimension request (" + dimension +
+          ") out of bounds for field (name=" + name + " dimensions=" + type.pointDimensionCount()/2 + "). ");
+    }
     return decodeMin(((BytesRef)fieldsData).bytes, dimension);
   }
 
@@ -158,7 +160,10 @@ public class FloatRange extends Field {
    * @return the decoded max value
    */
   public float getMax(int dimension) {
-    FutureObjects.checkIndex(dimension, type.pointDimensionCount()/2);
+    if (dimension < 0 || dimension >= type.pointDimensionCount()/2) {
+      throw new IllegalArgumentException("dimension request (" + dimension +
+          ") out of bounds for field (name=" + name + " dimensions=" + type.pointDimensionCount()/2 + "). ");
+    }
     return decodeMax(((BytesRef)fieldsData).bytes, dimension);
   }
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5f43dce1/lucene/core/src/java/org/apache/lucene/document/IntRange.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/document/IntRange.java b/lucene/core/src/java/org/apache/lucene/document/IntRange.java
index b426613..6d2b71c 100644
--- a/lucene/core/src/java/org/apache/lucene/document/IntRange.java
+++ b/lucene/core/src/java/org/apache/lucene/document/IntRange.java
@@ -19,7 +19,6 @@ package org.apache.lucene.document;
 import org.apache.lucene.document.RangeFieldQuery.QueryType;
 import org.apache.lucene.search.Query;
 import org.apache.lucene.util.BytesRef;
-import org.apache.lucene.util.FutureObjects;
 import org.apache.lucene.util.NumericUtils;
 
 /**
@@ -148,7 +147,10 @@ public class IntRange extends Field {
    * @return the decoded min value
    */
   public int getMin(int dimension) {
-    FutureObjects.checkIndex(dimension, type.pointDimensionCount()/2);
+    if (dimension < 0 || dimension >= type.pointDimensionCount()/2) {
+      throw new IllegalArgumentException("dimension request (" + dimension +
+          ") out of bounds for field (name=" + name + " dimensions=" + type.pointDimensionCount()/2 + "). ");
+    }
     return decodeMin(((BytesRef)fieldsData).bytes, dimension);
   }
 
@@ -158,7 +160,10 @@ public class IntRange extends Field {
    * @return the decoded max value
    */
   public int getMax(int dimension) {
-    FutureObjects.checkIndex(dimension, type.pointDimensionCount()/2);
+    if (dimension < 0 || dimension >= type.pointDimensionCount()/2) {
+      throw new IllegalArgumentException("dimension request (" + dimension +
+          ") out of bounds for field (name=" + name + " dimensions=" + type.pointDimensionCount()/2 + "). ");
+    }
     return decodeMax(((BytesRef)fieldsData).bytes, dimension);
   }
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5f43dce1/lucene/core/src/java/org/apache/lucene/document/LongRange.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/document/LongRange.java b/lucene/core/src/java/org/apache/lucene/document/LongRange.java
index 5c1c763..009f4a1 100644
--- a/lucene/core/src/java/org/apache/lucene/document/LongRange.java
+++ b/lucene/core/src/java/org/apache/lucene/document/LongRange.java
@@ -19,7 +19,6 @@ package org.apache.lucene.document;
 import org.apache.lucene.document.RangeFieldQuery.QueryType;
 import org.apache.lucene.search.Query;
 import org.apache.lucene.util.BytesRef;
-import org.apache.lucene.util.FutureObjects;
 import org.apache.lucene.util.NumericUtils;
 
 /**
@@ -146,7 +145,10 @@ public class LongRange extends Field {
    * @return the decoded min value
    */
   public long getMin(int dimension) {
-    FutureObjects.checkIndex(dimension, type.pointDimensionCount()/2);
+    if (dimension < 0 || dimension >= type.pointDimensionCount()/2) {
+      throw new IllegalArgumentException("dimension request (" + dimension +
+          ") out of bounds for field (name=" + name + " dimensions=" + type.pointDimensionCount()/2 + "). ");
+    }
     return decodeMin(((BytesRef)fieldsData).bytes, dimension);
   }
 
@@ -156,7 +158,10 @@ public class LongRange extends Field {
    * @return the decoded max value
    */
   public long getMax(int dimension) {
-    FutureObjects.checkIndex(dimension, type.pointDimensionCount()/2);
+    if (dimension < 0 || dimension >= type.pointDimensionCount()/2) {
+      throw new IllegalArgumentException("dimension request (" + dimension +
+          ") out of bounds for field (name=" + name + " dimensions=" + type.pointDimensionCount()/2 + "). ");
+    }
     return decodeMax(((BytesRef)fieldsData).bytes, dimension);
   }
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5f43dce1/lucene/core/src/java/org/apache/lucene/index/BitsSlice.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/index/BitsSlice.java b/lucene/core/src/java/org/apache/lucene/index/BitsSlice.java
index 19bf9c1..216d8f9 100644
--- a/lucene/core/src/java/org/apache/lucene/index/BitsSlice.java
+++ b/lucene/core/src/java/org/apache/lucene/index/BitsSlice.java
@@ -17,7 +17,6 @@
 package org.apache.lucene.index;
 
 import org.apache.lucene.util.Bits;
-import org.apache.lucene.util.FutureObjects;
 
 
 /**
@@ -40,7 +39,10 @@ final class BitsSlice implements Bits {
     
   @Override
   public boolean get(int doc) {
-    FutureObjects.checkIndex(doc, length);
+    if (doc >= length) {
+      throw new RuntimeException("doc " + doc + " is out of bounds 0 .. " + (length-1));
+    }
+    assert doc < length: "doc=" + doc + " length=" + length;
     return parent.get(doc+start);
   }
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5f43dce1/lucene/core/src/java/org/apache/lucene/index/CodecReader.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/index/CodecReader.java b/lucene/core/src/java/org/apache/lucene/index/CodecReader.java
index 50aaa42..9efcf25 100644
--- a/lucene/core/src/java/org/apache/lucene/index/CodecReader.java
+++ b/lucene/core/src/java/org/apache/lucene/index/CodecReader.java
@@ -31,7 +31,6 @@ import org.apache.lucene.codecs.StoredFieldsReader;
 import org.apache.lucene.codecs.TermVectorsReader;
 import org.apache.lucene.util.Accountable;
 import org.apache.lucene.util.Accountables;
-import org.apache.lucene.util.FutureObjects;
 
 /**
  * LeafReader implemented by codec APIs.
@@ -95,7 +94,9 @@ public abstract class CodecReader extends LeafReader implements Accountable {
   }
   
   private void checkBounds(int docID) {
-    FutureObjects.checkIndex(docID, maxDoc());
+    if (docID < 0 || docID >= maxDoc()) {       
+      throw new IndexOutOfBoundsException("docID must be >= 0 and < maxDoc=" + maxDoc() + " (got docID=" + docID + ")");
+    }
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5f43dce1/lucene/core/src/java/org/apache/lucene/index/MergeReaderWrapper.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/index/MergeReaderWrapper.java b/lucene/core/src/java/org/apache/lucene/index/MergeReaderWrapper.java
index 1f35e45..565bdd4 100644
--- a/lucene/core/src/java/org/apache/lucene/index/MergeReaderWrapper.java
+++ b/lucene/core/src/java/org/apache/lucene/index/MergeReaderWrapper.java
@@ -25,7 +25,6 @@ import org.apache.lucene.codecs.NormsProducer;
 import org.apache.lucene.codecs.StoredFieldsReader;
 import org.apache.lucene.codecs.TermVectorsReader;
 import org.apache.lucene.util.Bits;
-import org.apache.lucene.util.FutureObjects;
 
 /** This is a hack to make index sorting fast, with a {@link LeafReader} that always returns merge instances when you ask for the codec readers. */
 class MergeReaderWrapper extends LeafReader {
@@ -227,7 +226,9 @@ class MergeReaderWrapper extends LeafReader {
   }
 
   private void checkBounds(int docID) {
-    FutureObjects.checkIndex(docID, maxDoc());
+    if (docID < 0 || docID >= maxDoc()) {       
+      throw new IndexOutOfBoundsException("docID must be >= 0 and < maxDoc=" + maxDoc() + " (got docID=" + docID + ")");
+    }
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5f43dce1/lucene/core/src/java/org/apache/lucene/index/PrefixCodedTerms.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/index/PrefixCodedTerms.java b/lucene/core/src/java/org/apache/lucene/index/PrefixCodedTerms.java
index 7a65d71..ba56c2a 100644
--- a/lucene/core/src/java/org/apache/lucene/index/PrefixCodedTerms.java
+++ b/lucene/core/src/java/org/apache/lucene/index/PrefixCodedTerms.java
@@ -26,7 +26,6 @@ import org.apache.lucene.store.RAMOutputStream;
 import org.apache.lucene.util.Accountable;
 import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.BytesRefBuilder;
-import org.apache.lucene.util.StringHelper;
 
 /**
  * Prefix codes term instances (prefixes are shared). This is expected to be
@@ -75,19 +74,14 @@ public class PrefixCodedTerms implements Accountable {
       assert lastTerm.equals(new Term("")) || new Term(field, bytes).compareTo(lastTerm) > 0;
 
       try {
-        final int prefix;
-        if (size > 0 && field.equals(lastTerm.field)) {
-          // same field as the last term
-          prefix = StringHelper.bytesDifference(lastTerm.bytes, bytes);
+        int prefix = sharedPrefix(lastTerm.bytes, bytes);
+        int suffix = bytes.length - prefix;
+        if (field.equals(lastTerm.field)) {
           output.writeVInt(prefix << 1);
         } else {
-          // field change
-          prefix = 0;
-          output.writeVInt(1);
+          output.writeVInt(prefix << 1 | 1);
           output.writeString(field);
         }
-
-        int suffix = bytes.length - prefix;
         output.writeVInt(suffix);
         output.writeBytes(bytes.bytes, bytes.offset + prefix, suffix);
         lastTermBytes.copyBytes(bytes);
@@ -108,6 +102,20 @@ public class PrefixCodedTerms implements Accountable {
         throw new RuntimeException(e);
       }
     }
+    
+    private int sharedPrefix(BytesRef term1, BytesRef term2) {
+      int pos1 = 0;
+      int pos1End = pos1 + Math.min(term1.length, term2.length);
+      int pos2 = 0;
+      while(pos1 < pos1End) {
+        if (term1.bytes[term1.offset + pos1] != term2.bytes[term2.offset + pos2]) {
+          return pos1;
+        }
+        pos1++;
+        pos2++;
+      }
+      return pos1;
+    }
   }
 
   /** An iterator over the list of terms stored in a {@link PrefixCodedTerms}. */

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5f43dce1/lucene/core/src/java/org/apache/lucene/search/BooleanScorer.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/BooleanScorer.java b/lucene/core/src/java/org/apache/lucene/search/BooleanScorer.java
index 0e075b4..59b6be5 100644
--- a/lucene/core/src/java/org/apache/lucene/search/BooleanScorer.java
+++ b/lucene/core/src/java/org/apache/lucene/search/BooleanScorer.java
@@ -22,7 +22,6 @@ import java.util.Arrays;
 import java.util.Collection;
 
 import org.apache.lucene.util.Bits;
-import org.apache.lucene.util.FutureObjects;
 import org.apache.lucene.util.PriorityQueue;
 
 /**
@@ -106,7 +105,9 @@ final class BooleanScorer extends BulkScorer {
     }
 
     public BulkScorerAndDoc get(int i) {
-      FutureObjects.checkIndex(i, size());
+      if (i < 0 || i >= size()) {
+        throw new IndexOutOfBoundsException();
+      }
       return (BulkScorerAndDoc) getHeapArray()[1 + i];
     }
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5f43dce1/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..3bc65ef 100644
--- a/lucene/core/src/java/org/apache/lucene/util/ArrayUtil.java
+++ b/lucene/core/src/java/org/apache/lucene/util/ArrayUtil.java
@@ -313,6 +313,58 @@ public final class ArrayUtil {
       code = code * 31 + array[i];
     return code;
   }
+  
+  // Since Arrays.equals doesn't implement offsets for equals
+  /**
+   * See if two array slices are the same.
+   *
+   * @param left        The left array to compare
+   * @param offsetLeft  The offset into the array.  Must be positive
+   * @param right       The right array to compare
+   * @param offsetRight the offset into the right array.  Must be positive
+   * @param length      The length of the section of the array to compare
+   * @return true if the two arrays, starting at their respective offsets, are equal
+   * 
+   * @see java.util.Arrays#equals(byte[], byte[])
+   */
+  public static boolean equals(byte[] left, int offsetLeft, byte[] right, int offsetRight, int length) {
+    if ((offsetLeft + length <= left.length) && (offsetRight + length <= right.length)) {
+      for (int i = 0; i < length; i++) {
+        if (left[offsetLeft + i] != right[offsetRight + i]) {
+          return false;
+        }
+
+      }
+      return true;
+    }
+    return false;
+  }
+
+  // Since Arrays.equals doesn't implement offsets for equals
+  /**
+   * See if two array slices are the same.
+   *
+   * @param left        The left array to compare
+   * @param offsetLeft  The offset into the array.  Must be positive
+   * @param right       The right array to compare
+   * @param offsetRight the offset into the right array.  Must be positive
+   * @param length      The length of the section of the array to compare
+   * @return true if the two arrays, starting at their respective offsets, are equal
+   * 
+   * @see java.util.Arrays#equals(char[], char[])
+   */
+  public static boolean equals(int[] left, int offsetLeft, int[] right, int offsetRight, int length) {
+    if ((offsetLeft + length <= left.length) && (offsetRight + length <= right.length)) {
+      for (int i = 0; i < length; i++) {
+        if (left[offsetLeft + i] != right[offsetRight + i]) {
+          return false;
+        }
+
+      }
+      return true;
+    }
+    return false;
+  }
 
   /** Swap values stored in slots <code>i</code> and <code>j</code> */
   public static <T> void swap(T[] arr, int i, int j) {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5f43dce1/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..2fcf28a 100644
--- a/lucene/core/src/java/org/apache/lucene/util/BytesRef.java
+++ b/lucene/core/src/java/org/apache/lucene/util/BytesRef.java
@@ -96,8 +96,20 @@ public final class BytesRef implements Comparable<BytesRef>,Cloneable {
    * @lucene.internal
    */
   public boolean bytesEquals(BytesRef other) {
-    return FutureArrays.equals(this.bytes, this.offset, this.offset + this.length, 
-                               other.bytes, other.offset, other.offset + other.length);
+    assert other != null;
+    if (length == other.length) {
+      int otherUpto = other.offset;
+      final byte[] otherBytes = other.bytes;
+      final int end = offset + length;
+      for(int upto=offset;upto<end;upto++,otherUpto++) {
+        if (bytes[upto] != otherBytes[otherUpto]) {
+          return false;
+        }
+      }
+      return true;
+    } else {
+      return false;
+    }
   }
 
   /**
@@ -160,8 +172,27 @@ public final class BytesRef implements Comparable<BytesRef>,Cloneable {
   /** Unsigned byte order comparison */
   @Override
   public int compareTo(BytesRef other) {
-    return FutureArrays.compareUnsigned(this.bytes, this.offset, this.offset + this.length, 
-                                        other.bytes, other.offset, other.offset + other.length);
+    // TODO: Once we are on Java 9 replace this by java.util.Arrays#compareUnsigned()
+    // which is implemented by a Hotspot intrinsic! Also consider building a
+    // Multi-Release-JAR!
+    final byte[] aBytes = this.bytes;
+    int aUpto = this.offset;
+    final byte[] bBytes = other.bytes;
+    int bUpto = other.offset;
+    
+    final int aStop = aUpto + Math.min(this.length, other.length);
+    while(aUpto < aStop) {
+      int aByte = aBytes[aUpto++] & 0xff;
+      int bByte = bBytes[bUpto++] & 0xff;
+
+      int diff = aByte - bByte;
+      if (diff != 0) {
+        return diff;
+      }
+    }
+
+    // One is a prefix of the other, or, they are equal:
+    return this.length - other.length;
   }
     
   /**

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5f43dce1/lucene/core/src/java/org/apache/lucene/util/BytesRefArray.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/util/BytesRefArray.java b/lucene/core/src/java/org/apache/lucene/util/BytesRefArray.java
index 00222f4..bab3d04 100644
--- a/lucene/core/src/java/org/apache/lucene/util/BytesRefArray.java
+++ b/lucene/core/src/java/org/apache/lucene/util/BytesRefArray.java
@@ -93,28 +93,34 @@ public final class BytesRefArray implements SortableBytesRefArray {
    * @return the <i>n'th</i> element of this {@link BytesRefArray}
    */
   public BytesRef get(BytesRefBuilder spare, int index) {
-    FutureObjects.checkIndex(index, lastElement);
-    int offset = offsets[index];
-    int length = index == lastElement - 1 ? currentOffset - offset
-        : offsets[index + 1] - offset;
-    spare.grow(length);
-    spare.setLength(length);
-    pool.readBytes(offset, spare.bytes(), 0, spare.length());
-    return spare.get();
+    if (lastElement > index) {
+      int offset = offsets[index];
+      int length = index == lastElement - 1 ? currentOffset - offset
+          : offsets[index + 1] - offset;
+      spare.grow(length);
+      spare.setLength(length);
+      pool.readBytes(offset, spare.bytes(), 0, spare.length());
+      return spare.get();
+    }
+    throw new IndexOutOfBoundsException("index " + index
+        + " must be less than the size: " + lastElement);
   }
 
   /** Used only by sort below, to set a {@link BytesRef} with the specified slice, avoiding copying bytes in the common case when the slice
    *  is contained in a single block in the byte block pool. */
   private void setBytesRef(BytesRefBuilder spare, BytesRef result, int index) {
-    FutureObjects.checkIndex(index, lastElement);
-    int offset = offsets[index];
-    int length;
-    if (index == lastElement - 1) {
-      length = currentOffset - offset;
+    if (index < lastElement) {
+      int offset = offsets[index];
+      int length;
+      if (index == lastElement - 1) {
+        length = currentOffset - offset;
+      } else {
+        length = offsets[index + 1] - offset;
+      }
+      pool.setBytesRef(spare, result, offset, length);
     } else {
-      length = offsets[index + 1] - offset;
+      throw new IndexOutOfBoundsException("index " + index + " must be less than the size: " + lastElement);
     }
-    pool.setBytesRef(spare, result, offset, length);
   }
   
   private int[] sort(final Comparator<BytesRef> comp) {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5f43dce1/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..aacdfcc 100644
--- a/lucene/core/src/java/org/apache/lucene/util/CharsRef.java
+++ b/lucene/core/src/java/org/apache/lucene/util/CharsRef.java
@@ -107,15 +107,46 @@ public final class CharsRef implements Comparable<CharsRef>, CharSequence, Clone
   }
 
   public boolean charsEquals(CharsRef other) {
-    return FutureArrays.equals(this.chars, this.offset, this.offset + this.length, 
-                               other.chars, other.offset, other.offset + other.length);
+    if (length == other.length) {
+      int otherUpto = other.offset;
+      final char[] otherChars = other.chars;
+      final int end = offset + length;
+      for (int upto = offset; upto < end; upto++, otherUpto++) {
+        if (chars[upto] != otherChars[otherUpto]) {
+          return false;
+        }
+      }
+      return true;
+    } else {
+      return false;
+    }
   }
 
   /** Signed int order comparison */
   @Override
   public int compareTo(CharsRef other) {
-    return FutureArrays.compare(this.chars, this.offset, this.offset + this.length, 
-                                other.chars, other.offset, other.offset + other.length);
+    if (this == other)
+      return 0;
+
+    final char[] aChars = this.chars;
+    int aUpto = this.offset;
+    final char[] bChars = other.chars;
+    int bUpto = other.offset;
+
+    final int aStop = aUpto + Math.min(this.length, other.length);
+
+    while (aUpto < aStop) {
+      int aInt = aChars[aUpto++];
+      int bInt = bChars[bUpto++];
+      if (aInt > bInt) {
+        return 1;
+      } else if (aInt < bInt) {
+        return -1;
+      }
+    }
+
+    // One is a prefix of the other, or, they are equal:
+    return this.length - other.length;
   }
 
   @Override
@@ -131,14 +162,18 @@ public final class CharsRef implements Comparable<CharsRef>, CharSequence, Clone
   @Override
   public char charAt(int index) {
     // NOTE: must do a real check here to meet the specs of CharSequence
-    FutureObjects.checkIndex(index, length);
+    if (index < 0 || index >= length) {
+      throw new IndexOutOfBoundsException();
+    }
     return chars[offset + index];
   }
 
   @Override
   public CharSequence subSequence(int start, int end) {
     // NOTE: must do a real check here to meet the specs of CharSequence
-    FutureObjects.checkFromToIndex(start, end, length);
+    if (start < 0 || end > length || start > end) {
+      throw new IndexOutOfBoundsException();
+    }
     return new CharsRef(chars, offset + start, end - start);
   }
   
@@ -160,33 +195,40 @@ public final class CharsRef implements Comparable<CharsRef>, CharSequence, Clone
 
     @Override
     public int compare(CharsRef a, CharsRef b) {
-      int aEnd = a.offset + a.length;
-      int bEnd = b.offset + b.length;
-      int i = FutureArrays.mismatch(a.chars, a.offset, aEnd, 
-                                    b.chars, b.offset, bEnd);
-
-      if (i >= 0 && i < Math.min(a.length, b.length)) {
-        // http://icu-project.org/docs/papers/utf16_code_point_order.html
-
-        char aChar = a.chars[a.offset + i];
-        char bChar = b.chars[b.offset + i];        
-        /* aChar != bChar, fix up each one if they're both in or above the surrogate range, then compare them */
-        if (aChar >= 0xd800 && bChar >= 0xd800) {
-          if (aChar >= 0xe000) {
-            aChar -= 0x800;
-          } else {
-            aChar += 0x2000;
-          }
+      if (a == b)
+        return 0;
+
+      final char[] aChars = a.chars;
+      int aUpto = a.offset;
+      final char[] bChars = b.chars;
+      int bUpto = b.offset;
+
+      final int aStop = aUpto + Math.min(a.length, b.length);
+
+      while (aUpto < aStop) {
+        char aChar = aChars[aUpto++];
+        char bChar = bChars[bUpto++];
+        if (aChar != bChar) {
+          // http://icu-project.org/docs/papers/utf16_code_point_order.html
           
-          if (bChar >= 0xe000) {
-            bChar -= 0x800;
-          } else {
-            bChar += 0x2000;
+          /* aChar != bChar, fix up each one if they're both in or above the surrogate range, then compare them */
+          if (aChar >= 0xd800 && bChar >= 0xd800) {
+            if (aChar >= 0xe000) {
+              aChar -= 0x800;
+            } else {
+              aChar += 0x2000;
+            }
+            
+            if (bChar >= 0xe000) {
+              bChar -= 0x800;
+            } else {
+              bChar += 0x2000;
+            }
           }
+          
+          /* now aChar and bChar are in code point order */
+          return (int)aChar - (int)bChar; /* int must be 32 bits wide */
         }
-
-        /* now aChar and bChar are in code point order */
-        return (int)aChar - (int)bChar; /* int must be 32 bits wide */
       }
 
       // One is a prefix of the other, or, they are equal:

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5f43dce1/lucene/core/src/java/org/apache/lucene/util/FutureArrays.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/util/FutureArrays.java b/lucene/core/src/java/org/apache/lucene/util/FutureArrays.java
deleted file mode 100644
index 0154053..0000000
--- a/lucene/core/src/java/org/apache/lucene/util/FutureArrays.java
+++ /dev/null
@@ -1,268 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.lucene.util;
-
-/**
- * Additional methods from Java 9's <a href="https://docs.oracle.com/javase/9/docs/api/java/util/Arrays.html">
- * {@code java.util.Arrays}</a>.
- * <p>
- * This class will be removed when Java 9 is minimum requirement.
- * Currently any bytecode is patched to use the Java 9 native
- * classes through MR-JAR (Multi-Release JAR) mechanism.
- * In Java 8 it will use THIS implementation.
- * Because of patching, inside the Java source files we always
- * refer to the Lucene implementations, but the final Lucene
- * JAR files will use the native Java 9 class names when executed
- * with Java 9.
- * @lucene.internal
- */
-public final class FutureArrays {
-  
-  private FutureArrays() {} // no instance
-  
-  // methods in Arrays are defined stupid: they cannot use Objects.checkFromToIndex
-  // they throw IAE (vs IOOBE) in the case of fromIndex > toIndex.
-  // so this method works just like checkFromToIndex, but with that stupidity added.
-  private static void checkFromToIndex(int fromIndex, int toIndex, int length) {
-    if (fromIndex > toIndex) {
-      throw new IllegalArgumentException("fromIndex " + fromIndex + " > toIndex " + toIndex);
-    }
-    if (fromIndex < 0 || toIndex > length) {
-      throw new IndexOutOfBoundsException("Range [" + fromIndex + ", " + toIndex + ") out-of-bounds for length " + length);
-    }
-  }
-
-  // byte[]
-
-  /**
-   * Behaves like Java 9's Arrays.mismatch
-   * @see <a href="http://download.java.net/java/jdk9/docs/api/java/util/Arrays.html#mismatch-byte:A-int-int-byte:A-int-int-">Arrays.mismatch</a>
-   */
-  public static int mismatch(byte[] a, int aFromIndex, int aToIndex, byte[] b, int bFromIndex, int bToIndex) {
-    checkFromToIndex(aFromIndex, aToIndex, a.length);
-    checkFromToIndex(bFromIndex, bToIndex, b.length);
-    int aLen = aToIndex - aFromIndex;
-    int bLen = bToIndex - bFromIndex;
-    int len = Math.min(aLen, bLen);
-    for (int i = 0; i < len; i++)
-      if (a[i+aFromIndex] != b[i+bFromIndex])
-        return i;
-    return aLen == bLen ? -1 : len;
-  }
-  
-  /**
-   * Behaves like Java 9's Arrays.compareUnsigned
-   * @see <a href="http://download.java.net/java/jdk9/docs/api/java/util/Arrays.html#compareUnsigned-byte:A-int-int-byte:A-int-int-">Arrays.compareUnsigned</a>
-   */
-  public static int compareUnsigned(byte[] a, int aFromIndex, int aToIndex, byte[] b, int bFromIndex, int bToIndex) {
-    checkFromToIndex(aFromIndex, aToIndex, a.length);
-    checkFromToIndex(bFromIndex, bToIndex, b.length);
-    int aLen = aToIndex - aFromIndex;
-    int bLen = bToIndex - bFromIndex;
-    int len = Math.min(aLen, bLen);
-    for (int i = 0; i < len; i++) {
-      int aByte = a[i+aFromIndex] & 0xFF;
-      int bByte = b[i+bFromIndex] & 0xFF;
-      int diff = aByte - bByte;
-      if (diff != 0) {
-        return diff;
-      }
-    }
-
-    // One is a prefix of the other, or, they are equal:
-    return aLen - bLen;
-  }
-  
-  /**
-   * Behaves like Java 9's Arrays.equals
-   * @see <a href="http://download.java.net/java/jdk9/docs/api/java/util/Arrays.html#equals-byte:A-int-int-byte:A-int-int-">Arrays.equals</a>
-   */
-  public static boolean equals(byte[] a, int aFromIndex, int aToIndex, byte[] b, int bFromIndex, int bToIndex) {
-    checkFromToIndex(aFromIndex, aToIndex, a.length);
-    checkFromToIndex(bFromIndex, bToIndex, b.length);
-    int aLen = aToIndex - aFromIndex;
-    int bLen = bToIndex - bFromIndex;
-    // lengths differ: cannot be equal
-    if (aLen != bLen) {
-      return false;
-    }
-    for (int i = 0; i < aLen; i++) {
-      if (a[i+aFromIndex] != b[i+bFromIndex]) {
-        return false;
-      }
-    }
-    return true;
-  }
-
-  // char[]
-
-  /**
-   * Behaves like Java 9's Arrays.mismatch
-   * @see <a href="http://download.java.net/java/jdk9/docs/api/java/util/Arrays.html#mismatch-char:A-int-int-char:A-int-int-">Arrays.mismatch</a>
-   */
-  public static int mismatch(char[] a, int aFromIndex, int aToIndex, char[] b, int bFromIndex, int bToIndex) {
-    checkFromToIndex(aFromIndex, aToIndex, a.length);
-    checkFromToIndex(bFromIndex, bToIndex, b.length);
-    int aLen = aToIndex - aFromIndex;
-    int bLen = bToIndex - bFromIndex;
-    int len = Math.min(aLen, bLen);
-    for (int i = 0; i < len; i++)
-      if (a[i+aFromIndex] != b[i+bFromIndex])
-        return i;
-    return aLen == bLen ? -1 : len;
-  }
-  
-  /**
-   * Behaves like Java 9's Arrays.compare
-   * @see <a href="http://download.java.net/java/jdk9/docs/api/java/util/Arrays.html#compare-char:A-int-int-char:A-int-int-">Arrays.compare</a>
-   */
-  public static int compare(char[] a, int aFromIndex, int aToIndex, char[] b, int bFromIndex, int bToIndex) {
-    checkFromToIndex(aFromIndex, aToIndex, a.length);
-    checkFromToIndex(bFromIndex, bToIndex, b.length);
-    int aLen = aToIndex - aFromIndex;
-    int bLen = bToIndex - bFromIndex;
-    int len = Math.min(aLen, bLen);
-    for (int i = 0; i < len; i++) {
-      int aInt = a[i+aFromIndex];
-      int bInt = b[i+bFromIndex];
-      if (aInt > bInt) {
-        return 1;
-      } else if (aInt < bInt) {
-        return -1;
-      }
-    }
-
-    // One is a prefix of the other, or, they are equal:
-    return aLen - bLen;
-  }
-  
-  /**
-   * Behaves like Java 9's Arrays.equals
-   * @see <a href="http://download.java.net/java/jdk9/docs/api/java/util/Arrays.html#equals-char:A-int-int-char:A-int-int-">Arrays.equals</a>
-   */
-  public static boolean equals(char[] a, int aFromIndex, int aToIndex, char[] b, int bFromIndex, int bToIndex) {
-    checkFromToIndex(aFromIndex, aToIndex, a.length);
-    checkFromToIndex(bFromIndex, bToIndex, b.length);
-    int aLen = aToIndex - aFromIndex;
-    int bLen = bToIndex - bFromIndex;
-    // lengths differ: cannot be equal
-    if (aLen != bLen) {
-      return false;
-    }
-    for (int i = 0; i < aLen; i++) {
-      if (a[i+aFromIndex] != b[i+bFromIndex]) {
-        return false;
-      }
-    }
-    return true;
-  }
-
-  // int[]
-  
-  /**
-   * Behaves like Java 9's Arrays.compare
-   * @see <a href="http://download.java.net/java/jdk9/docs/api/java/util/Arrays.html#compare-int:A-int-int-int:A-int-int-">Arrays.compare</a>
-   */
-  public static int compare(int[] a, int aFromIndex, int aToIndex, int[] b, int bFromIndex, int bToIndex) {
-    checkFromToIndex(aFromIndex, aToIndex, a.length);
-    checkFromToIndex(bFromIndex, bToIndex, b.length);
-    int aLen = aToIndex - aFromIndex;
-    int bLen = bToIndex - bFromIndex;
-    int len = Math.min(aLen, bLen);
-    for (int i = 0; i < len; i++) {
-      int aInt = a[i+aFromIndex];
-      int bInt = b[i+bFromIndex];
-      if (aInt > bInt) {
-        return 1;
-      } else if (aInt < bInt) {
-        return -1;
-      }
-    }
-
-    // One is a prefix of the other, or, they are equal:
-    return aLen - bLen;
-  }
-  
-  /**
-   * Behaves like Java 9's Arrays.equals
-   * @see <a href="http://download.java.net/java/jdk9/docs/api/java/util/Arrays.html#equals-int:A-int-int-int:A-int-int-">Arrays.equals</a>
-   */
-  public static boolean equals(int[] a, int aFromIndex, int aToIndex, int[] b, int bFromIndex, int bToIndex) {
-    checkFromToIndex(aFromIndex, aToIndex, a.length);
-    checkFromToIndex(bFromIndex, bToIndex, b.length);
-    int aLen = aToIndex - aFromIndex;
-    int bLen = bToIndex - bFromIndex;
-    // lengths differ: cannot be equal
-    if (aLen != bLen) {
-      return false;
-    }
-    for (int i = 0; i < aLen; i++) {
-      if (a[i+aFromIndex] != b[i+bFromIndex]) {
-        return false;
-      }
-    }
-    return true;
-  }
-  
-  // long[]
-  
-  /**
-   * Behaves like Java 9's Arrays.compare
-   * @see <a href="http://download.java.net/java/jdk9/docs/api/java/util/Arrays.html#compare-long:A-int-int-long:A-int-int-">Arrays.compare</a>
-   */
-  public static int compare(long[] a, int aFromIndex, int aToIndex, long[] b, int bFromIndex, int bToIndex) {
-    checkFromToIndex(aFromIndex, aToIndex, a.length);
-    checkFromToIndex(bFromIndex, bToIndex, b.length);
-    int aLen = aToIndex - aFromIndex;
-    int bLen = bToIndex - bFromIndex;
-    int len = Math.min(aLen, bLen);
-    for (int i = 0; i < len; i++) {
-      long aInt = a[i+aFromIndex];
-      long bInt = b[i+bFromIndex];
-      if (aInt > bInt) {
-        return 1;
-      } else if (aInt < bInt) {
-        return -1;
-      }
-    }
-
-    // One is a prefix of the other, or, they are equal:
-    return aLen - bLen;
-  }
-  
-  /**
-   * Behaves like Java 9's Arrays.equals
-   * @see <a href="http://download.java.net/java/jdk9/docs/api/java/util/Arrays.html#equals-long:A-int-int-long:A-int-int-">Arrays.equals</a>
-   */
-  public static boolean equals(long[] a, int aFromIndex, int aToIndex, long[] b, int bFromIndex, int bToIndex) {
-    checkFromToIndex(aFromIndex, aToIndex, a.length);
-    checkFromToIndex(bFromIndex, bToIndex, b.length);
-    int aLen = aToIndex - aFromIndex;
-    int bLen = bToIndex - bFromIndex;
-    // lengths differ: cannot be equal
-    if (aLen != bLen) {
-      return false;
-    }
-    for (int i = 0; i < aLen; i++) {
-      if (a[i+aFromIndex] != b[i+bFromIndex]) {
-        return false;
-      }
-    }
-    return true;
-  }
-  
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5f43dce1/lucene/core/src/java/org/apache/lucene/util/FutureObjects.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/util/FutureObjects.java b/lucene/core/src/java/org/apache/lucene/util/FutureObjects.java
deleted file mode 100644
index b8ad4d3..0000000
--- a/lucene/core/src/java/org/apache/lucene/util/FutureObjects.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.lucene.util;
-
-/**
- * Additional methods from Java 9's <a href="https://docs.oracle.com/javase/9/docs/api/java/util/Objects.html">
- * {@code java.util.Objects}</a>.
- * <p>
- * This class will be removed when Java 9 is minimum requirement.
- * Currently any bytecode is patched to use the Java 9 native
- * classes through MR-JAR (Multi-Release JAR) mechanism.
- * In Java 8 it will use THIS implementation.
- * Because of patching, inside the Java source files we always
- * refer to the Lucene implementations, but the final Lucene
- * JAR files will use the native Java 9 class names when executed
- * with Java 9.
- * @lucene.internal
- */
-public final class FutureObjects {
-  
-  private FutureObjects() {} // no instance
-
-  /**
-   * Behaves like Java 9's Objects.checkIndex
-   * @see <a href="http://download.java.net/java/jdk9/docs/api/java/util/Objects.html#checkIndex-int-int-">Objects.checkIndex</a>
-   */
-  public static int checkIndex(int index, int length) {
-    if (index < 0 || index >= length) {
-      throw new IndexOutOfBoundsException("Index " + index + " out-of-bounds for length " + length);
-    }
-    return index;
-  }
-  
-  /**
-   * Behaves like Java 9's Objects.checkFromToIndex
-   * @see <a href="http://download.java.net/java/jdk9/docs/api/java/util/Objects.html#checkFromToIndex-int-int-int-">Objects.checkFromToIndex</a>
-   */
-  public static int checkFromToIndex(int fromIndex, int toIndex, int length) {
-    if (fromIndex < 0 || fromIndex > toIndex || toIndex > length) {
-      throw new IndexOutOfBoundsException("Range [" + fromIndex + ", " + toIndex + ") out-of-bounds for length " + length);
-    }
-    return fromIndex;
-  }
-  
-  /**
-   * Behaves like Java 9's Objects.checkFromIndexSize
-   * @see <a href="http://download.java.net/java/jdk9/docs/api/java/util/Objects.html#checkFromIndexSize-int-int-int-">Objects.checkFromIndexSize</a>
-   */
-  public static int checkFromIndexSize(int fromIndex, int size, int length) {
-    int end = fromIndex + size;
-    if (fromIndex < 0 || fromIndex > end || end > length) {
-      throw new IndexOutOfBoundsException("Range [" + fromIndex + ", " + fromIndex + " + " + size + ") out-of-bounds for length " + length);
-    }
-    return fromIndex;
-  }
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5f43dce1/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..981210d 100644
--- a/lucene/core/src/java/org/apache/lucene/util/IntsRef.java
+++ b/lucene/core/src/java/org/apache/lucene/util/IntsRef.java
@@ -93,15 +93,45 @@ public final class IntsRef implements Comparable<IntsRef>, Cloneable {
   }
 
   public boolean intsEquals(IntsRef other) {
-    return FutureArrays.equals(this.ints, this.offset, this.offset + this.length, 
-                               other.ints, other.offset, other.offset + other.length);
+    if (length == other.length) {
+      int otherUpto = other.offset;
+      final int[] otherInts = other.ints;
+      final int end = offset + length;
+      for(int upto=offset;upto<end;upto++,otherUpto++) {
+        if (ints[upto] != otherInts[otherUpto]) {
+          return false;
+        }
+      }
+      return true;
+    } else {
+      return false;
+    }
   }
 
   /** Signed int order comparison */
   @Override
   public int compareTo(IntsRef other) {
-    return FutureArrays.compare(this.ints, this.offset, this.offset + this.length, 
-                                other.ints, other.offset, other.offset + other.length);
+    if (this == other) return 0;
+
+    final int[] aInts = this.ints;
+    int aUpto = this.offset;
+    final int[] bInts = other.ints;
+    int bUpto = other.offset;
+
+    final int aStop = aUpto + Math.min(this.length, other.length);
+
+    while(aUpto < aStop) {
+      int aInt = aInts[aUpto++];
+      int bInt = bInts[bUpto++];
+      if (aInt > bInt) {
+        return 1;
+      } else if (aInt < bInt) {
+        return -1;
+      }
+    }
+
+    // One is a prefix of the other, or, they are equal:
+    return this.length - other.length;
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5f43dce1/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..61b85cf 100644
--- a/lucene/core/src/java/org/apache/lucene/util/LongsRef.java
+++ b/lucene/core/src/java/org/apache/lucene/util/LongsRef.java
@@ -92,15 +92,45 @@ public final class LongsRef implements Comparable<LongsRef>, Cloneable {
   }
 
   public boolean longsEquals(LongsRef other) {
-    return FutureArrays.equals(this.longs, this.offset, this.offset + this.length, 
-                               other.longs, other.offset, other.offset + other.length);
+    if (length == other.length) {
+      int otherUpto = other.offset;
+      final long[] otherInts = other.longs;
+      final long end = offset + length;
+      for(int upto=offset; upto<end; upto++,otherUpto++) {
+        if (longs[upto] != otherInts[otherUpto]) {
+          return false;
+        }
+      }
+      return true;
+    } else {
+      return false;
+    }
   }
 
   /** Signed int order comparison */
   @Override
   public int compareTo(LongsRef other) {
-    return FutureArrays.compare(this.longs, this.offset, this.offset + this.length, 
-                                other.longs, other.offset, other.offset + other.length);
+    if (this == other) return 0;
+
+    final long[] aInts = this.longs;
+    int aUpto = this.offset;
+    final long[] bInts = other.longs;
+    int bUpto = other.offset;
+
+    final long aStop = aUpto + Math.min(this.length, other.length);
+
+    while(aUpto < aStop) {
+      long aInt = aInts[aUpto++];
+      long bInt = bInts[bUpto++];
+      if (aInt > bInt) {
+        return 1;
+      } else if (aInt < bInt) {
+        return -1;
+      }
+    }
+
+    // One is a prefix of the other, or, they are equal:
+    return this.length - other.length;
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5f43dce1/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..6d958ba 100644
--- a/lucene/core/src/java/org/apache/lucene/util/StringHelper.java
+++ b/lucene/core/src/java/org/apache/lucene/util/StringHelper.java
@@ -34,19 +34,21 @@ public abstract class StringHelper {
   /**
    * Compares two {@link BytesRef}, element by element, and returns the
    * number of elements common to both arrays (from the start of each).
-   * This method assumes currentTerm comes after priorTerm.
    *
-   * @param priorTerm The first {@link BytesRef} to compare
-   * @param currentTerm The second {@link BytesRef} to compare
+   * @param left The first {@link BytesRef} to compare
+   * @param right The second {@link BytesRef} to compare
    * @return The number of common elements (from the start of each).
    */
-  public static int bytesDifference(BytesRef priorTerm, BytesRef currentTerm) {
-    int mismatch = FutureArrays.mismatch(priorTerm.bytes, priorTerm.offset, priorTerm.offset + priorTerm.length, 
-                                         currentTerm.bytes, currentTerm.offset, currentTerm.offset + currentTerm.length);
-    if (mismatch < 0) {
-      throw new IllegalArgumentException("terms out of order: priorTerm=" + priorTerm + ",currentTerm=" + currentTerm);
-    }
-    return mismatch;
+  public static int bytesDifference(BytesRef left, BytesRef right) {
+    int len = left.length < right.length ? left.length : right.length;
+    final byte[] bytesLeft = left.bytes;
+    final int offLeft = left.offset;
+    byte[] bytesRight = right.bytes;
+    final int offRight = right.offset;
+    for (int i = 0; i < len; i++)
+      if (bytesLeft[i+offLeft] != bytesRight[i+offRight])
+        return i;
+    return len;
   }
   
   /** 
@@ -55,7 +57,15 @@ public abstract class StringHelper {
    * This method assumes currentTerm comes after priorTerm.
    */
   public static int sortKeyLength(final BytesRef priorTerm, final BytesRef currentTerm) {
-    return bytesDifference(priorTerm, currentTerm) + 1;
+    final int currentTermOffset = currentTerm.offset;
+    final int priorTermOffset = priorTerm.offset;
+    final int limit = Math.min(priorTerm.length, currentTerm.length);
+    for (int i = 0; i < limit; i++) {
+      if (priorTerm.bytes[priorTermOffset+i] != currentTerm.bytes[currentTermOffset+i]) {
+        return i+1;
+      }
+    }
+    return Math.min(1+priorTerm.length, currentTerm.length);
   }
 
   private StringHelper() {
@@ -73,12 +83,17 @@ public abstract class StringHelper {
    *         Otherwise <code>false</code>.
    */
   public static boolean startsWith(byte[] ref, BytesRef prefix) {
-    // not long enough to start with the prefix
     if (ref.length < prefix.length) {
       return false;
     }
-    return FutureArrays.equals(ref, 0, prefix.length,
-                               prefix.bytes, prefix.offset, prefix.offset + prefix.length);
+
+    for(int i=0;i<prefix.length;i++) {
+      if (ref[i] != prefix.bytes[prefix.offset+i]) {
+        return false;
+      }
+    }
+
+    return true;
   }
 
   /**
@@ -93,12 +108,7 @@ public abstract class StringHelper {
    *         Otherwise <code>false</code>.
    */
   public static boolean startsWith(BytesRef ref, BytesRef prefix) {
-    // not long enough to start with the prefix
-    if (ref.length < prefix.length) {
-      return false;
-    }
-    return FutureArrays.equals(ref.bytes, ref.offset, ref.offset + prefix.length, 
-                               prefix.bytes, prefix.offset, prefix.offset + prefix.length);
+    return sliceEquals(ref, prefix, 0);
   }
 
   /**
@@ -113,13 +123,24 @@ public abstract class StringHelper {
    *         Otherwise <code>false</code>.
    */
   public static boolean endsWith(BytesRef ref, BytesRef suffix) {
-    int startAt = ref.length - suffix.length;
-    // not long enough to start with the suffix
-    if (startAt < 0) {
+    return sliceEquals(ref, suffix, ref.length - suffix.length);
+  }
+
+  private static boolean sliceEquals(BytesRef sliceToTest, BytesRef other, int pos) {
+    if (pos < 0 || sliceToTest.length - pos < other.length) {
       return false;
     }
-    return FutureArrays.equals(ref.bytes, ref.offset + startAt, ref.offset + startAt + suffix.length,
-                               suffix.bytes, suffix.offset, suffix.offset + suffix.length);
+    int i = sliceToTest.offset + pos;
+    int j = other.offset;
+    final int k = other.offset + other.length;
+    
+    while (j < k) {
+      if (sliceToTest.bytes[i++] != other.bytes[j++]) {
+        return false;
+      }
+    }
+    
+    return true;
   }
 
   /** Pass this as the seed to {@link #murmurhash3_x86_32}. */
@@ -354,12 +375,16 @@ public abstract class StringHelper {
 
   /** Compares a fixed length slice of two byte arrays interpreted as
    *  big-endian unsigned values.  Returns positive int if a &gt; b,
-   *  negative int if a &lt; b and 0 if a == b 
-   *  
-   * @deprecated Use FutureArrays.compareUnsigned instead.
-   */
-  @Deprecated
+   *  negative int if a &lt; b and 0 if a == b */
   public static int compare(int count, byte[] a, int aOffset, byte[] b, int bOffset) {
-    return FutureArrays.compareUnsigned(a, aOffset, aOffset + count, b, bOffset, bOffset + count);
+    // TODO: dedup this w/ BytesRef.compareTo?
+    for(int i=0;i<count;i++) {
+      int cmp = (a[aOffset+i]&0xff) - (b[bOffset+i]&0xff);
+      if (cmp != 0) {
+        return cmp;
+      }
+    }
+
+    return 0;
   }
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5f43dce1/lucene/core/src/java/org/apache/lucene/util/automaton/Automaton.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/util/automaton/Automaton.java b/lucene/core/src/java/org/apache/lucene/util/automaton/Automaton.java
index 9ef31e8..e4a5bd9 100644
--- a/lucene/core/src/java/org/apache/lucene/util/automaton/Automaton.java
+++ b/lucene/core/src/java/org/apache/lucene/util/automaton/Automaton.java
@@ -27,7 +27,6 @@ import java.util.Set;
 
 import org.apache.lucene.util.Accountable;
 import org.apache.lucene.util.ArrayUtil;
-import org.apache.lucene.util.FutureObjects;
 import org.apache.lucene.util.InPlaceMergeSorter;
 import org.apache.lucene.util.RamUsageEstimator;
 import org.apache.lucene.util.Sorter;
@@ -115,8 +114,14 @@ public class Automaton implements Accountable {
 
   /** Set or clear this state as an accept state. */
   public void setAccept(int state, boolean accept) {
-    FutureObjects.checkIndex(state, getNumStates());
-    isAccept.set(state, accept);
+    if (state >= getNumStates()) {
+      throw new IllegalArgumentException("state=" + state + " is out of bounds (numStates=" + getNumStates() + ")");
+    }
+    if (accept) {
+      isAccept.set(state);
+    } else {
+      isAccept.clear(state);
+    }
   }
 
   /** Sugar to get all transitions for all states.  This is
@@ -156,9 +161,12 @@ public class Automaton implements Accountable {
   public void addTransition(int source, int dest, int min, int max) {
     assert nextTransition%3 == 0;
 
-    int bounds = nextState/2;
-    FutureObjects.checkIndex(source, bounds);
-    FutureObjects.checkIndex(dest, bounds);
+    if (source >= nextState/2) {
+      throw new IllegalArgumentException("source=" + source + " is out of bounds (maxState is " + (nextState/2-1) + ")");
+    }
+    if (dest >= nextState/2) {
+      throw new IllegalArgumentException("dest=" + dest + " is out of bounds (max state is " + (nextState/2-1) + ")");
+    }
 
     growTransitions();
     if (curState != source) {
@@ -834,7 +842,10 @@ public class Automaton implements Accountable {
 
     /** Set or clear this state as an accept state. */
     public void setAccept(int state, boolean accept) {
-      FutureObjects.checkIndex(state, getNumStates());      
+      if (state >= getNumStates()) {
+        throw new IllegalArgumentException("state=" + state + " is out of bounds (numStates=" + getNumStates() + ")");
+      }
+      
       this.isAccept.set(state, accept);
     }
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5f43dce1/lucene/core/src/test/org/apache/lucene/analysis/tokenattributes/TestCharTermAttributeImpl.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/analysis/tokenattributes/TestCharTermAttributeImpl.java b/lucene/core/src/test/org/apache/lucene/analysis/tokenattributes/TestCharTermAttributeImpl.java
index 9bf3621..3082129 100644
--- a/lucene/core/src/test/org/apache/lucene/analysis/tokenattributes/TestCharTermAttributeImpl.java
+++ b/lucene/core/src/test/org/apache/lucene/analysis/tokenattributes/TestCharTermAttributeImpl.java
@@ -46,9 +46,10 @@ public class TestCharTermAttributeImpl extends LuceneTestCase {
     CharTermAttributeImpl t = new CharTermAttributeImpl();
     char[] content = "hello".toCharArray();
     t.copyBuffer(content, 0, content.length);
-    expectThrows(IndexOutOfBoundsException.class, () -> {
+    IllegalArgumentException expected = expectThrows(IllegalArgumentException.class, () -> {
       t.setLength(-1);
     });
+    assertTrue(expected.getMessage().contains("must not be negative"));
   }
 
   public void testGrow() {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5f43dce1/lucene/core/src/test/org/apache/lucene/util/TestArrayUtil.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/util/TestArrayUtil.java b/lucene/core/src/test/org/apache/lucene/util/TestArrayUtil.java
index 0cda337..79f4cbd 100644
--- a/lucene/core/src/test/org/apache/lucene/util/TestArrayUtil.java
+++ b/lucene/core/src/test/org/apache/lucene/util/TestArrayUtil.java
@@ -16,6 +16,8 @@
  */
 package org.apache.lucene.util;
 
+
+import java.nio.charset.StandardCharsets;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.Comparator;
@@ -105,6 +107,20 @@ public class TestArrayUtil extends LuceneTestCase {
     test = ArrayUtil.parseInt("foo 1923 bar".toCharArray(), 4, 4);
     assertTrue(test + " does not equal: " + 1923, test == 1923);
   }
+
+  public void testSliceEquals() {
+    String left = "this is equal";
+    String right = left;
+    byte[] leftChars = left.getBytes(StandardCharsets.UTF_8);
+    byte[] rightChars = right.getBytes(StandardCharsets.UTF_8);
+    assertTrue(left + " does not equal: " + right, ArrayUtil.equals(leftChars, 0, rightChars, 0, left.length()));
+    
+    assertFalse(left + " does not equal: " + right, ArrayUtil.equals(leftChars, 1, rightChars, 0, left.length()));
+    assertFalse(left + " does not equal: " + right, ArrayUtil.equals(leftChars, 1, rightChars, 2, left.length()));
+
+    assertFalse(left + " does not equal: " + right, ArrayUtil.equals(leftChars, 25, rightChars, 0, left.length()));
+    assertFalse(left + " does not equal: " + right, ArrayUtil.equals(leftChars, 12, rightChars, 0, left.length()));
+  }
   
   private Integer[] createRandomArray(int maxSize) {
     final Random rnd = random();