diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderUtils.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderUtils.java
index ceb8fa81fb0eeef580276ffaa2378871bf2e907c..5b319ad906d99f5baa490ef82be510edcaece409 100644
--- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderUtils.java
+++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderUtils.java
@@ -342,13 +342,11 @@ public final class BinaryDictDecoderUtils {
      * @param formatOptions file format options.
      * @return the word with its frequency, as a weighted string.
      */
-    /* package for tests */ static WeightedString getWordAtPosition(
-            final Ver3DictDecoder dictDecoder, final int headerSize, final int pos,
-            final FormatOptions formatOptions) {
-        final DictBuffer dictBuffer = dictDecoder.getDictBuffer();
+    /* package for tests */ static WeightedString getWordAtPosition(final DictDecoder dictDecoder,
+            final int headerSize, final int pos, final FormatOptions formatOptions) {
         final WeightedString result;
-        final int originalPos = dictBuffer.position();
-        dictBuffer.position(pos);
+        final int originalPos = dictDecoder.getPosition();
+        dictDecoder.setPosition(pos);
 
         if (BinaryDictIOUtils.supportsDynamicUpdate(formatOptions)) {
             result = getWordAtPositionWithParentAddress(dictDecoder, pos, formatOptions);
@@ -357,14 +355,13 @@ public final class BinaryDictDecoderUtils {
                     formatOptions);
         }
 
-        dictBuffer.position(originalPos);
+        dictDecoder.setPosition(originalPos);
         return result;
     }
 
     @SuppressWarnings("unused")
-    private static WeightedString getWordAtPositionWithParentAddress(
-            final Ver3DictDecoder dictDecoder, final int pos, final FormatOptions options) {
-        final DictBuffer dictBuffer = dictDecoder.getDictBuffer();
+    private static WeightedString getWordAtPositionWithParentAddress(final DictDecoder dictDecoder,
+            final int pos, final FormatOptions options) {
         int currentPos = pos;
         int frequency = Integer.MIN_VALUE;
         final StringBuilder builder = new StringBuilder();
@@ -373,7 +370,7 @@ public final class BinaryDictDecoderUtils {
             PtNodeInfo currentInfo;
             int loopCounter = 0;
             do {
-                dictBuffer.position(currentPos);
+                dictDecoder.setPosition(currentPos);
                 currentInfo = dictDecoder.readPtNode(currentPos, options);
                 if (BinaryDictIOUtils.isMovedPtNode(currentInfo.mFlags, options)) {
                     currentPos = currentInfo.mParentAddress + currentInfo.mOriginalAddress;
@@ -392,11 +389,10 @@ public final class BinaryDictDecoderUtils {
     }
 
     private static WeightedString getWordAtPositionWithoutParentAddress(
-            final Ver3DictDecoder dictDecoder, final int headerSize, final int pos,
+            final DictDecoder dictDecoder, final int headerSize, final int pos,
             final FormatOptions options) {
-        final DictBuffer dictBuffer = dictDecoder.getDictBuffer();
-        dictBuffer.position(headerSize);
-        final int count = readPtNodeCount(dictBuffer);
+        dictDecoder.setPosition(headerSize);
+        final int count = dictDecoder.readPtNodeCount();
         int groupPos = headerSize + BinaryDictIOUtils.getPtNodeCountSize(count);
         final StringBuilder builder = new StringBuilder();
         WeightedString result = null;
@@ -414,8 +410,8 @@ public final class BinaryDictDecoderUtils {
                 if (info.mChildrenAddress > pos) {
                     if (null == last) continue;
                     builder.append(new String(last.mCharacters, 0, last.mCharacters.length));
-                    dictBuffer.position(last.mChildrenAddress);
-                    i = readPtNodeCount(dictBuffer);
+                    dictDecoder.setPosition(last.mChildrenAddress);
+                    i = dictDecoder.readPtNodeCount();
                     groupPos = last.mChildrenAddress + BinaryDictIOUtils.getPtNodeCountSize(i);
                     last = null;
                     continue;
@@ -424,8 +420,8 @@ public final class BinaryDictDecoderUtils {
             }
             if (0 == i && BinaryDictIOUtils.hasChildrenAddress(last.mChildrenAddress)) {
                 builder.append(new String(last.mCharacters, 0, last.mCharacters.length));
-                dictBuffer.position(last.mChildrenAddress);
-                i = readPtNodeCount(dictBuffer);
+                dictDecoder.setPosition(last.mChildrenAddress);
+                i = dictDecoder.readPtNodeCount();
                 groupPos = last.mChildrenAddress + BinaryDictIOUtils.getPtNodeCountSize(i);
                 last = null;
                 continue;
@@ -449,17 +445,16 @@ public final class BinaryDictDecoderUtils {
      * @param options file format options.
      * @return the read node array with all his children already read.
      */
-    private static PtNodeArray readNodeArray(final Ver3DictDecoder dictDecoder,
+    private static PtNodeArray readNodeArray(final DictDecoder dictDecoder,
             final int headerSize, final Map<Integer, PtNodeArray> reverseNodeArrayMap,
             final Map<Integer, PtNode> reversePtNodeMap, final FormatOptions options)
             throws IOException {
-        final DictBuffer dictBuffer = dictDecoder.getDictBuffer();
         final ArrayList<PtNode> nodeArrayContents = new ArrayList<PtNode>();
-        final int nodeArrayOriginPos = dictBuffer.position();
+        final int nodeArrayOriginPos = dictDecoder.getPosition();
 
         do { // Scan the linked-list node.
-            final int nodeArrayHeadPos = dictBuffer.position();
-            final int count = readPtNodeCount(dictBuffer);
+            final int nodeArrayHeadPos = dictDecoder.getPosition();
+            final int count = dictDecoder.readPtNodeCount();
             int groupOffsetPos = nodeArrayHeadPos + BinaryDictIOUtils.getPtNodeCountSize(count);
             for (int i = count; i > 0; --i) { // Scan the array of PtNode.
                 PtNodeInfo info = dictDecoder.readPtNode(groupOffsetPos, options);
@@ -480,11 +475,11 @@ public final class BinaryDictDecoderUtils {
                 if (BinaryDictIOUtils.hasChildrenAddress(info.mChildrenAddress)) {
                     PtNodeArray children = reverseNodeArrayMap.get(info.mChildrenAddress);
                     if (null == children) {
-                        final int currentPosition = dictBuffer.position();
-                        dictBuffer.position(info.mChildrenAddress);
+                        final int currentPosition = dictDecoder.getPosition();
+                        dictDecoder.setPosition(info.mChildrenAddress);
                         children = readNodeArray(dictDecoder, headerSize, reverseNodeArrayMap,
                                 reversePtNodeMap, options);
-                        dictBuffer.position(currentPosition);
+                        dictDecoder.setPosition(currentPosition);
                     }
                     nodeArrayContents.add(
                             new PtNode(info.mCharacters, shortcutTargets, bigrams,
@@ -503,15 +498,10 @@ public final class BinaryDictDecoderUtils {
 
             // reach the end of the array.
             if (options.mSupportsDynamicUpdate) {
-                final int nextAddress = dictBuffer.readUnsignedInt24();
-                if (nextAddress >= 0 && nextAddress < dictBuffer.limit()) {
-                    dictBuffer.position(nextAddress);
-                } else {
-                    break;
-                }
+                final boolean hasValidForwardLink = dictDecoder.readForwardLinkAndAdvancePosition();
+                if (!hasValidForwardLink) break;
             }
-        } while (options.mSupportsDynamicUpdate &&
-                dictBuffer.position() != FormatSpec.NO_FORWARD_LINK_ADDRESS);
+        } while (options.mSupportsDynamicUpdate && dictDecoder.hasNextPtNodeArray());
 
         final PtNodeArray nodeArray = new PtNodeArray(nodeArrayContents);
         nodeArray.mCachedAddressBeforeUpdate = nodeArrayOriginPos;
diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java
index 106f025199726232af6cbdea5a97cb7a44ee7bd4..5cb40f30c8098ecd929db4fdc7d2e9e5d61eefd5 100644
--- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java
+++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java
@@ -61,12 +61,11 @@ public final class BinaryDictIOUtils {
     /**
      * Retrieves all node arrays without recursive call.
      */
-    private static void readUnigramsAndBigramsBinaryInner(
-            final Ver3DictDecoder dictDecoder, final int headerSize,
-            final Map<Integer, String> words, final Map<Integer, Integer> frequencies,
+    private static void readUnigramsAndBigramsBinaryInner(final DictDecoder dictDecoder,
+            final int headerSize, final Map<Integer, String> words,
+            final Map<Integer, Integer> frequencies,
             final Map<Integer, ArrayList<PendingAttribute>> bigrams,
             final FormatOptions formatOptions) {
-        final DictBuffer dictBuffer = dictDecoder.getDictBuffer();
         int[] pushedChars = new int[FormatSpec.MAX_WORD_LENGTH + 1];
 
         Stack<Position> stack = new Stack<Position>();
@@ -83,11 +82,11 @@ public final class BinaryDictIOUtils {
                         p.mNumOfPtNode + ", position=" + p.mPosition + ", length=" + p.mLength);
             }
 
-            if (dictBuffer.position() != p.mAddress) dictBuffer.position(p.mAddress);
+            if (dictDecoder.getPosition() != p.mAddress) dictDecoder.setPosition(p.mAddress);
             if (index != p.mLength) index = p.mLength;
 
             if (p.mNumOfPtNode == Position.NOT_READ_PTNODE_COUNT) {
-                p.mNumOfPtNode = BinaryDictDecoderUtils.readPtNodeCount(dictBuffer);
+                p.mNumOfPtNode = dictDecoder.readPtNodeCount();
                 p.mAddress += getPtNodeCountSize(p.mNumOfPtNode);
                 p.mPosition = 0;
             }
@@ -114,11 +113,12 @@ public final class BinaryDictIOUtils {
 
             if (p.mPosition == p.mNumOfPtNode) {
                 if (formatOptions.mSupportsDynamicUpdate) {
-                    final int forwardLinkAddress = dictBuffer.readUnsignedInt24();
-                    if (forwardLinkAddress != FormatSpec.NO_FORWARD_LINK_ADDRESS) {
+                    final boolean hasValidForwardLinkAddress =
+                            dictDecoder.readForwardLinkAndAdvancePosition();
+                    if (hasValidForwardLinkAddress && dictDecoder.hasNextPtNodeArray()) {
                         // The node array has a forward link.
                         p.mNumOfPtNode = Position.NOT_READ_PTNODE_COUNT;
-                        p.mAddress = forwardLinkAddress;
+                        p.mAddress = dictDecoder.getPosition();
                     } else {
                         stack.pop();
                     }
@@ -127,7 +127,7 @@ public final class BinaryDictIOUtils {
                 }
             } else {
                 // The Ptnode array has more PtNodes.
-                p.mAddress = dictBuffer.position();
+                p.mAddress = dictDecoder.getPosition();
             }
 
             if (!isMovedPtNode && hasChildrenAddress(info.mChildrenAddress)) {
@@ -171,9 +171,8 @@ public final class BinaryDictIOUtils {
     @UsedForTesting
     /* package */ static int getTerminalPosition(final Ver3DictDecoder dictDecoder,
             final String word) throws IOException, UnsupportedFormatException {
-        final DictBuffer dictBuffer = dictDecoder.getDictBuffer();
         if (word == null) return FormatSpec.NOT_VALID_WORD;
-        if (dictBuffer.position() != 0) dictBuffer.position(0);
+        dictDecoder.setPosition(0);
 
         final FileHeader header = dictDecoder.readHeader();
         int wordPos = 0;
@@ -182,10 +181,10 @@ public final class BinaryDictIOUtils {
             if (wordPos >= wordLen) return FormatSpec.NOT_VALID_WORD;
 
             do {
-                final int ptNodeCount = BinaryDictDecoderUtils.readPtNodeCount(dictBuffer);
+                final int ptNodeCount = dictDecoder.readPtNodeCount();
                 boolean foundNextPtNode = false;
                 for (int i = 0; i < ptNodeCount; ++i) {
-                    final int ptNodePos = dictBuffer.position();
+                    final int ptNodePos = dictDecoder.getPosition();
                     final PtNodeInfo currentInfo = dictDecoder.readPtNode(ptNodePos,
                             header.mFormatOptions);
                     final boolean isMovedNode = isMovedPtNode(currentInfo.mFlags,
@@ -219,7 +218,7 @@ public final class BinaryDictIOUtils {
                             return FormatSpec.NOT_VALID_WORD;
                         }
                         foundNextPtNode = true;
-                        dictBuffer.position(currentInfo.mChildrenAddress);
+                        dictDecoder.setPosition(currentInfo.mChildrenAddress);
                         break;
                     }
                 }
@@ -233,11 +232,11 @@ public final class BinaryDictIOUtils {
                     return FormatSpec.NOT_VALID_WORD;
                 }
 
-                final int forwardLinkAddress = dictBuffer.readUnsignedInt24();
-                if (forwardLinkAddress == FormatSpec.NO_FORWARD_LINK_ADDRESS) {
+                final boolean hasValidForwardLinkAddress =
+                        dictDecoder.readForwardLinkAndAdvancePosition();
+                if (!hasValidForwardLinkAddress || !dictDecoder.hasNextPtNodeArray()) {
                     return FormatSpec.NOT_VALID_WORD;
                 }
-                dictBuffer.position(forwardLinkAddress);
             } while(true);
         }
         return FormatSpec.NOT_VALID_WORD;
diff --git a/java/src/com/android/inputmethod/latin/makedict/DictDecoder.java b/java/src/com/android/inputmethod/latin/makedict/DictDecoder.java
index 64638fd987816c27cff4f2f9ef529e1bd0fb2254..5e398bd41a70733d7cd0ad6bf9988c219071313e 100644
--- a/java/src/com/android/inputmethod/latin/makedict/DictDecoder.java
+++ b/java/src/com/android/inputmethod/latin/makedict/DictDecoder.java
@@ -91,6 +91,33 @@ public interface DictDecoder {
             final TreeMap<Integer, ArrayList<PendingAttribute>> bigrams)
             throws IOException, UnsupportedFormatException;
 
+    /**
+     * Sets the position of the buffer to the given value.
+     *
+     * @param newPos the new position
+     */
+    public void setPosition(final int newPos);
+
+    /**
+     * Gets the position of the buffer.
+     *
+     * @return the position
+     */
+    public int getPosition();
+
+    /**
+     * Reads and returns the PtNode count out of a buffer and forwards the pointer.
+     */
+    public int readPtNodeCount();
+
+    /**
+     * Reads the forward link and advances the position.
+     *
+     * @return if this method advances the position then true else false.
+     */
+    public boolean readForwardLinkAndAdvancePosition();
+    public boolean hasNextPtNodeArray();
+
     // Flags for DictionaryBufferFactory.
     public static final int USE_READONLY_BYTEBUFFER = 0x01000000;
     public static final int USE_BYTEARRAY = 0x02000000;
diff --git a/java/src/com/android/inputmethod/latin/makedict/Ver3DictDecoder.java b/java/src/com/android/inputmethod/latin/makedict/Ver3DictDecoder.java
index b98aa0f607a88c3992a1e1b1014fc5aedf1d5184..6dff9b6d2b38e40c7b3c0b42d1c613a376a4324b 100644
--- a/java/src/com/android/inputmethod/latin/makedict/Ver3DictDecoder.java
+++ b/java/src/com/android/inputmethod/latin/makedict/Ver3DictDecoder.java
@@ -348,4 +348,33 @@ public class Ver3DictDecoder implements DictDecoder {
         BinaryDictIOUtils.readUnigramsAndBigramsBinary(this, words, frequencies, bigrams);
     }
 
+    @Override
+    public void setPosition(int newPos) {
+        mDictBuffer.position(newPos);
+    }
+
+    @Override
+    public int getPosition() {
+        return mDictBuffer.position();
+    }
+
+    @Override
+    public int readPtNodeCount() {
+        return BinaryDictDecoderUtils.readPtNodeCount(mDictBuffer);
+    }
+
+    @Override
+    public boolean readForwardLinkAndAdvancePosition() {
+        final int nextAddress = mDictBuffer.readUnsignedInt24();
+        if (nextAddress >= 0 && nextAddress < mDictBuffer.limit()) {
+            mDictBuffer.position(nextAddress);
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public boolean hasNextPtNodeArray() {
+        return mDictBuffer.position() != FormatSpec.NO_FORWARD_LINK_ADDRESS;
+    }
 }