diff --git a/java/com/google/flatbuffers/ByteBufferUtil.java b/java/com/google/flatbuffers/ByteBufferUtil.java
new file mode 100644
index 0000000..624dc4e
--- /dev/null
+++ b/java/com/google/flatbuffers/ByteBufferUtil.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2017 Google Inc. All rights reserved.
+ *
+ * Licensed 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 com.google.flatbuffers;
+
+import static com.google.flatbuffers.Constants.*;
+
+import java.nio.ByteBuffer;
+
+/// @file
+/// @addtogroup flatbuffers_java_api
+/// @{
+
+/**
+ * Class that collects utility functions around `ByteBuffer`.
+ */
+public class ByteBufferUtil {
+
+	/**
+     * Extract the size prefix from a `ByteBuffer`.
+     * 
+     * @param bb a size-prefixed buffer
+     * @return the size prefix
+     */
+    public static int getSizePrefix(ByteBuffer bb) {
+        return bb.getInt(bb.position());
+    }
+
+	/**
+     * Create a duplicate of a size-prefixed `ByteBuffer` that has its position
+     * advanced just past the size prefix.
+     * 
+     * @param bb a size-prefixed buffer
+     * @return a new buffer on the same underlying data that has skipped the
+     *         size prefix
+     */
+    public static ByteBuffer removeSizePrefix(ByteBuffer bb) {
+        ByteBuffer s = bb.duplicate();
+        s.position(s.position() + SIZE_PREFIX_LENGTH);
+        return s;
+    }
+
+}
+
+/// @}
diff --git a/java/com/google/flatbuffers/Constants.java b/java/com/google/flatbuffers/Constants.java
new file mode 100644
index 0000000..e974a80
--- /dev/null
+++ b/java/com/google/flatbuffers/Constants.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2014 Google Inc. All rights reserved.
+ *
+ * Licensed 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 com.google.flatbuffers;
+
+/// @cond FLATBUFFERS_INTERNAL
+
+/**
+ * Class that holds shared constants
+ */
+public class Constants {
+    // Java doesn't seem to have these.
+    /** The number of bytes in an `byte`. */
+    static final int SIZEOF_BYTE = 1;
+    /** The number of bytes in a `short`. */
+    static final int SIZEOF_SHORT = 2;
+    /** The number of bytes in an `int`. */
+    static final int SIZEOF_INT = 4;
+    /** The number of bytes in an `float`. */
+    static final int SIZEOF_FLOAT = 4;
+    /** The number of bytes in an `long`. */
+    static final int SIZEOF_LONG = 8;
+    /** The number of bytes in an `double`. */
+    static final int SIZEOF_DOUBLE = 8;
+    /** The number of bytes in a file identifier. */
+    static final int FILE_IDENTIFIER_LENGTH = 4;
+    /** The number of bytes in a size prefix. */
+    public static final int SIZE_PREFIX_LENGTH = 4;
+    /** A version identifier to force a compile error if someone
+    accidentally tries to build generated code with a runtime of
+    two mismatched version. Versions need to always match, as
+    the runtime and generated code are modified in sync.
+    Changes to the Java implementation need to be sure to change
+    the version here and in the code generator on every possible
+    incompatible change */
+    public static void FLATBUFFERS_1_11_1() {}
+}
+
+/// @endcond
diff --git a/java/com/google/flatbuffers/FlatBufferBuilder.java b/java/com/google/flatbuffers/FlatBufferBuilder.java
new file mode 100644
index 0000000..f224610
--- /dev/null
+++ b/java/com/google/flatbuffers/FlatBufferBuilder.java
@@ -0,0 +1,1012 @@
+/*
+ * Copyright 2014 Google Inc. All rights reserved.
+ *
+ * Licensed 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 com.google.flatbuffers;
+
+import static com.google.flatbuffers.Constants.*;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.*;
+import java.util.Arrays;
+
+/// @file
+/// @addtogroup flatbuffers_java_api
+/// @{
+
+/**
+ * Class that helps you build a FlatBuffer.  See the section
+ * "Use in Java/C#" in the main FlatBuffers documentation.
+ */
+public class FlatBufferBuilder {
+    /// @cond FLATBUFFERS_INTERNAL
+    ByteBuffer bb;                  // Where we construct the FlatBuffer.
+    int space;                      // Remaining space in the ByteBuffer.
+    int minalign = 1;               // Minimum alignment encountered so far.
+    int[] vtable = null;            // The vtable for the current table.
+    int vtable_in_use = 0;          // The amount of fields we're actually using.
+    boolean nested = false;         // Whether we are currently serializing a table.
+    boolean finished = false;       // Whether the buffer is finished.
+    int object_start;               // Starting offset of the current struct/table.
+    int[] vtables = new int[16];    // List of offsets of all vtables.
+    int num_vtables = 0;            // Number of entries in `vtables` in use.
+    int vector_num_elems = 0;       // For the current vector being built.
+    boolean force_defaults = false; // False omits default values from the serialized data.
+    ByteBufferFactory bb_factory;   // Factory for allocating the internal buffer
+    final Utf8 utf8;                // UTF-8 encoder to use
+    /// @endcond
+
+    /**
+     * Start with a buffer of size `initial_size`, then grow as required.
+     *
+     * @param initial_size The initial size of the internal buffer to use.
+     * @param bb_factory The factory to be used for allocating the internal buffer
+     */
+    public FlatBufferBuilder(int initial_size, ByteBufferFactory bb_factory) {
+        this(initial_size, bb_factory, null, Utf8.getDefault());
+    }
+
+    /**
+     * Start with a buffer of size `initial_size`, then grow as required.
+     *
+     * @param initial_size The initial size of the internal buffer to use.
+     * @param bb_factory The factory to be used for allocating the internal buffer
+     * @param existing_bb The byte buffer to reuse.
+     * @param utf8 The Utf8 codec
+     */
+    public FlatBufferBuilder(int initial_size, ByteBufferFactory bb_factory,
+                             ByteBuffer existing_bb, Utf8 utf8) {
+        if (initial_size <= 0) {
+          initial_size = 1;
+        }
+        space = initial_size;
+        this.bb_factory = bb_factory;
+        if (existing_bb != null) {
+          bb = existing_bb;
+          bb.clear();
+          bb.order(ByteOrder.LITTLE_ENDIAN);
+        } else {
+          bb = bb_factory.newByteBuffer(initial_size);
+        }
+        this.utf8 = utf8;
+    }
+
+   /**
+    * Start with a buffer of size `initial_size`, then grow as required.
+    *
+    * @param initial_size The initial size of the internal buffer to use.
+    */
+    public FlatBufferBuilder(int initial_size) {
+        this(initial_size, HeapByteBufferFactory.INSTANCE, null, Utf8.getDefault());
+    }
+
+    /**
+     * Start with a buffer of 1KiB, then grow as required.
+     */
+    public FlatBufferBuilder() {
+        this(1024);
+    }
+
+    /**
+     * Alternative constructor allowing reuse of {@link ByteBuffer}s.  The builder
+     * can still grow the buffer as necessary.  User classes should make sure
+     * to call {@link #dataBuffer()} to obtain the resulting encoded message.
+     *
+     * @param existing_bb The byte buffer to reuse.
+     * @param bb_factory The factory to be used for allocating a new internal buffer if
+     *                   the existing buffer needs to grow
+     */
+    public FlatBufferBuilder(ByteBuffer existing_bb, ByteBufferFactory bb_factory) {
+        this(existing_bb.capacity(), bb_factory, existing_bb, Utf8.getDefault());
+    }
+
+    /**
+     * Alternative constructor allowing reuse of {@link ByteBuffer}s.  The builder
+     * can still grow the buffer as necessary.  User classes should make sure
+     * to call {@link #dataBuffer()} to obtain the resulting encoded message.
+     *
+     * @param existing_bb The byte buffer to reuse.
+     */
+    public FlatBufferBuilder(ByteBuffer existing_bb) {
+        this(existing_bb, new HeapByteBufferFactory());
+    }
+
+    /**
+     * Alternative initializer that allows reusing this object on an existing
+     * `ByteBuffer`. This method resets the builder's internal state, but keeps
+     * objects that have been allocated for temporary storage.
+     *
+     * @param existing_bb The byte buffer to reuse.
+     * @param bb_factory The factory to be used for allocating a new internal buffer if
+     *                   the existing buffer needs to grow
+     * @return Returns `this`.
+     */
+    public FlatBufferBuilder init(ByteBuffer existing_bb, ByteBufferFactory bb_factory){
+        this.bb_factory = bb_factory;
+        bb = existing_bb;
+        bb.clear();
+        bb.order(ByteOrder.LITTLE_ENDIAN);
+        minalign = 1;
+        space = bb.capacity();
+        vtable_in_use = 0;
+        nested = false;
+        finished = false;
+        object_start = 0;
+        num_vtables = 0;
+        vector_num_elems = 0;
+        return this;
+    }
+
+    /**
+     * An interface that provides a user of the FlatBufferBuilder class the ability to specify
+     * the method in which the internal buffer gets allocated. This allows for alternatives
+     * to the default behavior, which is to allocate memory for a new byte-array
+     * backed `ByteBuffer` array inside the JVM.
+     *
+     * The FlatBufferBuilder class contains the HeapByteBufferFactory class to
+     * preserve the default behavior in the event that the user does not provide
+     * their own implementation of this interface.
+     */
+    public static abstract class ByteBufferFactory {
+        /**
+         * Create a `ByteBuffer` with a given capacity.
+         * The returned ByteBuf must have a ByteOrder.LITTLE_ENDIAN ByteOrder.
+         *
+         * @param capacity The size of the `ByteBuffer` to allocate.
+         * @return Returns the new `ByteBuffer` that was allocated.
+         */
+        public abstract ByteBuffer newByteBuffer(int capacity);
+
+        /**
+         * Release a ByteBuffer. Current {@link FlatBufferBuilder}
+         * released any reference to it, so it is safe to dispose the buffer
+         * or return it to a pool.
+         * It is not guaranteed that the buffer has been created
+         * with {@link #newByteBuffer(int) }.
+         *
+         * @param bb the buffer to release
+         */
+        public void releaseByteBuffer(ByteBuffer bb) {
+        }
+    }
+
+    /**
+     * An implementation of the ByteBufferFactory interface that is used when
+     * one is not provided by the user.
+     *
+     * Allocate memory for a new byte-array backed `ByteBuffer` array inside the JVM.
+     */
+    public static final class HeapByteBufferFactory extends ByteBufferFactory {
+
+        public static final HeapByteBufferFactory INSTANCE = new HeapByteBufferFactory();
+
+        @Override
+        public ByteBuffer newByteBuffer(int capacity) {
+            return ByteBuffer.allocate(capacity).order(ByteOrder.LITTLE_ENDIAN);
+        }
+    }
+
+    /**
+     * Reset the FlatBufferBuilder by purging all data that it holds.
+     */
+    public void clear(){
+        space = bb.capacity();
+        bb.clear();
+        minalign = 1;
+        while(vtable_in_use > 0) vtable[--vtable_in_use] = 0;
+        vtable_in_use = 0;
+        nested = false;
+        finished = false;
+        object_start = 0;
+        num_vtables = 0;
+        vector_num_elems = 0;
+    }
+
+    /**
+     * Doubles the size of the backing {@link ByteBuffer} and copies the old data towards the
+     * end of the new buffer (since we build the buffer backwards).
+     *
+     * @param bb The current buffer with the existing data.
+     * @param bb_factory The factory to be used for allocating the new internal buffer
+     * @return A new byte buffer with the old data copied copied to it.  The data is
+     * located at the end of the buffer.
+     */
+    static ByteBuffer growByteBuffer(ByteBuffer bb, ByteBufferFactory bb_factory) {
+        int old_buf_size = bb.capacity();
+        if ((old_buf_size & 0xC0000000) != 0)  // Ensure we don't grow beyond what fits in an int.
+            throw new AssertionError("FlatBuffers: cannot grow buffer beyond 2 gigabytes.");
+        int new_buf_size = old_buf_size == 0 ? 1 : old_buf_size << 1;
+        bb.position(0);
+        ByteBuffer nbb = bb_factory.newByteBuffer(new_buf_size);
+        nbb.position(new_buf_size - old_buf_size);
+        nbb.put(bb);
+        return nbb;
+    }
+
+   /**
+    * Offset relative to the end of the buffer.
+    *
+    * @return Offset relative to the end of the buffer.
+    */
+    public int offset() {
+        return bb.capacity() - space;
+    }
+
+   /**
+    * Add zero valued bytes to prepare a new entry to be added.
+    *
+    * @param byte_size Number of bytes to add.
+    */
+    public void pad(int byte_size) {
+        for (int i = 0; i < byte_size; i++) bb.put(--space, (byte)0);
+    }
+
+   /**
+    * Prepare to write an element of `size` after `additional_bytes`
+    * have been written, e.g. if you write a string, you need to align such
+    * the int length field is aligned to {@link com.google.flatbuffers.Constants#SIZEOF_INT}, and
+    * the string data follows it directly.  If all you need to do is alignment, `additional_bytes`
+    * will be 0.
+    *
+    * @param size This is the of the new element to write.
+    * @param additional_bytes The padding size.
+    */
+    public void prep(int size, int additional_bytes) {
+        // Track the biggest thing we've ever aligned to.
+        if (size > minalign) minalign = size;
+        // Find the amount of alignment needed such that `size` is properly
+        // aligned after `additional_bytes`
+        int align_size = ((~(bb.capacity() - space + additional_bytes)) + 1) & (size - 1);
+        // Reallocate the buffer if needed.
+        while (space < align_size + size + additional_bytes) {
+            int old_buf_size = bb.capacity();
+            ByteBuffer old = bb;
+            bb = growByteBuffer(old, bb_factory);
+            if (old != bb) {
+                bb_factory.releaseByteBuffer(old);
+            }
+            space += bb.capacity() - old_buf_size;
+        }
+        pad(align_size);
+    }
+
+    /**
+     * Add a `boolean` to the buffer, backwards from the current location. Doesn't align nor
+     * check for space.
+     *
+     * @param x A `boolean` to put into the buffer.
+     */
+    public void putBoolean(boolean x) { bb.put      (space -= Constants.SIZEOF_BYTE, (byte)(x ? 1 : 0)); }
+
+    /**
+     * Add a `byte` to the buffer, backwards from the current location. Doesn't align nor
+     * check for space.
+     *
+     * @param x A `byte` to put into the buffer.
+     */
+    public void putByte   (byte    x) { bb.put      (space -= Constants.SIZEOF_BYTE, x); }
+
+    /**
+     * Add a `short` to the buffer, backwards from the current location. Doesn't align nor
+     * check for space.
+     *
+     * @param x A `short` to put into the buffer.
+     */
+    public void putShort  (short   x) { bb.putShort (space -= Constants.SIZEOF_SHORT, x); }
+
+    /**
+     * Add an `int` to the buffer, backwards from the current location. Doesn't align nor
+     * check for space.
+     *
+     * @param x An `int` to put into the buffer.
+     */
+    public void putInt    (int     x) { bb.putInt   (space -= Constants.SIZEOF_INT, x); }
+
+    /**
+     * Add a `long` to the buffer, backwards from the current location. Doesn't align nor
+     * check for space.
+     *
+     * @param x A `long` to put into the buffer.
+     */
+    public void putLong   (long    x) { bb.putLong  (space -= Constants.SIZEOF_LONG, x); }
+
+    /**
+     * Add a `float` to the buffer, backwards from the current location. Doesn't align nor
+     * check for space.
+     *
+     * @param x A `float` to put into the buffer.
+     */
+    public void putFloat  (float   x) { bb.putFloat (space -= Constants.SIZEOF_FLOAT, x); }
+
+    /**
+     * Add a `double` to the buffer, backwards from the current location. Doesn't align nor
+     * check for space.
+     *
+     * @param x A `double` to put into the buffer.
+     */
+    public void putDouble (double  x) { bb.putDouble(space -= Constants.SIZEOF_DOUBLE, x); }
+    /// @endcond
+
+    /**
+     * Add a `boolean` to the buffer, properly aligned, and grows the buffer (if necessary).
+     *
+     * @param x A `boolean` to put into the buffer.
+     */
+    public void addBoolean(boolean x) { prep(Constants.SIZEOF_BYTE, 0); putBoolean(x); }
+
+    /**
+     * Add a `byte` to the buffer, properly aligned, and grows the buffer (if necessary).
+     *
+     * @param x A `byte` to put into the buffer.
+     */
+    public void addByte   (byte    x) { prep(Constants.SIZEOF_BYTE, 0); putByte   (x); }
+
+    /**
+     * Add a `short` to the buffer, properly aligned, and grows the buffer (if necessary).
+     *
+     * @param x A `short` to put into the buffer.
+     */
+    public void addShort  (short   x) { prep(Constants.SIZEOF_SHORT, 0); putShort  (x); }
+
+    /**
+     * Add an `int` to the buffer, properly aligned, and grows the buffer (if necessary).
+     *
+     * @param x An `int` to put into the buffer.
+     */
+    public void addInt    (int     x) { prep(Constants.SIZEOF_INT, 0); putInt    (x); }
+
+    /**
+     * Add a `long` to the buffer, properly aligned, and grows the buffer (if necessary).
+     *
+     * @param x A `long` to put into the buffer.
+     */
+    public void addLong   (long    x) { prep(Constants.SIZEOF_LONG, 0); putLong   (x); }
+
+    /**
+     * Add a `float` to the buffer, properly aligned, and grows the buffer (if necessary).
+     *
+     * @param x A `float` to put into the buffer.
+     */
+    public void addFloat  (float   x) { prep(Constants.SIZEOF_FLOAT, 0); putFloat  (x); }
+
+    /**
+     * Add a `double` to the buffer, properly aligned, and grows the buffer (if necessary).
+     *
+     * @param x A `double` to put into the buffer.
+     */
+    public void addDouble (double  x) { prep(Constants.SIZEOF_DOUBLE, 0); putDouble (x); }
+
+   /**
+    * Adds on offset, relative to where it will be written.
+    *
+    * @param off The offset to add.
+    */
+    public void addOffset(int off) {
+        prep(SIZEOF_INT, 0);  // Ensure alignment is already done.
+        assert off <= offset();
+        off = offset() - off + SIZEOF_INT;
+        putInt(off);
+    }
+
+   /// @cond FLATBUFFERS_INTERNAL
+   /**
+    * Start a new array/vector of objects.  Users usually will not call
+    * this directly.  The `FlatBuffers` compiler will create a start/end
+    * method for vector types in generated code.
+    * <p>
+    * The expected sequence of calls is:
+    * <ol>
+    * <li>Start the array using this method.</li>
+    * <li>Call {@link #addOffset(int)} `num_elems` number of times to set
+    * the offset of each element in the array.</li>
+    * <li>Call {@link #endVector()} to retrieve the offset of the array.</li>
+    * </ol>
+    * <p>
+    * For example, to create an array of strings, do:
+    * <pre>{@code
+    * // Need 10 strings
+    * FlatBufferBuilder builder = new FlatBufferBuilder(existingBuffer);
+    * int[] offsets = new int[10];
+    *
+    * for (int i = 0; i < 10; i++) {
+    *   offsets[i] = fbb.createString(" " + i);
+    * }
+    *
+    * // Have the strings in the buffer, but don't have a vector.
+    * // Add a vector that references the newly created strings:
+    * builder.startVector(4, offsets.length, 4);
+    *
+    * // Add each string to the newly created vector
+    * // The strings are added in reverse order since the buffer
+    * // is filled in back to front
+    * for (int i = offsets.length - 1; i >= 0; i--) {
+    *   builder.addOffset(offsets[i]);
+    * }
+    *
+    * // Finish off the vector
+    * int offsetOfTheVector = fbb.endVector();
+    * }</pre>
+    *
+    * @param elem_size The size of each element in the array.
+    * @param num_elems The number of elements in the array.
+    * @param alignment The alignment of the array.
+    */
+    public void startVector(int elem_size, int num_elems, int alignment) {
+        notNested();
+        vector_num_elems = num_elems;
+        prep(SIZEOF_INT, elem_size * num_elems);
+        prep(alignment, elem_size * num_elems); // Just in case alignment > int.
+        nested = true;
+    }
+
+   /**
+    * Finish off the creation of an array and all its elements.  The array
+    * must be created with {@link #startVector(int, int, int)}.
+    *
+    * @return The offset at which the newly created array starts.
+    * @see #startVector(int, int, int)
+    */
+    public int endVector() {
+        if (!nested)
+            throw new AssertionError("FlatBuffers: endVector called without startVector");
+        nested = false;
+        putInt(vector_num_elems);
+        return offset();
+    }
+    /// @endcond
+
+    /**
+     * Create a new array/vector and return a ByteBuffer to be filled later.
+     * Call {@link #endVector} after this method to get an offset to the beginning
+     * of vector.
+     *
+     * @param elem_size the size of each element in bytes.
+     * @param num_elems number of elements in the vector.
+     * @param alignment byte alignment.
+     * @return ByteBuffer with position and limit set to the space allocated for the array.
+     */
+    public ByteBuffer createUnintializedVector(int elem_size, int num_elems, int alignment) {
+        int length = elem_size * num_elems;
+        startVector(elem_size, num_elems, alignment);
+
+        bb.position(space -= length);
+
+        // Slice and limit the copy vector to point to the 'array'
+        ByteBuffer copy = bb.slice().order(ByteOrder.LITTLE_ENDIAN);
+        copy.limit(length);
+        return copy;
+    }
+
+   /**
+     * Create a vector of tables.
+     *
+     * @param offsets Offsets of the tables.
+     * @return Returns offset of the vector.
+     */
+    public int createVectorOfTables(int[] offsets) {
+        notNested();
+        startVector(Constants.SIZEOF_INT, offsets.length, Constants.SIZEOF_INT);
+        for(int i = offsets.length - 1; i >= 0; i--) addOffset(offsets[i]);
+        return endVector();
+    }
+
+    /**
+     * Create a vector of sorted by the key tables.
+     *
+     * @param obj Instance of the table subclass.
+     * @param offsets Offsets of the tables.
+     * @return Returns offset of the sorted vector.
+     */
+    public <T extends Table> int createSortedVectorOfTables(T obj, int[] offsets) {
+        obj.sortTables(offsets, bb);
+        return createVectorOfTables(offsets);
+    }
+
+   /**
+    * Encode the string `s` in the buffer using UTF-8.  If {@code s} is
+    * already a {@link CharBuffer}, this method is allocation free.
+    *
+    * @param s The string to encode.
+    * @return The offset in the buffer where the encoded string starts.
+    */
+    public int createString(CharSequence s) {
+        int length = utf8.encodedLength(s);
+        addByte((byte)0);
+        startVector(1, length, 1);
+        bb.position(space -= length);
+        utf8.encodeUtf8(s, bb);
+        return endVector();
+    }
+
+   /**
+    * Create a string in the buffer from an already encoded UTF-8 string in a ByteBuffer.
+    *
+    * @param s An already encoded UTF-8 string as a `ByteBuffer`.
+    * @return The offset in the buffer where the encoded string starts.
+    */
+    public int createString(ByteBuffer s) {
+        int length = s.remaining();
+        addByte((byte)0);
+        startVector(1, length, 1);
+        bb.position(space -= length);
+        bb.put(s);
+        return endVector();
+    }
+
+    /**
+     * Create a byte array in the buffer.
+     *
+     * @param arr A source array with data
+     * @return The offset in the buffer where the encoded array starts.
+     */
+    public int createByteVector(byte[] arr) {
+        int length = arr.length;
+        startVector(1, length, 1);
+        bb.position(space -= length);
+        bb.put(arr);
+        return endVector();
+    }
+
+   /// @cond FLATBUFFERS_INTERNAL
+   /**
+    * Should not be accessing the final buffer before it is finished.
+    */
+    public void finished() {
+        if (!finished)
+            throw new AssertionError(
+                "FlatBuffers: you can only access the serialized buffer after it has been" +
+                " finished by FlatBufferBuilder.finish().");
+    }
+
+   /**
+    * Should not be creating any other object, string or vector
+    * while an object is being constructed.
+    */
+    public void notNested() {
+        if (nested)
+            throw new AssertionError("FlatBuffers: object serialization must not be nested.");
+    }
+
+   /**
+    * Structures are always stored inline, they need to be created right
+    * where they're used.  You'll get this assertion failure if you
+    * created it elsewhere.
+    *
+    * @param obj The offset of the created object.
+    */
+    public void Nested(int obj) {
+        if (obj != offset())
+            throw new AssertionError("FlatBuffers: struct must be serialized inline.");
+    }
+
+   /**
+    * Start encoding a new object in the buffer.  Users will not usually need to
+    * call this directly. The `FlatBuffers` compiler will generate helper methods
+    * that call this method internally.
+    * <p>
+    * For example, using the "Monster" code found on the "landing page". An
+    * object of type `Monster` can be created using the following code:
+    *
+    * <pre>{@code
+    * int testArrayOfString = Monster.createTestarrayofstringVector(fbb, new int[] {
+    *   fbb.createString("test1"),
+    *   fbb.createString("test2")
+    * });
+    *
+    * Monster.startMonster(fbb);
+    * Monster.addPos(fbb, Vec3.createVec3(fbb, 1.0f, 2.0f, 3.0f, 3.0,
+    *   Color.Green, (short)5, (byte)6));
+    * Monster.addHp(fbb, (short)80);
+    * Monster.addName(fbb, str);
+    * Monster.addInventory(fbb, inv);
+    * Monster.addTestType(fbb, (byte)Any.Monster);
+    * Monster.addTest(fbb, mon2);
+    * Monster.addTest4(fbb, test4);
+    * Monster.addTestarrayofstring(fbb, testArrayOfString);
+    * int mon = Monster.endMonster(fbb);
+    * }</pre>
+    * <p>
+    * Here:
+    * <ul>
+    * <li>The call to `Monster#startMonster(FlatBufferBuilder)` will call this
+    * method with the right number of fields set.</li>
+    * <li>`Monster#endMonster(FlatBufferBuilder)` will ensure {@link #endObject()} is called.</li>
+    * </ul>
+    * <p>
+    * It's not recommended to call this method directly.  If it's called manually, you must ensure
+    * to audit all calls to it whenever fields are added or removed from your schema.  This is
+    * automatically done by the code generated by the `FlatBuffers` compiler.
+    *
+    * @param numfields The number of fields found in this object.
+    */
+    public void startTable(int numfields) {
+        notNested();
+        if (vtable == null || vtable.length < numfields) vtable = new int[numfields];
+        vtable_in_use = numfields;
+        Arrays.fill(vtable, 0, vtable_in_use, 0);
+        nested = true;
+        object_start = offset();
+    }
+
+    /**
+     * Add a `boolean` to a table at `o` into its vtable, with value `x` and default `d`.
+     *
+     * @param o The index into the vtable.
+     * @param x A `boolean` to put into the buffer, depending on how defaults are handled. If
+     * `force_defaults` is `false`, compare `x` against the default value `d`. If `x` contains the
+     * default value, it can be skipped.
+     * @param d A `boolean` default value to compare against when `force_defaults` is `false`.
+     */
+    public void addBoolean(int o, boolean x, boolean d) { if(force_defaults || x != d) { addBoolean(x); slot(o); } }
+
+    /**
+     * Add a `byte` to a table at `o` into its vtable, with value `x` and default `d`.
+     *
+     * @param o The index into the vtable.
+     * @param x A `byte` to put into the buffer, depending on how defaults are handled. If
+     * `force_defaults` is `false`, compare `x` against the default value `d`. If `x` contains the
+     * default value, it can be skipped.
+     * @param d A `byte` default value to compare against when `force_defaults` is `false`.
+     */
+    public void addByte   (int o, byte    x, int     d) { if(force_defaults || x != d) { addByte   (x); slot(o); } }
+
+    /**
+     * Add a `short` to a table at `o` into its vtable, with value `x` and default `d`.
+     *
+     * @param o The index into the vtable.
+     * @param x A `short` to put into the buffer, depending on how defaults are handled. If
+     * `force_defaults` is `false`, compare `x` against the default value `d`. If `x` contains the
+     * default value, it can be skipped.
+     * @param d A `short` default value to compare against when `force_defaults` is `false`.
+     */
+    public void addShort  (int o, short   x, int     d) { if(force_defaults || x != d) { addShort  (x); slot(o); } }
+
+    /**
+     * Add an `int` to a table at `o` into its vtable, with value `x` and default `d`.
+     *
+     * @param o The index into the vtable.
+     * @param x An `int` to put into the buffer, depending on how defaults are handled. If
+     * `force_defaults` is `false`, compare `x` against the default value `d`. If `x` contains the
+     * default value, it can be skipped.
+     * @param d An `int` default value to compare against when `force_defaults` is `false`.
+     */
+    public void addInt    (int o, int     x, int     d) { if(force_defaults || x != d) { addInt    (x); slot(o); } }
+
+    /**
+     * Add a `long` to a table at `o` into its vtable, with value `x` and default `d`.
+     *
+     * @param o The index into the vtable.
+     * @param x A `long` to put into the buffer, depending on how defaults are handled. If
+     * `force_defaults` is `false`, compare `x` against the default value `d`. If `x` contains the
+     * default value, it can be skipped.
+     * @param d A `long` default value to compare against when `force_defaults` is `false`.
+     */
+    public void addLong   (int o, long    x, long    d) { if(force_defaults || x != d) { addLong   (x); slot(o); } }
+
+    /**
+     * Add a `float` to a table at `o` into its vtable, with value `x` and default `d`.
+     *
+     * @param o The index into the vtable.
+     * @param x A `float` to put into the buffer, depending on how defaults are handled. If
+     * `force_defaults` is `false`, compare `x` against the default value `d`. If `x` contains the
+     * default value, it can be skipped.
+     * @param d A `float` default value to compare against when `force_defaults` is `false`.
+     */
+    public void addFloat  (int o, float   x, double  d) { if(force_defaults || x != d) { addFloat  (x); slot(o); } }
+
+    /**
+     * Add a `double` to a table at `o` into its vtable, with value `x` and default `d`.
+     *
+     * @param o The index into the vtable.
+     * @param x A `double` to put into the buffer, depending on how defaults are handled. If
+     * `force_defaults` is `false`, compare `x` against the default value `d`. If `x` contains the
+     * default value, it can be skipped.
+     * @param d A `double` default value to compare against when `force_defaults` is `false`.
+     */
+    public void addDouble (int o, double  x, double  d) { if(force_defaults || x != d) { addDouble (x); slot(o); } }
+
+    /**
+     * Add an `offset` to a table at `o` into its vtable, with value `x` and default `d`.
+     *
+     * @param o The index into the vtable.
+     * @param x An `offset` to put into the buffer, depending on how defaults are handled. If
+     * `force_defaults` is `false`, compare `x` against the default value `d`. If `x` contains the
+     * default value, it can be skipped.
+     * @param d An `offset` default value to compare against when `force_defaults` is `false`.
+     */
+    public void addOffset (int o, int     x, int     d) { if(force_defaults || x != d) { addOffset (x); slot(o); } }
+
+    /**
+     * Add a struct to the table. Structs are stored inline, so nothing additional is being added.
+     *
+     * @param voffset The index into the vtable.
+     * @param x The offset of the created struct.
+     * @param d The default value is always `0`.
+     */
+    public void addStruct(int voffset, int x, int d) {
+        if(x != d) {
+            Nested(x);
+            slot(voffset);
+        }
+    }
+
+    /**
+     * Set the current vtable at `voffset` to the current location in the buffer.
+     *
+     * @param voffset The index into the vtable to store the offset relative to the end of the
+     * buffer.
+     */
+    public void slot(int voffset) {
+        vtable[voffset] = offset();
+    }
+
+   /**
+    * Finish off writing the object that is under construction.
+    *
+    * @return The offset to the object inside {@link #dataBuffer()}.
+    * @see #startTable(int)
+    */
+    public int endTable() {
+        if (vtable == null || !nested)
+            throw new AssertionError("FlatBuffers: endTable called without startTable");
+        addInt(0);
+        int vtableloc = offset();
+        // Write out the current vtable.
+        int i = vtable_in_use - 1;
+        // Trim trailing zeroes.
+        for (; i >= 0 && vtable[i] == 0; i--) {}
+        int trimmed_size = i + 1;
+        for (; i >= 0 ; i--) {
+            // Offset relative to the start of the table.
+            short off = (short)(vtable[i] != 0 ? vtableloc - vtable[i] : 0);
+            addShort(off);
+        }
+
+        final int standard_fields = 2; // The fields below:
+        addShort((short)(vtableloc - object_start));
+        addShort((short)((trimmed_size + standard_fields) * SIZEOF_SHORT));
+
+        // Search for an existing vtable that matches the current one.
+        int existing_vtable = 0;
+        outer_loop:
+        for (i = 0; i < num_vtables; i++) {
+            int vt1 = bb.capacity() - vtables[i];
+            int vt2 = space;
+            short len = bb.getShort(vt1);
+            if (len == bb.getShort(vt2)) {
+                for (int j = SIZEOF_SHORT; j < len; j += SIZEOF_SHORT) {
+                    if (bb.getShort(vt1 + j) != bb.getShort(vt2 + j)) {
+                        continue outer_loop;
+                    }
+                }
+                existing_vtable = vtables[i];
+                break outer_loop;
+            }
+        }
+
+        if (existing_vtable != 0) {
+            // Found a match:
+            // Remove the current vtable.
+            space = bb.capacity() - vtableloc;
+            // Point table to existing vtable.
+            bb.putInt(space, existing_vtable - vtableloc);
+        } else {
+            // No match:
+            // Add the location of the current vtable to the list of vtables.
+            if (num_vtables == vtables.length) vtables = Arrays.copyOf(vtables, num_vtables * 2);
+            vtables[num_vtables++] = offset();
+            // Point table to current vtable.
+            bb.putInt(bb.capacity() - vtableloc, offset() - vtableloc);
+        }
+
+        nested = false;
+        return vtableloc;
+    }
+
+    /**
+     * Checks that a required field has been set in a given table that has
+     * just been constructed.
+     *
+     * @param table The offset to the start of the table from the `ByteBuffer` capacity.
+     * @param field The offset to the field in the vtable.
+     */
+    public void required(int table, int field) {
+        int table_start = bb.capacity() - table;
+        int vtable_start = table_start - bb.getInt(table_start);
+        boolean ok = bb.getShort(vtable_start + field) != 0;
+        // If this fails, the caller will show what field needs to be set.
+        if (!ok)
+            throw new AssertionError("FlatBuffers: field " + field + " must be set");
+    }
+    /// @endcond
+
+    /**
+     * Finalize a buffer, pointing to the given `root_table`.
+     *
+     * @param root_table An offset to be added to the buffer.
+     * @param size_prefix Whether to prefix the size to the buffer.
+     */
+    protected void finish(int root_table, boolean size_prefix) {
+        prep(minalign, SIZEOF_INT + (size_prefix ? SIZEOF_INT : 0));
+        addOffset(root_table);
+        if (size_prefix) {
+            addInt(bb.capacity() - space);
+        }
+        bb.position(space);
+        finished = true;
+    }
+
+    /**
+     * Finalize a buffer, pointing to the given `root_table`.
+     *
+     * @param root_table An offset to be added to the buffer.
+     */
+    public void finish(int root_table) {
+        finish(root_table, false);
+    }
+
+    /**
+     * Finalize a buffer, pointing to the given `root_table`, with the size prefixed.
+     *
+     * @param root_table An offset to be added to the buffer.
+     */
+    public void finishSizePrefixed(int root_table) {
+        finish(root_table, true);
+    }
+
+    /**
+     * Finalize a buffer, pointing to the given `root_table`.
+     *
+     * @param root_table An offset to be added to the buffer.
+     * @param file_identifier A FlatBuffer file identifier to be added to the buffer before
+     * `root_table`.
+     * @param size_prefix Whether to prefix the size to the buffer.
+     */
+    protected void finish(int root_table, String file_identifier, boolean size_prefix) {
+        prep(minalign, SIZEOF_INT + FILE_IDENTIFIER_LENGTH + (size_prefix ? SIZEOF_INT : 0));
+        if (file_identifier.length() != FILE_IDENTIFIER_LENGTH)
+            throw new AssertionError("FlatBuffers: file identifier must be length " +
+                                     FILE_IDENTIFIER_LENGTH);
+        for (int i = FILE_IDENTIFIER_LENGTH - 1; i >= 0; i--) {
+            addByte((byte)file_identifier.charAt(i));
+        }
+        finish(root_table, size_prefix);
+    }
+
+    /**
+     * Finalize a buffer, pointing to the given `root_table`.
+     *
+     * @param root_table An offset to be added to the buffer.
+     * @param file_identifier A FlatBuffer file identifier to be added to the buffer before
+     * `root_table`.
+     */
+    public void finish(int root_table, String file_identifier) {
+        finish(root_table, file_identifier, false);
+    }
+
+    /**
+     * Finalize a buffer, pointing to the given `root_table`, with the size prefixed.
+     *
+     * @param root_table An offset to be added to the buffer.
+     * @param file_identifier A FlatBuffer file identifier to be added to the buffer before
+     * `root_table`.
+     */
+    public void finishSizePrefixed(int root_table, String file_identifier) {
+        finish(root_table, file_identifier, true);
+    }
+
+    /**
+     * In order to save space, fields that are set to their default value
+     * don't get serialized into the buffer. Forcing defaults provides a
+     * way to manually disable this optimization.
+     *
+     * @param forceDefaults When set to `true`, always serializes default values.
+     * @return Returns `this`.
+     */
+    public FlatBufferBuilder forceDefaults(boolean forceDefaults){
+        this.force_defaults = forceDefaults;
+        return this;
+    }
+
+    /**
+     * Get the ByteBuffer representing the FlatBuffer. Only call this after you've
+     * called `finish()`. The actual data starts at the ByteBuffer's current position,
+     * not necessarily at `0`.
+     *
+     * @return The {@link ByteBuffer} representing the FlatBuffer
+     */
+    public ByteBuffer dataBuffer() {
+        finished();
+        return bb;
+    }
+
+   /**
+    * The FlatBuffer data doesn't start at offset 0 in the {@link ByteBuffer}, but
+    * now the {@code ByteBuffer}'s position is set to that location upon {@link #finish(int)}.
+    *
+    * @return The {@link ByteBuffer#position() position} the data starts in {@link #dataBuffer()}
+    * @deprecated This method should not be needed anymore, but is left
+    * here for the moment to document this API change. It will be removed in the future.
+    */
+    @Deprecated
+    private int dataStart() {
+        finished();
+        return space;
+    }
+
+   /**
+    * A utility function to copy and return the ByteBuffer data from `start` to
+    * `start` + `length` as a `byte[]`.
+    *
+    * @param start Start copying at this offset.
+    * @param length How many bytes to copy.
+    * @return A range copy of the {@link #dataBuffer() data buffer}.
+    * @throws IndexOutOfBoundsException If the range of bytes is ouf of bound.
+    */
+    public byte[] sizedByteArray(int start, int length){
+        finished();
+        byte[] array = new byte[length];
+        bb.position(start);
+        bb.get(array);
+        return array;
+    }
+
+   /**
+    * A utility function to copy and return the ByteBuffer data as a `byte[]`.
+    *
+    * @return A full copy of the {@link #dataBuffer() data buffer}.
+    */
+    public byte[] sizedByteArray() {
+        return sizedByteArray(space, bb.capacity() - space);
+    }
+
+    /**
+     * A utility function to return an InputStream to the ByteBuffer data
+     *
+     * @return An InputStream that starts at the beginning of the ByteBuffer data
+     *         and can read to the end of it.
+     */
+    public InputStream sizedInputStream() {
+        finished();
+        ByteBuffer duplicate = bb.duplicate();
+        duplicate.position(space);
+        duplicate.limit(bb.capacity());
+        return new ByteBufferBackedInputStream(duplicate);
+    }
+
+    /**
+     * A class that allows a user to create an InputStream from a ByteBuffer.
+     */
+    static class ByteBufferBackedInputStream extends InputStream {
+
+        ByteBuffer buf;
+
+        public ByteBufferBackedInputStream(ByteBuffer buf) {
+            this.buf = buf;
+        }
+
+        public int read() throws IOException {
+            try {
+                return buf.get() & 0xFF;
+            } catch(BufferUnderflowException e) {
+                return -1;
+            }
+        }
+    }
+
+}
+
+/// @}
diff --git a/java/com/google/flatbuffers/Struct.java b/java/com/google/flatbuffers/Struct.java
new file mode 100644
index 0000000..c92164f
--- /dev/null
+++ b/java/com/google/flatbuffers/Struct.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2014 Google Inc. All rights reserved.
+ *
+ * Licensed 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 com.google.flatbuffers;
+
+import java.nio.ByteBuffer;
+
+/// @cond FLATBUFFERS_INTERNAL
+
+/**
+ * All structs in the generated code derive from this class, and add their own accessors.
+ */
+public class Struct {
+  /** Used to hold the position of the `bb` buffer. */
+  protected int bb_pos;
+  /** The underlying ByteBuffer to hold the data of the Struct. */
+  protected ByteBuffer bb;
+
+  /**
+   * Re-init the internal state with an external buffer {@code ByteBuffer} and an offset within.
+   *
+   * This method exists primarily to allow recycling Table instances without risking memory leaks
+   * due to {@code ByteBuffer} references.
+   */
+  protected void __reset(int _i, ByteBuffer _bb) { 
+    bb = _bb;
+    if (bb != null) {
+      bb_pos = _i;
+    } else {
+      bb_pos = 0;
+    }
+  }
+
+  /**
+   * Resets internal state with a null {@code ByteBuffer} and a zero position.
+   *
+   * This method exists primarily to allow recycling Struct instances without risking memory leaks
+   * due to {@code ByteBuffer} references. The instance will be unusable until it is assigned
+   * again to a {@code ByteBuffer}.
+   *
+   * @param struct the instance to reset to initial state
+   */
+  public void __reset() {
+    __reset(0, null);
+  }
+}
+
+/// @endcond
diff --git a/java/com/google/flatbuffers/Table.java b/java/com/google/flatbuffers/Table.java
new file mode 100644
index 0000000..ff069f2
--- /dev/null
+++ b/java/com/google/flatbuffers/Table.java
@@ -0,0 +1,297 @@
+/*
+ * Copyright 2014 Google Inc. All rights reserved.
+ *
+ * Licensed 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 com.google.flatbuffers;
+
+import static com.google.flatbuffers.Constants.*;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.charset.Charset;
+
+/// @cond FLATBUFFERS_INTERNAL
+
+/**
+ * All tables in the generated code derive from this class, and add their own accessors.
+ */
+public class Table {
+  public final static ThreadLocal<Charset> UTF8_CHARSET = new ThreadLocal<Charset>() {
+    @Override
+    protected Charset initialValue() {
+      return Charset.forName("UTF-8");
+    }
+  };
+  /** Used to hold the position of the `bb` buffer. */
+  protected int bb_pos;
+  /** The underlying ByteBuffer to hold the data of the Table. */
+  protected ByteBuffer bb;
+  /** Used to hold the vtable position. */
+  private int vtable_start;
+  /** Used to hold the vtable size. */
+  private int vtable_size;
+  Utf8 utf8 = Utf8.getDefault();
+
+  /**
+   * Get the underlying ByteBuffer.
+   *
+   * @return Returns the Table's ByteBuffer.
+   */
+  public ByteBuffer getByteBuffer() { return bb; }
+
+  /**
+   * Look up a field in the vtable.
+   *
+   * @param vtable_offset An `int` offset to the vtable in the Table's ByteBuffer.
+   * @return Returns an offset into the object, or `0` if the field is not present.
+   */
+  protected int __offset(int vtable_offset) {
+    return vtable_offset < vtable_size ? bb.getShort(vtable_start + vtable_offset) : 0;
+  }
+
+  protected static int __offset(int vtable_offset, int offset, ByteBuffer bb) {
+    int vtable = bb.capacity() - offset;
+    return bb.getShort(vtable + vtable_offset - bb.getInt(vtable)) + vtable;
+  }
+
+  /**
+   * Retrieve a relative offset.
+   *
+   * @param offset An `int` index into the Table's ByteBuffer containing the relative offset.
+   * @return Returns the relative offset stored at `offset`.
+   */
+  protected int __indirect(int offset) {
+    return offset + bb.getInt(offset);
+  }
+
+  protected static int __indirect(int offset, ByteBuffer bb) {
+    return offset + bb.getInt(offset);
+  }
+
+  /**
+   * Create a Java `String` from UTF-8 data stored inside the FlatBuffer.
+   *
+   * This allocates a new string and converts to wide chars upon each access,
+   * which is not very efficient. Instead, each FlatBuffer string also comes with an
+   * accessor based on __vector_as_bytebuffer below, which is much more efficient,
+   * assuming your Java program can handle UTF-8 data directly.
+   *
+   * @param offset An `int` index into the Table's ByteBuffer.
+   * @return Returns a `String` from the data stored inside the FlatBuffer at `offset`.
+   */
+  protected String __string(int offset) {
+    offset += bb.getInt(offset);
+    int length = bb.getInt(offset);
+    return utf8.decodeUtf8(bb, offset + SIZEOF_INT, length);
+  }
+
+  /**
+   * Get the length of a vector.
+   *
+   * @param offset An `int` index into the Table's ByteBuffer.
+   * @return Returns the length of the vector whose offset is stored at `offset`.
+   */
+  protected int __vector_len(int offset) {
+    offset += bb_pos;
+    offset += bb.getInt(offset);
+    return bb.getInt(offset);
+  }
+
+  /**
+   * Get the start data of a vector.
+   *
+   * @param offset An `int` index into the Table's ByteBuffer.
+   * @return Returns the start of the vector data whose offset is stored at `offset`.
+   */
+  protected int __vector(int offset) {
+    offset += bb_pos;
+    return offset + bb.getInt(offset) + SIZEOF_INT;  // data starts after the length
+  }
+
+  /**
+   * Get a whole vector as a ByteBuffer.
+   *
+   * This is efficient, since it only allocates a new {@link ByteBuffer} object,
+   * but does not actually copy the data, it still refers to the same bytes
+   * as the original ByteBuffer. Also useful with nested FlatBuffers, etc.
+   *
+   * @param vector_offset The position of the vector in the byte buffer
+   * @param elem_size The size of each element in the array
+   * @return The {@link ByteBuffer} for the array
+   */
+  protected ByteBuffer __vector_as_bytebuffer(int vector_offset, int elem_size) {
+    int o = __offset(vector_offset);
+    if (o == 0) return null;
+    ByteBuffer bb = this.bb.duplicate().order(ByteOrder.LITTLE_ENDIAN);
+    int vectorstart = __vector(o);
+    bb.position(vectorstart);
+    bb.limit(vectorstart + __vector_len(o) * elem_size);
+    return bb;
+  }
+
+  /**
+   * Initialize vector as a ByteBuffer.
+   *
+   * This is more efficient than using duplicate, since it doesn't copy the data
+   * nor allocattes a new {@link ByteBuffer}, creating no garbage to be collected.
+   *
+   * @param bb The {@link ByteBuffer} for the array
+   * @param vector_offset The position of the vector in the byte buffer
+   * @param elem_size The size of each element in the array
+   * @return The {@link ByteBuffer} for the array
+   */
+  protected ByteBuffer __vector_in_bytebuffer(ByteBuffer bb, int vector_offset, int elem_size) {
+    int o = this.__offset(vector_offset);
+    if (o == 0) return null;
+    int vectorstart = __vector(o);
+    bb.rewind();
+    bb.limit(vectorstart + __vector_len(o) * elem_size);
+    bb.position(vectorstart);
+    return bb;
+  }
+
+  /**
+   * Initialize any Table-derived type to point to the union at the given `offset`.
+   *
+   * @param t A `Table`-derived type that should point to the union at `offset`.
+   * @param offset An `int` index into the Table's ByteBuffer.
+   * @return Returns the Table that points to the union at `offset`.
+   */
+  protected Table __union(Table t, int offset) {
+    offset += bb_pos;
+    t.bb_pos = offset + bb.getInt(offset);
+    t.bb = bb;
+    t.vtable_start = t.bb_pos - bb.getInt(t.bb_pos);
+    t.vtable_size = bb.getShort(t.vtable_start);
+    return t;
+  }
+
+  /**
+   * Check if a {@link ByteBuffer} contains a file identifier.
+   *
+   * @param bb A {@code ByteBuffer} to check if it contains the identifier
+   * `ident`.
+   * @param ident A `String` identifier of the FlatBuffer file.
+   * @return True if the buffer contains the file identifier
+   */
+  protected static boolean __has_identifier(ByteBuffer bb, String ident) {
+    if (ident.length() != FILE_IDENTIFIER_LENGTH)
+        throw new AssertionError("FlatBuffers: file identifier must be length " +
+                                 FILE_IDENTIFIER_LENGTH);
+    for (int i = 0; i < FILE_IDENTIFIER_LENGTH; i++) {
+      if (ident.charAt(i) != (char)bb.get(bb.position() + SIZEOF_INT + i)) return false;
+    }
+    return true;
+  }
+
+  /**
+   * Sort tables by the key.
+   *
+   * @param offsets An 'int' indexes of the tables into the bb.
+   * @param bb A {@code ByteBuffer} to get the tables.
+   */
+  protected void sortTables(int[] offsets, final ByteBuffer bb) {
+    Integer[] off = new Integer[offsets.length];
+    for (int i = 0; i < offsets.length; i++) off[i] = offsets[i];
+    java.util.Arrays.sort(off, new java.util.Comparator<Integer>() {
+      public int compare(Integer o1, Integer o2) {
+        return keysCompare(o1, o2, bb);
+      }
+    });
+    for (int i = 0; i < offsets.length; i++) offsets[i] = off[i];
+  }
+
+  /**
+   * Compare two tables by the key.
+   *
+   * @param o1 An 'Integer' index of the first key into the bb.
+   * @param o2 An 'Integer' index of the second key into the bb.
+   * @param bb A {@code ByteBuffer} to get the keys.
+   */
+  protected int keysCompare(Integer o1, Integer o2, ByteBuffer bb) { return 0; }
+
+  /**
+   * Compare two strings in the buffer.
+   *
+   * @param offset_1 An 'int' index of the first string into the bb.
+   * @param offset_2 An 'int' index of the second string into the bb.
+   * @param bb A {@code ByteBuffer} to get the strings.
+   */
+  protected static int compareStrings(int offset_1, int offset_2, ByteBuffer bb) {
+    offset_1 += bb.getInt(offset_1);
+    offset_2 += bb.getInt(offset_2);
+    int len_1 = bb.getInt(offset_1);
+    int len_2 = bb.getInt(offset_2);
+    int startPos_1 = offset_1 + SIZEOF_INT;
+    int startPos_2 = offset_2 + SIZEOF_INT;
+    int len = Math.min(len_1, len_2);
+    for(int i = 0; i < len; i++) {
+      if (bb.get(i + startPos_1) != bb.get(i + startPos_2))
+        return bb.get(i + startPos_1) - bb.get(i + startPos_2);
+    }
+    return len_1 - len_2;
+  }
+
+  /**
+   * Compare string from the buffer with the 'String' object.
+   *
+   * @param offset_1 An 'int' index of the first string into the bb.
+   * @param key Second string as a byte array.
+   * @param bb A {@code ByteBuffer} to get the first string.
+   */
+  protected static int compareStrings(int offset_1, byte[] key, ByteBuffer bb) {
+    offset_1 += bb.getInt(offset_1);
+    int len_1 = bb.getInt(offset_1);
+    int len_2 = key.length;
+    int startPos_1 = offset_1 + Constants.SIZEOF_INT;
+    int len = Math.min(len_1, len_2);
+    for (int i = 0; i < len; i++) {
+      if (bb.get(i + startPos_1) != key[i])
+        return bb.get(i + startPos_1) - key[i];
+    }
+    return len_1 - len_2;
+  }
+
+  /**
+   * Re-init the internal state with an external buffer {@code ByteBuffer} and an offset within.
+   *
+   * This method exists primarily to allow recycling Table instances without risking memory leaks
+   * due to {@code ByteBuffer} references.
+   */
+  protected void __reset(int _i, ByteBuffer _bb) { 
+    bb = _bb;
+    if (bb != null) {
+      bb_pos = _i;
+      vtable_start = bb_pos - bb.getInt(bb_pos);
+      vtable_size = bb.getShort(vtable_start);
+    } else {
+      bb_pos = 0;
+      vtable_start = 0;
+      vtable_size = 0;
+    }
+  }
+
+  /**
+   * Resets the internal state with a null {@code ByteBuffer} and a zero position.
+   *
+   * This method exists primarily to allow recycling Table instances without risking memory leaks
+   * due to {@code ByteBuffer} references. The instance will be unusable until it is assigned
+   * again to a {@code ByteBuffer}.
+   */
+  public void __reset() {
+    __reset(0, null);
+  }
+}
+
+/// @endcond
diff --git a/java/com/google/flatbuffers/Utf8.java b/java/com/google/flatbuffers/Utf8.java
new file mode 100644
index 0000000..efb6811
--- /dev/null
+++ b/java/com/google/flatbuffers/Utf8.java
@@ -0,0 +1,193 @@
+/*
+ * Copyright 2014 Google Inc. All rights reserved.
+ *
+ * Licensed 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 com.google.flatbuffers;
+
+import java.nio.ByteBuffer;
+
+import static java.lang.Character.MIN_HIGH_SURROGATE;
+import static java.lang.Character.MIN_LOW_SURROGATE;
+import static java.lang.Character.MIN_SUPPLEMENTARY_CODE_POINT;
+
+public abstract class Utf8 {
+
+  /**
+   * Returns the number of bytes in the UTF-8-encoded form of {@code sequence}. For a string,
+   * this method is equivalent to {@code string.getBytes(UTF_8).length}, but is more efficient in
+   * both time and space.
+   *
+   * @throws IllegalArgumentException if {@code sequence} contains ill-formed UTF-16 (unpaired
+   *     surrogates)
+   */
+  public abstract int encodedLength(CharSequence sequence);
+
+  /**
+   * Encodes the given characters to the target {@link ByteBuffer} using UTF-8 encoding.
+   *
+   * <p>Selects an optimal algorithm based on the type of {@link ByteBuffer} (i.e. heap or direct)
+   * and the capabilities of the platform.
+   *
+   * @param in the source string to be encoded
+   * @param out the target buffer to receive the encoded string.
+   */
+  public abstract void encodeUtf8(CharSequence in, ByteBuffer out);
+
+  /**
+   * Decodes the given UTF-8 portion of the {@link ByteBuffer} into a {@link String}.
+   *
+   * @throws IllegalArgumentException if the input is not valid UTF-8.
+   */
+  public abstract String decodeUtf8(ByteBuffer buffer, int offset, int length);
+
+  private static Utf8 DEFAULT;
+
+  /**
+   * Get the default UTF-8 processor.
+   * @return the default processor
+   */
+  public static Utf8 getDefault() {
+    if (DEFAULT == null) {
+      DEFAULT = new Utf8Safe();
+    }
+    return DEFAULT;
+  }
+
+  /**
+   * Set the default instance of the UTF-8 processor.
+   * @param instance the new instance to use
+   */
+  public static void setDefault(Utf8 instance) {
+    DEFAULT = instance;
+  }
+
+  /**
+   * Utility methods for decoding bytes into {@link String}. Callers are responsible for extracting
+   * bytes (possibly using Unsafe methods), and checking remaining bytes. All other UTF-8 validity
+   * checks and codepoint conversion happen in this class.
+   */
+  static class DecodeUtil {
+
+    /**
+     * Returns whether this is a single-byte codepoint (i.e., ASCII) with the form '0XXXXXXX'.
+     */
+    static boolean isOneByte(byte b) {
+      return b >= 0;
+    }
+
+    /**
+     * Returns whether this is a two-byte codepoint with the form '10XXXXXX'.
+     */
+    static boolean isTwoBytes(byte b) {
+      return b < (byte) 0xE0;
+    }
+
+    /**
+     * Returns whether this is a three-byte codepoint with the form '110XXXXX'.
+     */
+    static boolean isThreeBytes(byte b) {
+      return b < (byte) 0xF0;
+    }
+
+    static void handleOneByte(byte byte1, char[] resultArr, int resultPos) {
+      resultArr[resultPos] = (char) byte1;
+    }
+
+    static void handleTwoBytes(
+        byte byte1, byte byte2, char[] resultArr, int resultPos)
+        throws IllegalArgumentException {
+      // Simultaneously checks for illegal trailing-byte in leading position (<= '11000000') and
+      // overlong 2-byte, '11000001'.
+      if (byte1 < (byte) 0xC2) {
+        throw new IllegalArgumentException("Invalid UTF-8: Illegal leading byte in 2 bytes utf");
+      }
+      if (isNotTrailingByte(byte2)) {
+        throw new IllegalArgumentException("Invalid UTF-8: Illegal trailing byte in 2 bytes utf");
+      }
+      resultArr[resultPos] = (char) (((byte1 & 0x1F) << 6) | trailingByteValue(byte2));
+    }
+
+    static void handleThreeBytes(
+        byte byte1, byte byte2, byte byte3, char[] resultArr, int resultPos)
+        throws IllegalArgumentException {
+      if (isNotTrailingByte(byte2)
+              // overlong? 5 most significant bits must not all be zero
+              || (byte1 == (byte) 0xE0 && byte2 < (byte) 0xA0)
+              // check for illegal surrogate codepoints
+              || (byte1 == (byte) 0xED && byte2 >= (byte) 0xA0)
+              || isNotTrailingByte(byte3)) {
+        throw new IllegalArgumentException("Invalid UTF-8");
+      }
+      resultArr[resultPos] = (char)
+                                 (((byte1 & 0x0F) << 12) | (trailingByteValue(byte2) << 6) | trailingByteValue(byte3));
+    }
+
+    static void handleFourBytes(
+        byte byte1, byte byte2, byte byte3, byte byte4, char[] resultArr, int resultPos)
+        throws IllegalArgumentException{
+      if (isNotTrailingByte(byte2)
+              // Check that 1 <= plane <= 16.  Tricky optimized form of:
+              //   valid 4-byte leading byte?
+              // if (byte1 > (byte) 0xF4 ||
+              //   overlong? 4 most significant bits must not all be zero
+              //     byte1 == (byte) 0xF0 && byte2 < (byte) 0x90 ||
+              //   codepoint larger than the highest code point (U+10FFFF)?
+              //     byte1 == (byte) 0xF4 && byte2 > (byte) 0x8F)
+              || (((byte1 << 28) + (byte2 - (byte) 0x90)) >> 30) != 0
+              || isNotTrailingByte(byte3)
+              || isNotTrailingByte(byte4)) {
+        throw new IllegalArgumentException("Invalid UTF-8");
+      }
+      int codepoint = ((byte1 & 0x07) << 18)
+                          | (trailingByteValue(byte2) << 12)
+                          | (trailingByteValue(byte3) << 6)
+                          | trailingByteValue(byte4);
+      resultArr[resultPos] = DecodeUtil.highSurrogate(codepoint);
+      resultArr[resultPos + 1] = DecodeUtil.lowSurrogate(codepoint);
+    }
+
+    /**
+     * Returns whether the byte is not a valid continuation of the form '10XXXXXX'.
+     */
+    private static boolean isNotTrailingByte(byte b) {
+      return b > (byte) 0xBF;
+    }
+
+    /**
+     * Returns the actual value of the trailing byte (removes the prefix '10') for composition.
+     */
+    private static int trailingByteValue(byte b) {
+      return b & 0x3F;
+    }
+
+    private static char highSurrogate(int codePoint) {
+      return (char) ((MIN_HIGH_SURROGATE - (MIN_SUPPLEMENTARY_CODE_POINT >>> 10))
+                         + (codePoint >>> 10));
+    }
+
+    private static char lowSurrogate(int codePoint) {
+      return (char) (MIN_LOW_SURROGATE + (codePoint & 0x3ff));
+    }
+  }
+
+  // These UTF-8 handling methods are copied from Guava's Utf8Unsafe class with a modification to throw
+  // a protocol buffer local exception. This exception is then caught in CodedOutputStream so it can
+  // fallback to more lenient behavior.
+  static class UnpairedSurrogateException extends IllegalArgumentException {
+    UnpairedSurrogateException(int index, int length) {
+      super("Unpaired surrogate at index " + index + " of " + length);
+    }
+  }
+}
diff --git a/java/com/google/flatbuffers/Utf8Old.java b/java/com/google/flatbuffers/Utf8Old.java
new file mode 100644
index 0000000..3dac714
--- /dev/null
+++ b/java/com/google/flatbuffers/Utf8Old.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2014 Google Inc. All rights reserved.
+ *
+ * Licensed 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 com.google.flatbuffers;
+
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.CoderResult;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * This class implements the Utf8 API using the Java Utf8 encoder. Use
+ * Utf8.setDefault(new Utf8Old()); to use it.
+ */
+public class Utf8Old extends Utf8 {
+
+  private static class Cache {
+    final CharsetEncoder encoder;
+    final CharsetDecoder decoder;
+    CharSequence lastInput = null;
+    ByteBuffer lastOutput = null;
+
+    Cache() {
+      encoder = StandardCharsets.UTF_8.newEncoder();
+      decoder = StandardCharsets.UTF_8.newDecoder();
+    }
+  }
+
+  private static final ThreadLocal<Cache> CACHE =
+      ThreadLocal.withInitial(() -> new Cache());
+
+  // Play some games so that the old encoder doesn't pay twice for computing
+  // the length of the encoded string.
+
+  @Override
+  public int encodedLength(CharSequence in) {
+    final Cache cache = CACHE.get();
+    int estimated = (int) (in.length() * cache.encoder.maxBytesPerChar());
+    if (cache.lastOutput == null || cache.lastOutput.capacity() < estimated) {
+      cache.lastOutput = ByteBuffer.allocate(Math.max(128, estimated));
+    }
+    cache.lastOutput.clear();
+    cache.lastInput = in;
+    CharBuffer wrap = (in instanceof CharBuffer) ?
+                          (CharBuffer) in : CharBuffer.wrap(in);
+    CoderResult result = cache.encoder.encode(wrap, cache.lastOutput, true);
+    if (result.isError()) {
+      try {
+        result.throwException();
+      } catch (CharacterCodingException e) {
+        throw new IllegalArgumentException("bad character encoding", e);
+      }
+    }
+    cache.lastOutput.flip();
+    return cache.lastOutput.remaining();
+  }
+
+  @Override
+  public void encodeUtf8(CharSequence in, ByteBuffer out) {
+    final Cache cache = CACHE.get();
+    if (cache.lastInput != in) {
+      // Update the lastOutput to match our input, although flatbuffer should
+      // never take this branch.
+      encodedLength(in);
+    }
+    out.put(cache.lastOutput);
+  }
+
+  @Override
+  public String decodeUtf8(ByteBuffer buffer, int offset, int length) {
+    CharsetDecoder decoder = CACHE.get().decoder;
+    decoder.reset();
+    buffer = buffer.duplicate();
+    buffer.position(offset);
+    buffer.limit(offset + length);
+    try {
+      CharBuffer result = decoder.decode(buffer);
+      return result.toString();
+    } catch (CharacterCodingException e) {
+      throw new IllegalArgumentException("Bad encoding", e);
+    }
+  }
+}
diff --git a/java/com/google/flatbuffers/Utf8Safe.java b/java/com/google/flatbuffers/Utf8Safe.java
new file mode 100644
index 0000000..06ea420
--- /dev/null
+++ b/java/com/google/flatbuffers/Utf8Safe.java
@@ -0,0 +1,451 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.flatbuffers;
+
+import java.nio.ByteBuffer;
+import static java.lang.Character.MAX_SURROGATE;
+import static java.lang.Character.MIN_SUPPLEMENTARY_CODE_POINT;
+import static java.lang.Character.MIN_SURROGATE;
+import static java.lang.Character.isSurrogatePair;
+import static java.lang.Character.toCodePoint;
+
+/**
+ * A set of low-level, high-performance static utility methods related
+ * to the UTF-8 character encoding.  This class has no dependencies
+ * outside of the core JDK libraries.
+ *
+ * <p>There are several variants of UTF-8.  The one implemented by
+ * this class is the restricted definition of UTF-8 introduced in
+ * Unicode 3.1, which mandates the rejection of "overlong" byte
+ * sequences as well as rejection of 3-byte surrogate codepoint byte
+ * sequences.  Note that the UTF-8 decoder included in Oracle's JDK
+ * has been modified to also reject "overlong" byte sequences, but (as
+ * of 2011) still accepts 3-byte surrogate codepoint byte sequences.
+ *
+ * <p>The byte sequences considered valid by this class are exactly
+ * those that can be roundtrip converted to Strings and back to bytes
+ * using the UTF-8 charset, without loss: <pre> {@code
+ * Arrays.equals(bytes, new String(bytes, Internal.UTF_8).getBytes(Internal.UTF_8))
+ * }</pre>
+ *
+ * <p>See the Unicode Standard,</br>
+ * Table 3-6. <em>UTF-8 Bit Distribution</em>,</br>
+ * Table 3-7. <em>Well Formed UTF-8 Byte Sequences</em>.
+ */
+final public class Utf8Safe extends Utf8 {
+
+  /**
+   * Returns the number of bytes in the UTF-8-encoded form of {@code sequence}. For a string,
+   * this method is equivalent to {@code string.getBytes(UTF_8).length}, but is more efficient in
+   * both time and space.
+   *
+   * @throws IllegalArgumentException if {@code sequence} contains ill-formed UTF-16 (unpaired
+   *     surrogates)
+   */
+  private static int computeEncodedLength(CharSequence sequence) {
+    // Warning to maintainers: this implementation is highly optimized.
+    int utf16Length = sequence.length();
+    int utf8Length = utf16Length;
+    int i = 0;
+
+    // This loop optimizes for pure ASCII.
+    while (i < utf16Length && sequence.charAt(i) < 0x80) {
+      i++;
+    }
+
+    // This loop optimizes for chars less than 0x800.
+    for (; i < utf16Length; i++) {
+      char c = sequence.charAt(i);
+      if (c < 0x800) {
+        utf8Length += ((0x7f - c) >>> 31);  // branch free!
+      } else {
+        utf8Length += encodedLengthGeneral(sequence, i);
+        break;
+      }
+    }
+
+    if (utf8Length < utf16Length) {
+      // Necessary and sufficient condition for overflow because of maximum 3x expansion
+      throw new IllegalArgumentException("UTF-8 length does not fit in int: "
+                                             + (utf8Length + (1L << 32)));
+    }
+    return utf8Length;
+  }
+
+  private static int encodedLengthGeneral(CharSequence sequence, int start) {
+    int utf16Length = sequence.length();
+    int utf8Length = 0;
+    for (int i = start; i < utf16Length; i++) {
+      char c = sequence.charAt(i);
+      if (c < 0x800) {
+        utf8Length += (0x7f - c) >>> 31; // branch free!
+      } else {
+        utf8Length += 2;
+        // jdk7+: if (Character.isSurrogate(c)) {
+        if (Character.MIN_SURROGATE <= c && c <= Character.MAX_SURROGATE) {
+          // Check that we have a well-formed surrogate pair.
+          int cp = Character.codePointAt(sequence, i);
+          if (cp < MIN_SUPPLEMENTARY_CODE_POINT) {
+            throw new Utf8Safe.UnpairedSurrogateException(i, utf16Length);
+          }
+          i++;
+        }
+      }
+    }
+    return utf8Length;
+  }
+
+  private static String decodeUtf8Array(byte[] bytes, int index, int size) {
+    // Bitwise OR combines the sign bits so any negative value fails the check.
+    if ((index | size | bytes.length - index - size) < 0) {
+      throw new ArrayIndexOutOfBoundsException(
+          String.format("buffer length=%d, index=%d, size=%d", bytes.length, index, size));
+    }
+
+    int offset = index;
+    final int limit = offset + size;
+
+    // The longest possible resulting String is the same as the number of input bytes, when it is
+    // all ASCII. For other cases, this over-allocates and we will truncate in the end.
+    char[] resultArr = new char[size];
+    int resultPos = 0;
+
+    // Optimize for 100% ASCII (Hotspot loves small simple top-level loops like this).
+    // This simple loop stops when we encounter a byte >= 0x80 (i.e. non-ASCII).
+    while (offset < limit) {
+      byte b = bytes[offset];
+      if (!DecodeUtil.isOneByte(b)) {
+        break;
+      }
+      offset++;
+      DecodeUtil.handleOneByte(b, resultArr, resultPos++);
+    }
+
+    while (offset < limit) {
+      byte byte1 = bytes[offset++];
+      if (DecodeUtil.isOneByte(byte1)) {
+        DecodeUtil.handleOneByte(byte1, resultArr, resultPos++);
+        // It's common for there to be multiple ASCII characters in a run mixed in, so add an
+        // extra optimized loop to take care of these runs.
+        while (offset < limit) {
+          byte b = bytes[offset];
+          if (!DecodeUtil.isOneByte(b)) {
+            break;
+          }
+          offset++;
+          DecodeUtil.handleOneByte(b, resultArr, resultPos++);
+        }
+      } else if (DecodeUtil.isTwoBytes(byte1)) {
+        if (offset >= limit) {
+          throw new IllegalArgumentException("Invalid UTF-8");
+        }
+        DecodeUtil.handleTwoBytes(byte1, /* byte2 */ bytes[offset++], resultArr, resultPos++);
+      } else if (DecodeUtil.isThreeBytes(byte1)) {
+        if (offset >= limit - 1) {
+          throw new IllegalArgumentException("Invalid UTF-8");
+        }
+        DecodeUtil.handleThreeBytes(
+            byte1,
+            /* byte2 */ bytes[offset++],
+            /* byte3 */ bytes[offset++],
+            resultArr,
+            resultPos++);
+      } else {
+        if (offset >= limit - 2) {
+          throw new IllegalArgumentException("Invalid UTF-8");
+        }
+        DecodeUtil.handleFourBytes(
+            byte1,
+            /* byte2 */ bytes[offset++],
+            /* byte3 */ bytes[offset++],
+            /* byte4 */ bytes[offset++],
+            resultArr,
+            resultPos++);
+        // 4-byte case requires two chars.
+        resultPos++;
+      }
+    }
+
+    return new String(resultArr, 0, resultPos);
+  }
+
+  private static String decodeUtf8Buffer(ByteBuffer buffer, int offset,
+                                         int length) {
+    // Bitwise OR combines the sign bits so any negative value fails the check.
+    if ((offset | length | buffer.limit() - offset - length) < 0) {
+      throw new ArrayIndexOutOfBoundsException(
+          String.format("buffer limit=%d, index=%d, limit=%d", buffer.limit(),
+              offset, length));
+    }
+
+    final int limit = offset + length;
+
+    // The longest possible resulting String is the same as the number of input bytes, when it is
+    // all ASCII. For other cases, this over-allocates and we will truncate in the end.
+    char[] resultArr = new char[length];
+    int resultPos = 0;
+
+    // Optimize for 100% ASCII (Hotspot loves small simple top-level loops like this).
+    // This simple loop stops when we encounter a byte >= 0x80 (i.e. non-ASCII).
+    while (offset < limit) {
+      byte b = buffer.get(offset);
+      if (!DecodeUtil.isOneByte(b)) {
+        break;
+      }
+      offset++;
+      DecodeUtil.handleOneByte(b, resultArr, resultPos++);
+    }
+
+    while (offset < limit) {
+      byte byte1 = buffer.get(offset++);
+      if (DecodeUtil.isOneByte(byte1)) {
+        DecodeUtil.handleOneByte(byte1, resultArr, resultPos++);
+        // It's common for there to be multiple ASCII characters in a run mixed in, so add an
+        // extra optimized loop to take care of these runs.
+        while (offset < limit) {
+          byte b = buffer.get(offset);
+          if (!DecodeUtil.isOneByte(b)) {
+            break;
+          }
+          offset++;
+          DecodeUtil.handleOneByte(b, resultArr, resultPos++);
+        }
+      } else if (DecodeUtil.isTwoBytes(byte1)) {
+        if (offset >= limit) {
+          throw new IllegalArgumentException("Invalid UTF-8");
+        }
+        DecodeUtil.handleTwoBytes(
+            byte1, /* byte2 */ buffer.get(offset++), resultArr, resultPos++);
+      } else if (DecodeUtil.isThreeBytes(byte1)) {
+        if (offset >= limit - 1) {
+          throw new IllegalArgumentException("Invalid UTF-8");
+        }
+        DecodeUtil.handleThreeBytes(
+            byte1,
+            /* byte2 */ buffer.get(offset++),
+            /* byte3 */ buffer.get(offset++),
+            resultArr,
+            resultPos++);
+      } else {
+        if (offset >= limit - 2) {
+          throw new IllegalArgumentException("Invalid UTF-8");
+        }
+        DecodeUtil.handleFourBytes(
+            byte1,
+            /* byte2 */ buffer.get(offset++),
+            /* byte3 */ buffer.get(offset++),
+            /* byte4 */ buffer.get(offset++),
+            resultArr,
+            resultPos++);
+        // 4-byte case requires two chars.
+        resultPos++;
+      }
+    }
+
+    return new String(resultArr, 0, resultPos);
+  }
+
+  @Override
+  public int encodedLength(CharSequence in) {
+    return computeEncodedLength(in);
+  }
+
+  /**
+   * Decodes the given UTF-8 portion of the {@link ByteBuffer} into a {@link String}.
+   *
+   * @throws IllegalArgumentException if the input is not valid UTF-8.
+   */
+  @Override
+  public String decodeUtf8(ByteBuffer buffer, int offset, int length)
+      throws IllegalArgumentException {
+    if (buffer.hasArray()) {
+      return decodeUtf8Array(buffer.array(), buffer.arrayOffset() + offset, length);
+    } else {
+      return decodeUtf8Buffer(buffer, offset, length);
+    }
+  }
+
+
+  private static void encodeUtf8Buffer(CharSequence in, ByteBuffer out) {
+    final int inLength = in.length();
+    int outIx = out.position();
+    int inIx = 0;
+
+    // Since ByteBuffer.putXXX() already checks boundaries for us, no need to explicitly check
+    // access. Assume the buffer is big enough and let it handle the out of bounds exception
+    // if it occurs.
+    try {
+      // Designed to take advantage of
+      // https://wikis.oracle.com/display/HotSpotInternals/RangeCheckElimination
+      for (char c; inIx < inLength && (c = in.charAt(inIx)) < 0x80; ++inIx) {
+        out.put(outIx + inIx, (byte) c);
+      }
+      if (inIx == inLength) {
+        // Successfully encoded the entire string.
+        out.position(outIx + inIx);
+        return;
+      }
+
+      outIx += inIx;
+      for (char c; inIx < inLength; ++inIx, ++outIx) {
+        c = in.charAt(inIx);
+        if (c < 0x80) {
+          // One byte (0xxx xxxx)
+          out.put(outIx, (byte) c);
+        } else if (c < 0x800) {
+          // Two bytes (110x xxxx 10xx xxxx)
+
+          // Benchmarks show put performs better than putShort here (for HotSpot).
+          out.put(outIx++, (byte) (0xC0 | (c >>> 6)));
+          out.put(outIx, (byte) (0x80 | (0x3F & c)));
+        } else if (c < MIN_SURROGATE || MAX_SURROGATE < c) {
+          // Three bytes (1110 xxxx 10xx xxxx 10xx xxxx)
+          // Maximum single-char code point is 0xFFFF, 16 bits.
+
+          // Benchmarks show put performs better than putShort here (for HotSpot).
+          out.put(outIx++, (byte) (0xE0 | (c >>> 12)));
+          out.put(outIx++, (byte) (0x80 | (0x3F & (c >>> 6))));
+          out.put(outIx, (byte) (0x80 | (0x3F & c)));
+        } else {
+          // Four bytes (1111 xxxx 10xx xxxx 10xx xxxx 10xx xxxx)
+
+          // Minimum code point represented by a surrogate pair is 0x10000, 17 bits, four UTF-8
+          // bytes
+          final char low;
+          if (inIx + 1 == inLength || !isSurrogatePair(c, (low = in.charAt(++inIx)))) {
+            throw new UnpairedSurrogateException(inIx, inLength);
+          }
+          // TODO(nathanmittler): Consider using putInt() to improve performance.
+          int codePoint = toCodePoint(c, low);
+          out.put(outIx++, (byte) ((0xF << 4) | (codePoint >>> 18)));
+          out.put(outIx++, (byte) (0x80 | (0x3F & (codePoint >>> 12))));
+          out.put(outIx++, (byte) (0x80 | (0x3F & (codePoint >>> 6))));
+          out.put(outIx, (byte) (0x80 | (0x3F & codePoint)));
+        }
+      }
+
+      // Successfully encoded the entire string.
+      out.position(outIx);
+    } catch (IndexOutOfBoundsException e) {
+      // TODO(nathanmittler): Consider making the API throw IndexOutOfBoundsException instead.
+
+      // If we failed in the outer ASCII loop, outIx will not have been updated. In this case,
+      // use inIx to determine the bad write index.
+      int badWriteIndex = out.position() + Math.max(inIx, outIx - out.position() + 1);
+      throw new ArrayIndexOutOfBoundsException(
+          "Failed writing " + in.charAt(inIx) + " at index " + badWriteIndex);
+    }
+  }
+
+  private static int encodeUtf8Array(CharSequence in, byte[] out,
+                                     int offset, int length) {
+    int utf16Length = in.length();
+    int j = offset;
+    int i = 0;
+    int limit = offset + length;
+    // Designed to take advantage of
+    // https://wikis.oracle.com/display/HotSpotInternals/RangeCheckElimination
+    for (char c; i < utf16Length && i + j < limit && (c = in.charAt(i)) < 0x80; i++) {
+      out[j + i] = (byte) c;
+    }
+    if (i == utf16Length) {
+      return j + utf16Length;
+    }
+    j += i;
+    for (char c; i < utf16Length; i++) {
+      c = in.charAt(i);
+      if (c < 0x80 && j < limit) {
+        out[j++] = (byte) c;
+      } else if (c < 0x800 && j <= limit - 2) { // 11 bits, two UTF-8 bytes
+        out[j++] = (byte) ((0xF << 6) | (c >>> 6));
+        out[j++] = (byte) (0x80 | (0x3F & c));
+      } else if ((c < Character.MIN_SURROGATE || Character.MAX_SURROGATE < c) && j <= limit - 3) {
+        // Maximum single-char code point is 0xFFFF, 16 bits, three UTF-8 bytes
+        out[j++] = (byte) ((0xF << 5) | (c >>> 12));
+        out[j++] = (byte) (0x80 | (0x3F & (c >>> 6)));
+        out[j++] = (byte) (0x80 | (0x3F & c));
+      } else if (j <= limit - 4) {
+        // Minimum code point represented by a surrogate pair is 0x10000, 17 bits,
+        // four UTF-8 bytes
+        final char low;
+        if (i + 1 == in.length()
+                || !Character.isSurrogatePair(c, (low = in.charAt(++i)))) {
+          throw new UnpairedSurrogateException((i - 1), utf16Length);
+        }
+        int codePoint = Character.toCodePoint(c, low);
+        out[j++] = (byte) ((0xF << 4) | (codePoint >>> 18));
+        out[j++] = (byte) (0x80 | (0x3F & (codePoint >>> 12)));
+        out[j++] = (byte) (0x80 | (0x3F & (codePoint >>> 6)));
+        out[j++] = (byte) (0x80 | (0x3F & codePoint));
+      } else {
+        // If we are surrogates and we're not a surrogate pair, always throw an
+        // UnpairedSurrogateException instead of an ArrayOutOfBoundsException.
+        if ((Character.MIN_SURROGATE <= c && c <= Character.MAX_SURROGATE)
+                && (i + 1 == in.length()
+                        || !Character.isSurrogatePair(c, in.charAt(i + 1)))) {
+          throw new UnpairedSurrogateException(i, utf16Length);
+        }
+        throw new ArrayIndexOutOfBoundsException("Failed writing " + c + " at index " + j);
+      }
+    }
+    return j;
+  }
+
+  /**
+   * Encodes the given characters to the target {@link ByteBuffer} using UTF-8 encoding.
+   *
+   * <p>Selects an optimal algorithm based on the type of {@link ByteBuffer} (i.e. heap or direct)
+   * and the capabilities of the platform.
+   *
+   * @param in the source string to be encoded
+   * @param out the target buffer to receive the encoded string.
+   */
+  @Override
+  public void encodeUtf8(CharSequence in, ByteBuffer out) {
+    if (out.hasArray()) {
+      int start = out.arrayOffset();
+      int end = encodeUtf8Array(in, out.array(), start + out.position(),
+          out.remaining());
+      out.position(end - start);
+    } else {
+      encodeUtf8Buffer(in, out);
+    }
+  }
+
+  // These UTF-8 handling methods are copied from Guava's Utf8Unsafe class with
+  // a modification to throw a local exception. This exception can be caught
+  // to fallback to more lenient behavior.
+  static class UnpairedSurrogateException extends IllegalArgumentException {
+    UnpairedSurrogateException(int index, int length) {
+      super("Unpaired surrogate at index " + index + " of " + length);
+    }
+  }
+}
