diff --git a/CMake/PackageDebian.cmake b/CMake/PackageDebian.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..ebe893140a971f4036afb3d66e5e39838703bc47
--- /dev/null
+++ b/CMake/PackageDebian.cmake
@@ -0,0 +1,57 @@
+# ------------------- Debianization ---------------------
+if (UNIX)
+
+    # Set build environment
+    SET(CPACK_GENERATOR "TGZ;DEB")
+    SET(CPACK_SOURCE_TGZ "ON")
+
+    # Common package information
+    SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY
+        "FlatBuffers is an efficient cross platform serialization library for C++, with support for Java, C# and Go. It was created at Google specifically for game development and other performance-critical applications.")
+    SET(CPACK_DEBIAN_PACKAGE_HOMEPAGE "https://github.com/google/flatbuffers")
+    SET(CPACK_DEBIAN_PACKAGE_MAINTAINER "Vitaly Isaev <vitalyisaev2@gmail.com>")
+
+    # Derive package version from git
+    EXECUTE_PROCESS(
+        COMMAND date +%Y%m%d
+        OUTPUT_VARIABLE DATE
+        OUTPUT_STRIP_TRAILING_WHITESPACE
+    )
+    EXECUTE_PROCESS(
+      COMMAND git describe
+      WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+      OUTPUT_VARIABLE GIT_DESCRIBE_DIRTY
+      OUTPUT_STRIP_TRAILING_WHITESPACE
+    )
+    string(REGEX REPLACE "^v([0-9]+)\\..*" "\\1" VERSION_MAJOR "${GIT_DESCRIBE_DIRTY}")
+    string(REGEX REPLACE "^v[0-9]+\\.([0-9]+).*" "\\1" VERSION_MINOR "${GIT_DESCRIBE_DIRTY}")
+    string(REGEX REPLACE "^v[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" VERSION_PATCH "${GIT_DESCRIBE_DIRTY}")
+    string(REGEX REPLACE "^v[0-9]+\\.[0-9]+\\.[0-9]+\\-([0-9]+).*" "\\1" VERSION_COMMIT "${GIT_DESCRIBE_DIRTY}")
+    SET(CPACK_PACKAGE_VERSION_MAJOR ${VERSION_MAJOR})
+    SET(CPACK_PACKAGE_VERSION_MINOR ${VERSION_MINOR})
+    SET(CPACK_PACKAGE_VERSION_PATCH ${VERSION_PATCH})
+    SET(CPACK_PACKAGE_VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}-${VERSION_COMMIT}")
+    SET(CPACK_DEBIAN_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION}")
+
+    # Derive architecture
+    IF(NOT CPACK_DEBIAN_PACKAGE_ARCHITECTURE)
+      FIND_PROGRAM(DPKG_CMD dpkg)
+      IF(NOT DPKG_CMD)
+        MESSAGE(STATUS "Can not find dpkg in your path, default to i386.")
+        SET(CPACK_DEBIAN_PACKAGE_ARCHITECTURE i386)
+      ENDIF(NOT DPKG_CMD)
+      EXECUTE_PROCESS(COMMAND "${DPKG_CMD}" --print-architecture
+        OUTPUT_VARIABLE CPACK_DEBIAN_PACKAGE_ARCHITECTURE
+        OUTPUT_STRIP_TRAILING_WHITESPACE
+        )
+    ENDIF(NOT CPACK_DEBIAN_PACKAGE_ARCHITECTURE)
+
+    # Package name
+    SET(CPACK_DEBIAN_PACKAGE_NAME "flatbuffers")
+    SET(CPACK_RESOURCE_FILE_LICENSE ${CMAKE_SOURCE_DIR}/LICENSE.txt)
+    SET(CPACK_PACKAGE_FILE_NAME 
+        "${CPACK_DEBIAN_PACKAGE_NAME}_${CPACK_DEBIAN_PACKAGE_VERSION}_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}")
+
+endif(UNIX)
+
+INCLUDE(CPack)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 81c9e5837d7af4bc5c4784cfa00ab81a9a197d5e..1af3d3334159823e16fca5511161e0ef8a2ce416 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -44,6 +44,7 @@ set(FlatBuffers_Compiler_SRCS
   src/idl_gen_fbs.cpp
   src/idl_gen_grpc.cpp
   src/flatc.cpp
+  grpc/src/compiler/schema_interface.h
   grpc/src/compiler/cpp_generator.h
   grpc/src/compiler/cpp_generator.cc
 )
@@ -222,3 +223,7 @@ if(FLATBUFFERS_BUILD_TESTS)
 endif()
 
 include(CMake/BuildFlatBuffers.cmake)
+
+if(FLATBUFFERS_PACKAGE_DEBIAN)
+    include(CMake/PackageDebian.cmake)
+endif()
diff --git a/docs/source/doxyfile b/docs/source/doxyfile
index bef63f582770ddc49d98b6c9de189394685d203e..db3eeac7151b52f767543bbdbdb905a8e0005766 100755
--- a/docs/source/doxyfile
+++ b/docs/source/doxyfile
@@ -761,7 +761,7 @@ INPUT = "FlatBuffers.md" \
         "WhitePaper.md" \
         "Internals.md" \
         "Grammar.md" \
-        "CONTRIBUTING.md" \
+        "../../CONTRIBUTING.md" \
         "Tutorial.md" \
         "GoApi.md" \
         "groups" \
diff --git a/grpc/src/compiler/cpp_generator.cc b/grpc/src/compiler/cpp_generator.cc
index 9319c41934984ab32ac7a0f03eb17fbcdbf0e4f8..e8ad49e70de3ec379725266a51ffd13ee125f565 100644
--- a/grpc/src/compiler/cpp_generator.cc
+++ b/grpc/src/compiler/cpp_generator.cc
@@ -67,7 +67,8 @@ grpc::string FilenameIdentifier(const grpc::string &filename) {
 template<class T, size_t N>
 T *array_end(T (&array)[N]) { return array + N; }
 
-void PrintIncludes(Printer *printer, const std::vector<grpc::string>& headers, const Parameters &params) {
+void PrintIncludes(grpc_generator::Printer *printer, 
+                   const std::vector<grpc::string>& headers, const Parameters &params) {
   std::map<grpc::string, grpc::string> vars;
 
   vars["l"] = params.use_system_headers ? '<' : '"';
@@ -86,7 +87,7 @@ void PrintIncludes(Printer *printer, const std::vector<grpc::string>& headers, c
   }
 }
 
-grpc::string GetHeaderPrologue(File *file, const Parameters & /*params*/) {
+grpc::string GetHeaderPrologue(grpc_generator::File *file, const Parameters & /*params*/) {
   grpc::string output;
   {
     // Scope the output stream so it closes and finalizes output to the string.
@@ -111,7 +112,7 @@ grpc::string GetHeaderPrologue(File *file, const Parameters & /*params*/) {
   return output;
 }
 
-grpc::string GetHeaderIncludes(File *file,
+grpc::string GetHeaderIncludes(grpc_generator::File *file,
                                const Parameters &params) {
   grpc::string output;
   {
@@ -154,7 +155,7 @@ grpc::string GetHeaderIncludes(File *file,
 }
 
 void PrintHeaderClientMethodInterfaces(
-    Printer *printer, const Method *method,
+    grpc_generator::Printer *printer, const grpc_generator::Method *method,
     std::map<grpc::string, grpc::string> *vars, bool is_public) {
   (*vars)["Method"] = method->name();
   (*vars)["Request"] = method->input_type_name();
@@ -303,8 +304,8 @@ void PrintHeaderClientMethodInterfaces(
   }
 }
 
-void PrintHeaderClientMethod(Printer *printer,
-                             const Method *method,
+void PrintHeaderClientMethod(grpc_generator::Printer *printer,
+                             const grpc_generator::Method *method,
                              std::map<grpc::string, grpc::string> *vars,
                              bool is_public) {
   (*vars)["Method"] = method->name();
@@ -445,13 +446,13 @@ void PrintHeaderClientMethod(Printer *printer,
   }
 }
 
-void PrintHeaderClientMethodData(Printer *printer, const Method *method,
+void PrintHeaderClientMethodData(grpc_generator::Printer *printer, const grpc_generator::Method *method,
                                  std::map<grpc::string, grpc::string> *vars) {
   (*vars)["Method"] = method->name();
   printer->Print(*vars, "const ::grpc::RpcMethod rpcmethod_$Method$_;\n");
 }
 
-void PrintHeaderServerMethodSync(Printer *printer, const Method *method,
+void PrintHeaderServerMethodSync(grpc_generator::Printer *printer, const grpc_generator::Method *method,
                                  std::map<grpc::string, grpc::string> *vars) {
   (*vars)["Method"] = method->name();
   (*vars)["Request"] = method->input_type_name();
@@ -483,8 +484,8 @@ void PrintHeaderServerMethodSync(Printer *printer, const Method *method,
 }
 
 void PrintHeaderServerMethodAsync(
-    Printer *printer,
-    const Method *method,
+    grpc_generator::Printer *printer,
+    const grpc_generator::Method *method,
     std::map<grpc::string, grpc::string> *vars) {
   (*vars)["Method"] = method->name();
   (*vars)["Request"] = method->input_type_name();
@@ -599,8 +600,8 @@ void PrintHeaderServerMethodAsync(
 }
 
 void PrintHeaderServerMethodGeneric(
-    Printer *printer,
-    const Method *method,
+    grpc_generator::Printer *printer,
+    const grpc_generator::Method *method,
     std::map<grpc::string, grpc::string> *vars) {
   (*vars)["Method"] = method->name();
   (*vars)["Request"] = method->input_type_name();
@@ -669,8 +670,8 @@ void PrintHeaderServerMethodGeneric(
   printer->Print(*vars, "};\n");
 }
 
-void PrintHeaderService(Printer *printer,
-                        const Service *service,
+void PrintHeaderService(grpc_generator::Printer *printer,
+                        const grpc_generator::Service *service,
                         std::map<grpc::string, grpc::string> *vars) {
   (*vars)["Service"] = service->name();
 
@@ -764,7 +765,7 @@ void PrintHeaderService(Printer *printer,
   printer->Print("};\n");
 }
 
-grpc::string GetHeaderServices(File *file,
+grpc::string GetHeaderServices(grpc_generator::File *file,
                                const Parameters &params) {
   grpc::string output;
   {
@@ -795,7 +796,7 @@ grpc::string GetHeaderServices(File *file,
   return output;
 }
 
-grpc::string GetHeaderEpilogue(File *file, const Parameters & /*params*/) {
+grpc::string GetHeaderEpilogue(grpc_generator::File *file, const Parameters & /*params*/) {
   grpc::string output;
   {
     // Scope the output stream so it closes and finalizes output to the string.
@@ -821,7 +822,7 @@ grpc::string GetHeaderEpilogue(File *file, const Parameters & /*params*/) {
   return output;
 }
 
-grpc::string GetSourcePrologue(File *file, const Parameters & /*params*/) {
+grpc::string GetSourcePrologue(grpc_generator::File *file, const Parameters & /*params*/) {
   grpc::string output;
   {
     // Scope the output stream so it closes and finalizes output to the string.
@@ -845,7 +846,7 @@ grpc::string GetSourcePrologue(File *file, const Parameters & /*params*/) {
   return output;
 }
 
-grpc::string GetSourceIncludes(File *file,
+grpc::string GetSourceIncludes(grpc_generator::File *file,
                                const Parameters &params) {
   grpc::string output;
   {
@@ -880,8 +881,8 @@ grpc::string GetSourceIncludes(File *file,
   return output;
 }
 
-void PrintSourceClientMethod(Printer *printer,
-                             const Method *method,
+void PrintSourceClientMethod(grpc_generator::Printer *printer,
+                             const grpc_generator::Method *method,
                              std::map<grpc::string, grpc::string> *vars) {
   (*vars)["Method"] = method->name();
   (*vars)["Request"] = method->input_type_name();
@@ -981,8 +982,8 @@ void PrintSourceClientMethod(Printer *printer,
   }
 }
 
-void PrintSourceServerMethod(Printer *printer,
-                             const Method *method,
+void PrintSourceServerMethod(grpc_generator::Printer *printer,
+                             const grpc_generator::Method *method,
                              std::map<grpc::string, grpc::string> *vars) {
   (*vars)["Method"] = method->name();
   (*vars)["Request"] = method->input_type_name();
@@ -1040,8 +1041,8 @@ void PrintSourceServerMethod(Printer *printer,
   }
 }
 
-void PrintSourceService(Printer *printer,
-                        const Service *service,
+void PrintSourceService(grpc_generator::Printer *printer,
+                        const grpc_generator::Service *service,
                         std::map<grpc::string, grpc::string> *vars) {
   (*vars)["Service"] = service->name();
 
@@ -1153,7 +1154,7 @@ void PrintSourceService(Printer *printer,
   }
 }
 
-grpc::string GetSourceServices(File *file,
+grpc::string GetSourceServices(grpc_generator::File *file,
                                const Parameters &params) {
   grpc::string output;
   {
@@ -1182,7 +1183,7 @@ grpc::string GetSourceServices(File *file,
   return output;
 }
 
-grpc::string GetSourceEpilogue(File *file, const Parameters & /*params*/) {
+grpc::string GetSourceEpilogue(grpc_generator::File *file, const Parameters & /*params*/) {
   grpc::string temp;
 
   if (!file->package().empty()) {
diff --git a/grpc/src/compiler/cpp_generator.h b/grpc/src/compiler/cpp_generator.h
index 953ddfd569e0ccb1d2bc39d6dbe5d47b4e6f66eb..a4adee70ecc86a314efbe8026fa184c50f07dfdf 100644
--- a/grpc/src/compiler/cpp_generator.h
+++ b/grpc/src/compiler/cpp_generator.h
@@ -41,16 +41,7 @@
 #include <memory>
 #include <vector>
 
-#ifndef GRPC_CUSTOM_STRING
-#include <string>
-#define GRPC_CUSTOM_STRING std::string
-#endif
-
-namespace grpc {
-
-typedef GRPC_CUSTOM_STRING string;
-
-}  // namespace grpc
+#include "src/compiler/schema_interface.h"
 
 namespace grpc_cpp_generator {
 
@@ -64,83 +55,29 @@ struct Parameters {
   grpc::string grpc_search_path;
 };
 
-// An abstract interface representing a method.
-struct Method {
-  virtual ~Method() {}
-
-  virtual grpc::string name() const = 0;
-
-  virtual grpc::string input_type_name() const = 0;
-  virtual grpc::string output_type_name() const = 0;
-
-  virtual bool NoStreaming() const = 0;
-  virtual bool ClientOnlyStreaming() const = 0;
-  virtual bool ServerOnlyStreaming() const = 0;
-  virtual bool BidiStreaming() const = 0;
-};
-
-// An abstract interface representing a service.
-struct Service {
-  virtual ~Service() {}
-
-  virtual grpc::string name() const = 0;
-
-  virtual int method_count() const = 0;
-  virtual std::unique_ptr<const Method> method(int i) const = 0;
-};
-
-struct Printer {
-  virtual ~Printer() {}
-
-  virtual void Print(const std::map<grpc::string, grpc::string> &vars,
-                     const char *template_string) = 0;
-  virtual void Print(const char *string) = 0;
-  virtual void Indent() = 0;
-  virtual void Outdent() = 0;
-};
-
-// An interface that allows the source generated to be output using various
-// libraries/idls/serializers.
-struct File {
-  virtual ~File() {}
-
-  virtual grpc::string filename() const = 0;
-  virtual grpc::string filename_without_ext() const = 0;
-  virtual grpc::string message_header_ext() const = 0;
-  virtual grpc::string service_header_ext() const = 0;
-  virtual grpc::string package() const = 0;
-  virtual std::vector<grpc::string> package_parts() const = 0;
-  virtual grpc::string additional_headers() const = 0;
-
-  virtual int service_count() const = 0;
-  virtual std::unique_ptr<const Service> service(int i) const = 0;
-
-  virtual std::unique_ptr<Printer> CreatePrinter(grpc::string *str) const = 0;
-};
-
 // Return the prologue of the generated header file.
-grpc::string GetHeaderPrologue(File *file, const Parameters &params);
+grpc::string GetHeaderPrologue(grpc_generator::File *file, const Parameters &params);
 
 // Return the includes needed for generated header file.
-grpc::string GetHeaderIncludes(File *file, const Parameters &params);
+grpc::string GetHeaderIncludes(grpc_generator::File *file, const Parameters &params);
 
 // Return the includes needed for generated source file.
-grpc::string GetSourceIncludes(File *file, const Parameters &params);
+grpc::string GetSourceIncludes(grpc_generator::File *file, const Parameters &params);
 
 // Return the epilogue of the generated header file.
-grpc::string GetHeaderEpilogue(File *file, const Parameters &params);
+grpc::string GetHeaderEpilogue(grpc_generator::File *file, const Parameters &params);
 
 // Return the prologue of the generated source file.
-grpc::string GetSourcePrologue(File *file, const Parameters &params);
+grpc::string GetSourcePrologue(grpc_generator::File *file, const Parameters &params);
 
 // Return the services for generated header file.
-grpc::string GetHeaderServices(File *file, const Parameters &params);
+grpc::string GetHeaderServices(grpc_generator::File *file, const Parameters &params);
 
 // Return the services for generated source file.
-grpc::string GetSourceServices(File *file, const Parameters &params);
+grpc::string GetSourceServices(grpc_generator::File *file, const Parameters &params);
 
 // Return the epilogue of the generated source file.
-grpc::string GetSourceEpilogue(File *file, const Parameters &params);
+grpc::string GetSourceEpilogue(grpc_generator::File *file, const Parameters &params);
 
 }  // namespace grpc_cpp_generator
 
diff --git a/grpc/src/compiler/schema_interface.h b/grpc/src/compiler/schema_interface.h
new file mode 100644
index 0000000000000000000000000000000000000000..332a51a54fea82deb7ef21c52b5c5b6d81072e9c
--- /dev/null
+++ b/grpc/src/compiler/schema_interface.h
@@ -0,0 +1,108 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * 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.
+ *
+ */
+
+#ifndef GRPC_INTERNAL_COMPILER_SCHEMA_INTERFACE_H
+#define GRPC_INTERNAL_COMPILER_SCHEMA_INTERFACE_H
+
+ #include <memory>
+ #include <vector>
+
+ #ifndef GRPC_CUSTOM_STRING
+ #include <string>
+ #define GRPC_CUSTOM_STRING std::string
+ #endif
+
+namespace grpc {
+
+  typedef GRPC_CUSTOM_STRING string;
+
+}  // namespace grpc
+
+namespace grpc_generator {
+
+  // An abstract interface representing a method.
+  struct Method {
+    virtual ~Method() {}
+
+    virtual grpc::string name() const = 0;
+
+    virtual grpc::string input_type_name() const = 0;
+    virtual grpc::string output_type_name() const = 0;
+
+    virtual bool NoStreaming() const = 0;
+    virtual bool ClientOnlyStreaming() const = 0;
+    virtual bool ServerOnlyStreaming() const = 0;
+    virtual bool BidiStreaming() const = 0;
+  };
+
+  // An abstract interface representing a service.
+  struct Service {
+    virtual ~Service() {}
+
+    virtual grpc::string name() const = 0;
+
+    virtual int method_count() const = 0;
+    virtual std::unique_ptr<const Method> method(int i) const = 0;
+  };
+
+  struct Printer {
+    virtual ~Printer() {}
+
+    virtual void Print(const std::map<grpc::string, grpc::string> &vars,
+                       const char *template_string) = 0;
+    virtual void Print(const char *string) = 0;
+    virtual void Indent() = 0;
+    virtual void Outdent() = 0;
+  };
+
+  // An interface that allows the source generated to be output using various
+  // libraries/idls/serializers.
+  struct File {
+    virtual ~File() {}
+
+    virtual grpc::string filename() const = 0;
+    virtual grpc::string filename_without_ext() const = 0;
+    virtual grpc::string message_header_ext() const = 0;
+    virtual grpc::string service_header_ext() const = 0;
+    virtual grpc::string package() const = 0;
+    virtual std::vector<grpc::string> package_parts() const = 0;
+    virtual grpc::string additional_headers() const = 0;
+
+    virtual int service_count() const = 0;
+    virtual std::unique_ptr<const Service> service(int i) const = 0;
+
+    virtual std::unique_ptr<Printer> CreatePrinter(grpc::string *str) const = 0;
+  };
+} // namespace grpc_generator
+
+#endif  // GRPC_INTERNAL_COMPILER_SCHEMA_INTERFACE_H
diff --git a/include/flatbuffers/flatbuffers.h b/include/flatbuffers/flatbuffers.h
index 4644f9c600184a1e9f694d167af7ffbe6d464c54..b193b17911222c951028feeb7c04eecba2da7aba 100644
--- a/include/flatbuffers/flatbuffers.h
+++ b/include/flatbuffers/flatbuffers.h
@@ -1436,11 +1436,6 @@ class Struct FLATBUFFERS_FINAL_CLASS {
     return ReadScalar<T>(&data_[o]);
   }
 
-  template<typename T> T GetPointer(uoffset_t o) const {
-    auto p = &data_[o];
-    return reinterpret_cast<T>(p + ReadScalar<uoffset_t>(p));
-  }
-
   template<typename T> T GetStruct(uoffset_t o) const {
     return reinterpret_cast<T>(&data_[o]);
   }
diff --git a/include/flatbuffers/idl.h b/include/flatbuffers/idl.h
index 5909a4e20ae20d385537fa9507ca036394078ade..1c1e63494cd7a223c72ab1ad6b60463805b676ab 100644
--- a/include/flatbuffers/idl.h
+++ b/include/flatbuffers/idl.h
@@ -596,7 +596,9 @@ extern void GenComment(const std::vector<std::string> &dc,
 // if it is less than 0, no linefeeds will be generated either.
 // See idl_gen_text.cpp.
 // strict_json adds "quotes" around field names if true.
-extern void GenerateText(const Parser &parser,
+// If the flatbuffer cannot be encoded in JSON (e.g., it contains non-UTF-8
+// byte arrays in String values), returns false.
+extern bool GenerateText(const Parser &parser,
                          const void *flatbuffer,
                          std::string *text);
 extern bool GenerateTextFile(const Parser &parser,
diff --git a/java/com/google/flatbuffers/FlatBufferBuilder.java b/java/com/google/flatbuffers/FlatBufferBuilder.java
index 7ab24e10d0a575ae7829f0e67d99f497ca1cc944..fd4b729e6693efdd74fc57864cb3c357f8e11b11 100644
--- a/java/com/google/flatbuffers/FlatBufferBuilder.java
+++ b/java/com/google/flatbuffers/FlatBufferBuilder.java
@@ -367,6 +367,28 @@ public class FlatBufferBuilder {
     }
     /// @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.
      *
@@ -438,6 +460,20 @@ public class FlatBufferBuilder {
         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.
diff --git a/java/com/google/flatbuffers/Table.java b/java/com/google/flatbuffers/Table.java
index c9c6545616a7ee79db4080c4f12e6e66659956ad..b853842a77cd2311ae13b0a3d44437fd9c2da0ca 100644
--- a/java/com/google/flatbuffers/Table.java
+++ b/java/com/google/flatbuffers/Table.java
@@ -37,6 +37,12 @@ public class Table {
       return Charset.forName("UTF-8").newDecoder();
     }
   };
+  public final static ThreadLocal<Charset> UTF8_CHARSET = new ThreadLocal<Charset>() {
+    @Override
+    protected Charset initialValue() {
+      return Charset.forName("UTF-8");
+    }
+  };
   private final static ThreadLocal<CharBuffer> CHAR_BUFFER = new ThreadLocal<CharBuffer>();
   /** Used to hold the position of the `bb` buffer. */
   protected int bb_pos;
@@ -75,7 +81,7 @@ public class Table {
   protected int __indirect(int offset) {
     return offset + bb.getInt(offset);
   }
-  
+
   protected static int __indirect(int offset, ByteBuffer bb) {
     return offset + bb.getInt(offset);
   }
@@ -197,17 +203,21 @@ public class Table {
     }
     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, ByteBuffer bb) {
+  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];
-    Arrays.sort(off, (Integer o1, Integer o2) -> keysCompare(o1, o2, bb));
+    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];
   }
 
@@ -219,7 +229,7 @@ public class Table {
    * @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.
    *
@@ -242,7 +252,7 @@ public class Table {
     }
     return len_1 - len_2;
   }
-  
+
   /**
    * Compare string from the buffer with the 'String' object.
    *
diff --git a/net/FlatBuffers/ByteBuffer.cs b/net/FlatBuffers/ByteBuffer.cs
index 5fa1ac7a51d0603b638565615b711659ebf6c5dd..37a2c7e6ed3800153632424310cc44c0ebdf33ff 100755
--- a/net/FlatBuffers/ByteBuffer.cs
+++ b/net/FlatBuffers/ByteBuffer.cs
@@ -14,7 +14,20 @@
  * limitations under the License.
  */
 
-//#define UNSAFE_BYTEBUFFER  // uncomment this line to use faster ByteBuffer
+// There are 2 #defines that have an impact on performance of this ByteBuffer implementation
+//
+//      UNSAFE_BYTEBUFFER 
+//          This will use unsafe code to manipulate the underlying byte array. This
+//          can yield a reasonable performance increase.
+//
+//      BYTEBUFFER_NO_BOUNDS_CHECK
+//          This will disable the bounds check asserts to the byte array. This can
+//          yield a small performance gain in normal code..
+//
+// Using UNSAFE_BYTEBUFFER and BYTEBUFFER_NO_BOUNDS_CHECK together can yield a
+// performance gain of ~15% for some operations, however doing so is potentially 
+// dangerous. Do so at your own risk!
+//
 
 using System;
 
@@ -22,9 +35,6 @@ namespace FlatBuffers
 {
     /// <summary>
     /// Class to mimic Java's ByteBuffer which is used heavily in Flatbuffers.
-    /// If your execution environment allows unsafe code, you should enable
-    /// unsafe code in your project and #define UNSAFE_BYTEBUFFER to use a
-    /// MUCH faster version of ByteBuffer.
     /// </summary>
     public class ByteBuffer
     {
@@ -126,11 +136,14 @@ namespace FlatBuffers
         }
 #endif // !UNSAFE_BYTEBUFFER
 
+
         private void AssertOffsetAndLength(int offset, int length)
         {
+            #if !BYTEBUFFER_NO_BOUNDS_CHECK
             if (offset < 0 ||
                 offset > _buffer.Length - length)
                 throw new ArgumentOutOfRangeException();
+            #endif
         }
 
         public void PutSbyte(int offset, sbyte value)
@@ -200,7 +213,6 @@ namespace FlatBuffers
         public unsafe void PutUlong(int offset, ulong value)
         {
             AssertOffsetAndLength(offset, sizeof(ulong));
-
             fixed (byte* ptr = _buffer)
             {
                 *(ulong*)(ptr + offset) = BitConverter.IsLittleEndian
diff --git a/pom.xml b/pom.xml
index 8e32feec3310b1eafd2bebdb453a626010bcc9b2..86d7f5329ca3d9e3becc49e381e127765a0afc93 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.google.flatbuffers</groupId>
   <artifactId>flatbuffers-java</artifactId>
-  <version>1.3.0-SNAPSHOT</version>
+  <version>1.4.0-SNAPSHOT</version>
   <packaging>bundle</packaging>
   <name>FlatBuffers Java API</name>
   <description>
diff --git a/samples/sample_text.cpp b/samples/sample_text.cpp
index 557077d4bcfa5b99a823cddc1244a0df5dd8bc2b..d851120d1785db78930d59876816533b339ed7b8 100644
--- a/samples/sample_text.cpp
+++ b/samples/sample_text.cpp
@@ -46,7 +46,10 @@ int main(int /*argc*/, const char * /*argv*/[]) {
   // to ensure it is correct, we now generate text back from the binary,
   // and compare the two:
   std::string jsongen;
-  GenerateText(parser, parser.builder_.GetBufferPointer(), &jsongen);
+  if (!GenerateText(parser, parser.builder_.GetBufferPointer(), &jsongen)) {
+    printf("Couldn't serialize parsed data to JSON!\n");
+    return 1;
+  }
 
   if (jsongen != jsonfile) {
     printf("%s----------------\n%s", jsongen.c_str(), jsonfile.c_str());
diff --git a/src/flatc.cpp b/src/flatc.cpp
index 44ce91350ae971caa277837088e90c38ca8c11c4..5ca7ab3b512bdf0e5950bee2ee02a4fc5e5a0fea 100644
--- a/src/flatc.cpp
+++ b/src/flatc.cpp
@@ -19,7 +19,7 @@
 #include "flatbuffers/util.h"
 #include <limits>
 
-#define FLATC_VERSION "1.3.0 (" __DATE__ ")"
+#define FLATC_VERSION "1.4.0 (" __DATE__ ")"
 
 static void Error(const std::string &err, bool usage = false,
                   bool show_exe_name = true);
@@ -243,7 +243,7 @@ int main(int argc, const char *argv[]) {
             goto found;
           }
         }
-        Error("unknown commandline argument" + arg, true);
+        Error("unknown commandline argument: " + arg, true);
         found:;
       }
     } else {
diff --git a/src/idl_gen_cpp.cpp b/src/idl_gen_cpp.cpp
index edb14cc6bf97e59e961d94ef0d440a117a5250e6..74a6bf9a0c4fc8695cfe7c6acf71c1c20c22abc3 100644
--- a/src/idl_gen_cpp.cpp
+++ b/src/idl_gen_cpp.cpp
@@ -333,15 +333,15 @@ class CppGenerator : public BaseGenerator {
     return (opts.scoped_enums ? "enum class " : "enum ") + enum_def.name;
   }
 
-  static std::string GenEnumVal(const EnumDef &enum_def,
-                                const std::string &enum_val,
-                                const IDLOptions &opts) {
+  static std::string GenEnumValDecl(const EnumDef &enum_def,
+                                   const std::string &enum_val,
+                                   const IDLOptions &opts) {
     return opts.prefixed_enums ? enum_def.name + "_" + enum_val : enum_val;
   }
 
-  static std::string GetEnumVal(const EnumDef &enum_def,
-                                const EnumVal &enum_val,
-                                const IDLOptions &opts) {
+  static std::string GetEnumValUse(const EnumDef &enum_def,
+                                   const EnumVal &enum_val,
+                                   const IDLOptions &opts) {
     if (opts.scoped_enums) {
       return enum_def.name + "::" + enum_val.name;
     } else if (opts.prefixed_enums) {
@@ -396,7 +396,7 @@ class CppGenerator : public BaseGenerator {
          ++it) {
       auto &ev = **it;
       GenComment(ev.doc_comment, code_ptr, nullptr, "  ");
-      code += "  " + GenEnumVal(enum_def, ev.name, parser_.opts) + " = ";
+      code += "  " + GenEnumValDecl(enum_def, ev.name, parser_.opts) + " = ";
       code += NumToString(ev.value) + ",\n";
       minv = !minv || minv->value > ev.value ? &ev : minv;
       maxv = !maxv || maxv->value < ev.value ? &ev : maxv;
@@ -406,15 +406,15 @@ class CppGenerator : public BaseGenerator {
       assert(minv && maxv);
       if (enum_def.attributes.Lookup("bit_flags")) {
         if (minv->value != 0)  // If the user didn't defined NONE value
-          code += "  " + GenEnumVal(enum_def, "NONE", parser_.opts) + " = 0,\n";
+          code += "  " + GenEnumValDecl(enum_def, "NONE", parser_.opts) + " = 0,\n";
         if (maxv->value != anyv)  // If the user didn't defined ANY value
-          code += "  " + GenEnumVal(enum_def, "ANY", parser_.opts) + " = " +
+          code += "  " + GenEnumValDecl(enum_def, "ANY", parser_.opts) + " = " +
                   NumToString(anyv) + "\n";
       } else {  // MIN & MAX are useless for bit_flags
-        code += "  " + GenEnumVal(enum_def, "MIN", parser_.opts) + " = ";
-        code += GenEnumVal(enum_def, minv->name, parser_.opts) + ",\n";
-        code += "  " + GenEnumVal(enum_def, "MAX", parser_.opts) + " = ";
-        code += GenEnumVal(enum_def, maxv->name, parser_.opts) + "\n";
+        code += "  " + GenEnumValDecl(enum_def, "MIN", parser_.opts) + " = ";
+        code += GenEnumValDecl(enum_def, minv->name, parser_.opts) + ",\n";
+        code += "  " + GenEnumValDecl(enum_def, "MAX", parser_.opts) + " = ";
+        code += GenEnumValDecl(enum_def, maxv->name, parser_.opts) + "\n";
       }
     }
     code += "};\n";
@@ -429,7 +429,7 @@ class CppGenerator : public BaseGenerator {
       code += "  " + enum_def.name + " type;\n\n";
       code += "  flatbuffers::NativeTable *table;\n";
       code += "  " + enum_def.name + "Union() : type(";
-      code += GenEnumVal(enum_def, "NONE", parser_.opts);
+      code += GetEnumValUse(enum_def, *enum_def.vals.Lookup("NONE"), parser_.opts);
       code += "), table(nullptr) {}\n";
       code += "  " + enum_def.name + "Union(const ";
       code += enum_def.name + "Union &);\n";
@@ -445,7 +445,7 @@ class CppGenerator : public BaseGenerator {
           auto native_name = NativeName(WrapInNameSpace(*ev.struct_def));
           code += "  " + native_name + " *As";
           code += ev.name + "() { return type == ";
-          code += GetEnumVal(enum_def, ev, parser_.opts);
+          code += GetEnumValUse(enum_def, ev, parser_.opts);
           code += " ? reinterpret_cast<" + native_name;
           code += " *>(table) : nullptr; }\n";
         }
@@ -478,7 +478,7 @@ class CppGenerator : public BaseGenerator {
       code += "()[static_cast<int>(e)";
       if (enum_def.vals.vec.front()->value) {
         code += " - static_cast<int>(";
-        code += GetEnumVal(enum_def, *enum_def.vals.vec.front(), parser_.opts) +
+        code += GetEnumValUse(enum_def, *enum_def.vals.vec.front(), parser_.opts) +
                 ")";
       }
       code += "]; }\n\n";
@@ -500,7 +500,7 @@ class CppGenerator : public BaseGenerator {
     for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end();
          ++it) {
       auto &ev = **it;
-      code += "    case " + GetEnumVal(enum_def, ev, parser_.opts);
+      code += "    case " + GetEnumValUse(enum_def, ev, parser_.opts);
       if (!ev.value) {
         code += ": return true;\n";  // "NONE" enum value.
       } else {
@@ -518,7 +518,7 @@ class CppGenerator : public BaseGenerator {
       for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end();
            ++it) {
         auto &ev = **it;
-        code += "    case " + GetEnumVal(enum_def, ev, parser_.opts);
+        code += "    case " + GetEnumValUse(enum_def, ev, parser_.opts);
         if (!ev.value) {
           code += ": return nullptr;\n";  // "NONE" enum value.
         } else {
@@ -533,7 +533,7 @@ class CppGenerator : public BaseGenerator {
       for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end();
            ++it) {
         auto &ev = **it;
-        code += "    case " + GetEnumVal(enum_def, ev, parser_.opts);
+        code += "    case " + GetEnumValUse(enum_def, ev, parser_.opts);
         if (!ev.value) {
           code += ": return 0;\n";  // "NONE" enum value.
         } else {
@@ -553,7 +553,7 @@ class CppGenerator : public BaseGenerator {
            ++it) {
         auto &ev = **it;
         if (ev.value) {
-          code += "    case " + GenEnumVal(enum_def, ev.name, parser_.opts);
+          code += "    case " + GetEnumValUse(enum_def, ev, parser_.opts);
           code += ": delete reinterpret_cast<";
           code += NativeName(WrapInNameSpace(*ev.struct_def));
           code += " *>(table); break;\n";
@@ -613,7 +613,7 @@ class CppGenerator : public BaseGenerator {
       if (ev) {
         code += WrapInNameSpace(
             field.value.type.enum_def->defined_namespace,
-            GetEnumVal(*field.value.type.enum_def, *ev, parser_.opts));
+            GetEnumValUse(*field.value.type.enum_def, *ev, parser_.opts));
       } else {
         code += GenUnderlyingCast(field, true, field.value.constant);
       }
diff --git a/src/idl_gen_general.cpp b/src/idl_gen_general.cpp
index 88ec0db2555f94af119edbd3b8c3648e2e8ade83..274a22f5e36e3e164dd2ada9fae8041c4a6030c5 100644
--- a/src/idl_gen_general.cpp
+++ b/src/idl_gen_general.cpp
@@ -237,7 +237,7 @@ class GeneralGenerator : public BaseGenerator {
   // Save out the generated code for a single class while adding
   // declaration boilerplate.
   bool SaveType(const std::string &defname, const Namespace &ns,
-  	  const std::string &classcode, bool needs_includes) {
+      const std::string &classcode, bool needs_includes) {
     if (!classcode.length()) return true;
 
     std::string code;
@@ -684,8 +684,7 @@ std::string GenOffsetGetter(flatbuffers::FieldDef *key_field, const char *num =
     key_offset += num;
     key_offset += (lang_.language == IDLOptions::kCSharp ?
       ".Value, builder.DataBuffer)" : ", _bb)");
-  }
-  else {
+  } else {
     key_offset += GenByteBufferLength("bb");
     key_offset += " - tableOffset, bb)";
   }
@@ -694,23 +693,21 @@ std::string GenOffsetGetter(flatbuffers::FieldDef *key_field, const char *num =
 
 std::string GenLookupKeyGetter(flatbuffers::FieldDef *key_field) {
   std::string key_getter = "      ";
-  key_getter += "tableOffset = __indirect(vectorLocation + 4 * (start + middle)";
+  key_getter += "int tableOffset = __indirect(vectorLocation + 4 * (start + middle)";
   key_getter += ", bb);\n      ";
   if (key_field->value.type.base_type == BASE_TYPE_STRING) {
-    key_getter += "comp = " + FunctionStart('C') + "ompareStrings(";
+    key_getter += "int comp = " + FunctionStart('C') + "ompareStrings(";
     key_getter += GenOffsetGetter(key_field);
     key_getter += ", byteKey, bb);\n";
-  }
-  else {
+  } else {
     auto get_val = GenGetter(key_field->value.type) +
       "(" + GenOffsetGetter(key_field) + ")";
     if (lang_.language == IDLOptions::kCSharp) {
-      key_getter += "comp = " + get_val + ".CompareTo(key);\n";
-    }
-    else {
+      key_getter += "int comp = " + get_val + ".CompateTo(key);\n";
+    } else {
       key_getter += GenTypeGet(key_field->value.type) + " val = ";
       key_getter += get_val + ";\n";
-      key_getter += "      comp = val > key ? 1 : val < key ? -1 : 0;\n";
+      key_getter += "      int comp = val > key ? 1 : val < key ? -1 : 0;\n";
     }
   }
   return key_getter;
@@ -1215,8 +1212,7 @@ void GenStruct(StructDef &struct_def, std::string *code_ptr) {
       code += "); }\n";
     }
   }
-  if (struct_def.has_key && (lang_.language == IDLOptions::kJava ||
-    lang_.language == IDLOptions::kCSharp)) {
+  if (struct_def.has_key) {
     if (lang_.language == IDLOptions::kJava) {
       code += "\n  @Override\n  protected int keysCompare(";
       code += "Integer o1, Integer o2, ByteBuffer _bb) {";
@@ -1238,32 +1234,31 @@ void GenStruct(StructDef &struct_def, std::string *code_ptr) {
     code += "ookupByKey(" + GenVectorOffsetType();
     code += " vectorOffset, " + GenTypeGet(key_field->value.type);
     code += " key, ByteBuffer bb) {\n";
-    if (key_field->value.type.base_type == BASE_TYPE_STRING) {
-      code += "    byte[] byteKey = ";
-      if (lang_.language == IDLOptions::kJava)
-        code += "key.getBytes(java.nio.charset.StandardCharsets.UTF_8);\n";
-      else
-        code += "System.Text.Encoding.UTF8.GetBytes(key);\n";
-    }
+    code += "    byte[] byteKey = ";
+    if (lang_.language == IDLOptions::kJava)
+      code += "key.getBytes(Table.UTF8_CHARSET.get());\n";
+    else
+      code += "System.Text.Encoding.UTF8.GetBytes(key);\n";
     code += "    int vectorLocation = " + GenByteBufferLength("bb");
     code += " - vectorOffset";
     if (lang_.language == IDLOptions::kCSharp) code += ".Value";
     code += ";\n    int span = ";
-    code += "bb." + FunctionStart('G') + "etInt(vectorLocation), ";
-    code += "middle, start = 0, comp, tableOffset; \n";
+    code += "bb." + FunctionStart('G') + "etInt(vectorLocation);\n";
+    code += "    int start = 0;\n";
     code += "    vectorLocation += 4;\n";
     code += "    while (span != 0) {\n";
-    code += "      middle = span / 2;\n";
+    code += "      int middle = span / 2;\n";
     code += GenLookupKeyGetter(key_field);
-    code += "      if (comp > 0) span = middle;\n";
-    code += "      else if (comp < 0) {\n";
+    code += "      if (comp > 0) {\n";
+    code += "        span = middle;\n";
+    code += "      } else if (comp < 0) {\n";
     code += "        middle++;\n";
     code += "        start += middle;\n";
     code += "        span -= middle;\n";
-    code += "      }\n";
-    code += "      else return new " + struct_def.name;
+    code += "      } else {\n";
+    code += "        return new " + struct_def.name;
     code += "().__init(tableOffset, bb);\n";
-    code += "    }\n";
+    code += "      }\n    }\n";
     code += "    return null;\n";
     code += "  }\n";
   }
diff --git a/src/idl_gen_go.cpp b/src/idl_gen_go.cpp
index 573300980dad3be60ee5ceabfb7061c81b7c91a7..2df8c7b62314f1ae1a1396f5cafa08a7f97472ac 100644
--- a/src/idl_gen_go.cpp
+++ b/src/idl_gen_go.cpp
@@ -288,9 +288,6 @@ static void GetMemberOfVectorOfStruct(const StructDef &struct_def,
   if (!(vectortype.struct_def->fixed)) {
     code += "\t\tx = rcv._tab.Indirect(x)\n";
   }
-  code += "\t\tif obj == nil {\n";
-  code += "\t\t\tobj = new(" + TypeName(field) + ")\n";
-  code += "\t\t}\n";
   code += "\t\tobj.Init(rcv._tab.Bytes, x)\n";
   code += "\t\treturn true\n\t}\n";
   code += "\treturn false\n";
diff --git a/src/idl_gen_grpc.cpp b/src/idl_gen_grpc.cpp
index 6ada3e87394d77123f215e9c74e1607c7c5d1638..9bcd5bcfa5f32a78b1ead204114ddd1cf160dfa4 100644
--- a/src/idl_gen_grpc.cpp
+++ b/src/idl_gen_grpc.cpp
@@ -24,7 +24,7 @@
 
 namespace flatbuffers {
 
-class FlatBufMethod : public grpc_cpp_generator::Method {
+class FlatBufMethod : public grpc_generator::Method {
  public:
   enum Streaming { kNone, kClient, kServer, kBiDi };
 
@@ -62,7 +62,7 @@ class FlatBufMethod : public grpc_cpp_generator::Method {
   Streaming streaming_;
 };
 
-class FlatBufService : public grpc_cpp_generator::Service {
+class FlatBufService : public grpc_generator::Service {
  public:
   FlatBufService(const ServiceDef *service) : service_(service) {}
 
@@ -72,8 +72,8 @@ class FlatBufService : public grpc_cpp_generator::Service {
     return static_cast<int>(service_->calls.vec.size());
   };
 
-  std::unique_ptr<const grpc_cpp_generator::Method> method(int i) const {
-    return std::unique_ptr<const grpc_cpp_generator::Method>(
+  std::unique_ptr<const grpc_generator::Method> method(int i) const {
+    return std::unique_ptr<const grpc_generator::Method>(
           new FlatBufMethod(service_->calls.vec[i]));
   };
 
@@ -81,7 +81,7 @@ class FlatBufService : public grpc_cpp_generator::Service {
   const ServiceDef *service_;
 };
 
-class FlatBufPrinter : public grpc_cpp_generator::Printer {
+class FlatBufPrinter : public grpc_generator::Printer {
  public:
   FlatBufPrinter(std::string *str)
     : str_(str), escape_char_('$'), indent_(0) {}
@@ -133,7 +133,7 @@ class FlatBufPrinter : public grpc_cpp_generator::Printer {
   int indent_;
 };
 
-class FlatBufFile : public grpc_cpp_generator::File {
+class FlatBufFile : public grpc_generator::File {
  public:
   FlatBufFile(const Parser &parser, const std::string &file_name)
     : parser_(parser), file_name_(file_name) {}
@@ -163,13 +163,13 @@ class FlatBufFile : public grpc_cpp_generator::File {
     return static_cast<int>(parser_.services_.vec.size());
   };
 
-  std::unique_ptr<const grpc_cpp_generator::Service> service(int i) const {
-    return std::unique_ptr<const grpc_cpp_generator::Service> (
+  std::unique_ptr<const grpc_generator::Service> service(int i) const {
+    return std::unique_ptr<const grpc_generator::Service> (
           new FlatBufService(parser_.services_.vec[i]));
   }
 
-  std::unique_ptr<grpc_cpp_generator::Printer> CreatePrinter(std::string *str) const {
-    return std::unique_ptr<grpc_cpp_generator::Printer>(
+  std::unique_ptr<grpc_generator::Printer> CreatePrinter(std::string *str) const {
+    return std::unique_ptr<grpc_generator::Printer>(
           new FlatBufPrinter(str));
   }
 
diff --git a/src/idl_gen_text.cpp b/src/idl_gen_text.cpp
index 3e41a0a7683bb4803e1763fbeff4b74e2903c62c..4ff13c8a961138e87ff0547c2808183c9eddbf88 100644
--- a/src/idl_gen_text.cpp
+++ b/src/idl_gen_text.cpp
@@ -22,7 +22,7 @@
 
 namespace flatbuffers {
 
-static void GenStruct(const StructDef &struct_def, const Table *table,
+static bool GenStruct(const StructDef &struct_def, const Table *table,
                       int indent, const IDLOptions &opts,
                       std::string *_text);
 
@@ -48,7 +48,7 @@ void OutputIdentifier(const std::string &name, const IDLOptions &opts,
 // Print (and its template specialization below for pointers) generate text
 // for a single FlatBuffer value into JSON format.
 // The general case for scalars:
-template<typename T> void Print(T val, Type type, int /*indent*/,
+template<typename T> bool Print(T val, Type type, int /*indent*/,
                                 StructDef * /*union_sd*/,
                                 const IDLOptions &opts,
                                 std::string *_text) {
@@ -57,7 +57,7 @@ template<typename T> void Print(T val, Type type, int /*indent*/,
     auto enum_val = type.enum_def->ReverseLookup(static_cast<int>(val));
     if (enum_val) {
       OutputIdentifier(enum_val->name, opts, _text);
-      return;
+      return true;
     }
   }
 
@@ -66,10 +66,12 @@ template<typename T> void Print(T val, Type type, int /*indent*/,
   } else {
     text += NumToString(val);
   }
+
+  return true;
 }
 
 // Print a vector a sequence of JSON values, comma separated, wrapped in "[]".
-template<typename T> void PrintVector(const Vector<T> &v, Type type,
+template<typename T> bool PrintVector(const Vector<T> &v, Type type,
                                       int indent, const IDLOptions &opts,
                                       std::string *_text) {
   std::string &text = *_text;
@@ -81,19 +83,25 @@ template<typename T> void PrintVector(const Vector<T> &v, Type type,
       text += NewLine(opts);
     }
     text.append(indent + Indent(opts), ' ');
-    if (IsStruct(type))
-      Print(v.GetStructFromOffset(i * type.struct_def->bytesize), type,
-            indent + Indent(opts), nullptr, opts, _text);
-    else
-      Print(v[i], type, indent + Indent(opts), nullptr,
-            opts, _text);
+    if (IsStruct(type)) {
+      if (!Print(v.GetStructFromOffset(i * type.struct_def->bytesize), type,
+                 indent + Indent(opts), nullptr, opts, _text)) {
+        return false;
+      }
+    } else {
+      if (!Print(v[i], type, indent + Indent(opts), nullptr,
+                 opts, _text)) {
+        return false;
+      }
+    }
   }
   text += NewLine(opts);
   text.append(indent, ' ');
   text += "]";
+  return true;
 }
 
-static void EscapeString(const String &s, std::string *_text, const IDLOptions& opts) {
+static bool EscapeString(const String &s, std::string *_text, const IDLOptions& opts) {
   std::string &text = *_text;
   text += "\"";
   for (uoffset_t i = 0; i < s.size(); i++) {
@@ -118,9 +126,19 @@ static void EscapeString(const String &s, std::string *_text, const IDLOptions&
               text += "\\x";
               text += IntToStringHex(static_cast<uint8_t>(c), 2);
             } else {
-              // We previously checked for non-UTF-8 and returned a parse error,
-              // so we shouldn't reach here.
-              assert(0);
+              // There are two cases here:
+              //
+              // 1) We reached here by parsing an IDL file. In that case,
+              // we previously checked for non-UTF-8, so we shouldn't reach
+              // here.
+              //
+              // 2) We reached here by someone calling GenerateText()
+              // on a previously-serialized flatbuffer. The data might have
+              // non-UTF-8 Strings, or might be corrupt.
+              //
+              // In both cases, we have to give up and inform the caller
+              // they have no JSON.
+              return false;
             }
           } else {
             if (ucc <= 0xFFFF) {
@@ -145,10 +163,11 @@ static void EscapeString(const String &s, std::string *_text, const IDLOptions&
     }
   }
   text += "\"";
+  return true;
 }
 
 // Specialization of Print above for pointer types.
-template<> void Print<const void *>(const void *val,
+template<> bool Print<const void *>(const void *val,
                                     Type type, int indent,
                                     StructDef *union_sd,
                                     const IDLOptions &opts,
@@ -158,21 +177,27 @@ template<> void Print<const void *>(const void *val,
       // If this assert hits, you have an corrupt buffer, a union type field
       // was not present or was out of range.
       assert(union_sd);
-      GenStruct(*union_sd,
-                reinterpret_cast<const Table *>(val),
-                indent,
-                opts,
-                _text);
+      if (!GenStruct(*union_sd,
+                     reinterpret_cast<const Table *>(val),
+                     indent,
+                     opts,
+                     _text)) {
+        return false;
+      }
       break;
     case BASE_TYPE_STRUCT:
-      GenStruct(*type.struct_def,
-                reinterpret_cast<const Table *>(val),
-                indent,
-                opts,
-                _text);
+      if (!GenStruct(*type.struct_def,
+                     reinterpret_cast<const Table *>(val),
+                     indent,
+                     opts,
+                     _text)) {
+        return false;
+      }
       break;
     case BASE_TYPE_STRING: {
-      EscapeString(*reinterpret_cast<const String *>(val), _text, opts);
+      if (!EscapeString(*reinterpret_cast<const String *>(val), _text, opts)) {
+        return false;
+      }
       break;
     }
     case BASE_TYPE_VECTOR:
@@ -182,31 +207,35 @@ template<> void Print<const void *>(const void *val,
         #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, \
           PTYPE) \
           case BASE_TYPE_ ## ENUM: \
-            PrintVector<CTYPE>( \
-              *reinterpret_cast<const Vector<CTYPE> *>(val), \
-              type, indent, opts, _text); break;
+            if (!PrintVector<CTYPE>( \
+                  *reinterpret_cast<const Vector<CTYPE> *>(val), \
+                  type, indent, opts, _text)) { \
+              return false; \
+            } \
+            break;
           FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
         #undef FLATBUFFERS_TD
       }
       break;
     default: assert(0);
   }
+  return true;
 }
 
 // Generate text for a scalar field.
-template<typename T> static void GenField(const FieldDef &fd,
+template<typename T> static bool GenField(const FieldDef &fd,
                                           const Table *table, bool fixed,
                                           const IDLOptions &opts,
                                           int indent,
                                           std::string *_text) {
-  Print(fixed ?
+  return Print(fixed ?
     reinterpret_cast<const Struct *>(table)->GetField<T>(fd.value.offset) :
     table->GetField<T>(fd.value.offset, 0), fd.value.type, indent, nullptr,
                                             opts, _text);
 }
 
 // Generate text for non-scalar field.
-static void GenFieldOffset(const FieldDef &fd, const Table *table, bool fixed,
+static bool GenFieldOffset(const FieldDef &fd, const Table *table, bool fixed,
                            int indent, StructDef *union_sd,
                            const IDLOptions &opts, std::string *_text) {
   const void *val = nullptr;
@@ -220,12 +249,12 @@ static void GenFieldOffset(const FieldDef &fd, const Table *table, bool fixed,
       ? table->GetStruct<const void *>(fd.value.offset)
       : table->GetPointer<const void *>(fd.value.offset);
   }
-  Print(val, fd.value.type, indent, union_sd, opts, _text);
+  return Print(val, fd.value.type, indent, union_sd, opts, _text);
 }
 
 // Generate text for a struct or table, values separated by commas, indented,
 // and bracketed by "{}"
-static void GenStruct(const StructDef &struct_def, const Table *table,
+static bool GenStruct(const StructDef &struct_def, const Table *table,
                       int indent, const IDLOptions &opts,
                       std::string *_text) {
   std::string &text = *_text;
@@ -253,8 +282,10 @@ static void GenStruct(const StructDef &struct_def, const Table *table,
            #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, \
              PTYPE) \
              case BASE_TYPE_ ## ENUM: \
-                GenField<CTYPE>(fd, table, struct_def.fixed, \
-                                opts, indent + Indent(opts), _text); \
+                if (!GenField<CTYPE>(fd, table, struct_def.fixed, \
+                                     opts, indent + Indent(opts), _text)) { \
+                  return false; \
+                } \
                 break;
             FLATBUFFERS_GEN_TYPES_SCALAR(FLATBUFFERS_TD)
           #undef FLATBUFFERS_TD
@@ -264,8 +295,10 @@ static void GenStruct(const StructDef &struct_def, const Table *table,
             case BASE_TYPE_ ## ENUM:
             FLATBUFFERS_GEN_TYPES_POINTER(FLATBUFFERS_TD)
           #undef FLATBUFFERS_TD
-              GenFieldOffset(fd, table, struct_def.fixed, indent + Indent(opts),
-                             union_sd, opts, _text);
+              if (!GenFieldOffset(fd, table, struct_def.fixed, indent + Indent(opts),
+                                  union_sd, opts, _text)) {
+                return false;
+              }
               break;
         }
         if (fd.value.type.base_type == BASE_TYPE_UTYPE) {
@@ -284,20 +317,24 @@ static void GenStruct(const StructDef &struct_def, const Table *table,
   text += NewLine(opts);
   text.append(indent, ' ');
   text += "}";
+  return true;
 }
 
 // Generate a text representation of a flatbuffer in JSON format.
-void GenerateText(const Parser &parser, const void *flatbuffer,
+bool GenerateText(const Parser &parser, const void *flatbuffer,
                   std::string *_text) {
   std::string &text = *_text;
   assert(parser.root_struct_def_);  // call SetRootType()
   text.reserve(1024);   // Reduce amount of inevitable reallocs.
-  GenStruct(*parser.root_struct_def_,
-            GetRoot<Table>(flatbuffer),
-            0,
-            parser.opts,
-            _text);
+  if (!GenStruct(*parser.root_struct_def_,
+                 GetRoot<Table>(flatbuffer),
+                 0,
+                 parser.opts,
+                 _text)) {
+    return false;
+  }
   text += NewLine(parser.opts);
+  return true;
 }
 
 std::string TextFileName(const std::string &path,
@@ -310,7 +347,9 @@ bool GenerateTextFile(const Parser &parser,
                       const std::string &file_name) {
   if (!parser.builder_.GetSize() || !parser.root_struct_def_) return true;
   std::string text;
-  GenerateText(parser, parser.builder_.GetBufferPointer(), &text);
+  if (!GenerateText(parser, parser.builder_.GetBufferPointer(), &text)) {
+    return false;
+  }
   return flatbuffers::SaveFile(TextFileName(path, file_name).c_str(),
                                text,
                                false);
diff --git a/tests/FlatBuffers.Test/ByteBufferTests.cs b/tests/FlatBuffers.Test/ByteBufferTests.cs
index b86c36587b2244d34d997be1b2a09b05efaa27c0..3324f12a3c23b3b1d3a189502fbf9b84c738d416 100644
--- a/tests/FlatBuffers.Test/ByteBufferTests.cs
+++ b/tests/FlatBuffers.Test/ByteBufferTests.cs
@@ -40,6 +40,7 @@ namespace FlatBuffers.Test
             Assert.AreEqual((byte)99, buffer[0]);
         }
 
+#if !BYTEBUFFER_NO_BOUNDS_CHECK
         [FlatBuffersTestMethod]
         public void ByteBuffer_PutByteCannotPutAtOffsetPastLength()
         {
@@ -47,6 +48,7 @@ namespace FlatBuffers.Test
             var uut = new ByteBuffer(buffer);
             Assert.Throws<ArgumentOutOfRangeException>(() => uut.PutByte(1, 99));
         }
+#endif
 
         [FlatBuffersTestMethod]
         public void ByteBuffer_PutShortPopulatesBufferCorrectly()
@@ -60,6 +62,7 @@ namespace FlatBuffers.Test
             Assert.AreEqual((byte)0, buffer[1]);
         }
 
+#if !BYTEBUFFER_NO_BOUNDS_CHECK
         [FlatBuffersTestMethod]
         public void ByteBuffer_PutShortCannotPutAtOffsetPastLength()
         {
@@ -67,7 +70,9 @@ namespace FlatBuffers.Test
             var uut = new ByteBuffer(buffer);
             Assert.Throws<ArgumentOutOfRangeException>(() => uut.PutShort(2, 99));
         }
+#endif
 
+#if !BYTEBUFFER_NO_BOUNDS_CHECK
         [FlatBuffersTestMethod]
         public void ByteBuffer_PutShortChecksLength()
         {
@@ -83,6 +88,7 @@ namespace FlatBuffers.Test
             var uut = new ByteBuffer(buffer);
             Assert.Throws<ArgumentOutOfRangeException>(() => uut.PutShort(1, 99));
         }
+#endif
 
         [FlatBuffersTestMethod]
         public void ByteBuffer_PutIntPopulatesBufferCorrectly()
@@ -98,6 +104,7 @@ namespace FlatBuffers.Test
             Assert.AreEqual(0x0A, buffer[3]);
         }
 
+ #if !BYTEBUFFER_NO_BOUNDS_CHECK
         [FlatBuffersTestMethod]
         public void ByteBuffer_PutIntCannotPutAtOffsetPastLength()
         {
@@ -121,6 +128,7 @@ namespace FlatBuffers.Test
             var uut = new ByteBuffer(buffer);
             Assert.Throws<ArgumentOutOfRangeException>(() => uut.PutInt(2, 0x0A0B0C0D));
         }
+#endif
 
         [FlatBuffersTestMethod]
         public void ByteBuffer_PutLongPopulatesBufferCorrectly()
@@ -140,6 +148,7 @@ namespace FlatBuffers.Test
             Assert.AreEqual(0x01, buffer[7]);
         }
 
+#if !BYTEBUFFER_NO_BOUNDS_CHECK
         [FlatBuffersTestMethod]
         public void ByteBuffer_PutLongCannotPutAtOffsetPastLength()
         {
@@ -163,6 +172,7 @@ namespace FlatBuffers.Test
             var uut = new ByteBuffer(buffer);
             Assert.Throws<ArgumentOutOfRangeException>(() => uut.PutLong(2, 0x010203040A0B0C0D));
         }
+#endif
 
         [FlatBuffersTestMethod]
         public void ByteBuffer_GetByteReturnsCorrectData()
@@ -173,6 +183,7 @@ namespace FlatBuffers.Test
             Assert.AreEqual((byte)99, uut.Get(0));
         }
 
+#if !BYTEBUFFER_NO_BOUNDS_CHECK
         [FlatBuffersTestMethod]
         public void ByteBuffer_GetByteChecksOffset()
         {
@@ -180,6 +191,7 @@ namespace FlatBuffers.Test
             var uut = new ByteBuffer(buffer);
             Assert.Throws<ArgumentOutOfRangeException>(()=>uut.Get(1));
         }
+#endif
 
         [FlatBuffersTestMethod]
         public void ByteBuffer_GetShortReturnsCorrectData()
@@ -191,6 +203,7 @@ namespace FlatBuffers.Test
             Assert.AreEqual(1, uut.GetShort(0));
         }
 
+#if !BYTEBUFFER_NO_BOUNDS_CHECK
         [FlatBuffersTestMethod]
         public void ByteBuffer_GetShortChecksOffset()
         {
@@ -206,6 +219,7 @@ namespace FlatBuffers.Test
             var uut = new ByteBuffer(buffer);
             Assert.Throws<ArgumentOutOfRangeException>(() => uut.GetShort(1));
         }
+#endif
 
         [FlatBuffersTestMethod]
         public void ByteBuffer_GetIntReturnsCorrectData()
@@ -219,6 +233,7 @@ namespace FlatBuffers.Test
             Assert.AreEqual(0x0A0B0C0D, uut.GetInt(0));
         }
 
+#if !BYTEBUFFER_NO_BOUNDS_CHECK
         [FlatBuffersTestMethod]
         public void ByteBuffer_GetIntChecksOffset()
         {
@@ -234,6 +249,7 @@ namespace FlatBuffers.Test
             var uut = new ByteBuffer(buffer);
             Assert.Throws<ArgumentOutOfRangeException>(() => uut.GetInt(0));
         }
+#endif
 
         [FlatBuffersTestMethod]
         public void ByteBuffer_GetLongReturnsCorrectData()
@@ -251,6 +267,7 @@ namespace FlatBuffers.Test
             Assert.AreEqual(0x010203040A0B0C0D, uut.GetLong(0));
         }
 
+#if !BYTEBUFFER_NO_BOUNDS_CHECK
         [FlatBuffersTestMethod]
         public void ByteBuffer_GetLongChecksOffset()
         {
@@ -266,6 +283,7 @@ namespace FlatBuffers.Test
             var uut = new ByteBuffer(buffer);
             Assert.Throws<ArgumentOutOfRangeException>(() => uut.GetLong(0));
         }
+#endif
 
         [FlatBuffersTestMethod]
         public void ByteBuffer_ReverseBytesUshort()
diff --git a/tests/JavaTest.java b/tests/JavaTest.java
index 9f46f3fae4ce3a30f1d0db1ddfca4733d7c85e49..d53e97327ae0a10bf619ab3555905a18d8903712 100755
--- a/tests/JavaTest.java
+++ b/tests/JavaTest.java
@@ -185,6 +185,10 @@ class JavaTest {
 
         TestNestedFlatBuffer();
 
+        TestCreateByteVector();
+
+        TestCreateUninitializedVector();
+
         System.out.println("FlatBuffers test: completed successfully");
     }
 
@@ -305,6 +309,44 @@ class JavaTest {
         TestEq(nestedMonsterName, nestedMonster.name());
     }
 
+    static void TestCreateByteVector() {
+        FlatBufferBuilder fbb = new FlatBufferBuilder(16);
+        int str = fbb.createString("MyMonster");
+        byte[] inventory = new byte[] { 0, 1, 2, 3, 4 };
+        int vec = fbb.createByteVector(inventory);
+        Monster.startMonster(fbb);
+        Monster.addInventory(fbb, vec);
+        Monster.addName(fbb, str);
+        int monster1 = Monster.endMonster(fbb);
+        Monster.finishMonsterBuffer(fbb, monster1);
+        Monster monsterObject = Monster.getRootAsMonster(fbb.dataBuffer());
+
+        TestEq(monsterObject.inventory(1), (int)inventory[1]);
+        TestEq(monsterObject.inventoryLength(), inventory.length);
+        TestEq(ByteBuffer.wrap(inventory), monsterObject.inventoryAsByteBuffer());
+    }
+
+    static void TestCreateUninitializedVector() {
+        FlatBufferBuilder fbb = new FlatBufferBuilder(16);
+        int str = fbb.createString("MyMonster");
+        byte[] inventory = new byte[] { 0, 1, 2, 3, 4 };
+        ByteBuffer bb = fbb.createUnintializedVector(1, inventory.length, 1);
+        for (byte i:inventory) {
+            bb.put(i);
+        }
+        int vec = fbb.endVector();
+        Monster.startMonster(fbb);
+        Monster.addInventory(fbb, vec);
+        Monster.addName(fbb, str);
+        int monster1 = Monster.endMonster(fbb);
+        Monster.finishMonsterBuffer(fbb, monster1);
+        Monster monsterObject = Monster.getRootAsMonster(fbb.dataBuffer());
+
+        TestEq(monsterObject.inventory(1), (int)inventory[1]);
+        TestEq(monsterObject.inventoryLength(), inventory.length);
+        TestEq(ByteBuffer.wrap(inventory), monsterObject.inventoryAsByteBuffer());
+    }
+
     static <T> void TestEq(T a, T b) {
         if (!a.equals(b)) {
             System.out.println("" + a.getClass().getName() + " " + b.getClass().getName());
diff --git a/tests/MyGame/Example/Monster.cs b/tests/MyGame/Example/Monster.cs
index 95a303cf414fc0f39872a96ee8c412fa451998ba..1883659f6b36b345a731b9af00442812b47bdf7b 100644
--- a/tests/MyGame/Example/Monster.cs
+++ b/tests/MyGame/Example/Monster.cs
@@ -129,7 +129,7 @@ public sealed class Monster : Table {
     return new Offset<Monster>(o);
   }
   public static void FinishMonsterBuffer(FlatBufferBuilder builder, Offset<Monster> offset) { builder.Finish(offset.Value, "MONS"); }
-  
+
   public static VectorOffset CreateMySortedVectorOfTables(FlatBufferBuilder builder, Offset<Monster>[] offsets) {
     Array.Sort(offsets, (Offset<Monster> o1, Offset<Monster> o2) => CompareStrings(__offset(10, o1.Value, builder.DataBuffer), __offset(10, o2.Value, builder.DataBuffer), builder.DataBuffer));
     return builder.CreateVectorOfTables(offsets);
@@ -138,19 +138,22 @@ public sealed class Monster : Table {
   public static Monster LookupByKey(VectorOffset vectorOffset, string key, ByteBuffer bb) {
     byte[] byteKey = System.Text.Encoding.UTF8.GetBytes(key);
     int vectorLocation = bb.Length - vectorOffset.Value;
-    int span = bb.GetInt(vectorLocation), middle, start = 0, comp, tableOffset; 
+    int span = bb.GetInt(vectorLocation);
+    int start = 0;
     vectorLocation += 4;
     while (span != 0) {
       int middle = span / 2;
-      tableOffset = __indirect(vectorLocation + 4 * (start + middle), bb);
-      comp = CompareStrings(__offset(10, bb.Length - tableOffset, bb), byteKey, bb);
-      if (comp > 0) span = middle;
-      else if (comp < 0) {
+      int tableOffset = __indirect(vectorLocation + 4 * (start + middle), bb);
+      int comp = CompareStrings(__offset(10, bb.Length - tableOffset, bb), byteKey, bb);
+      if (comp > 0) {
+        span = middle;
+      } else if (comp < 0) {
         middle++;
         start += middle;
         span -= middle;
+      } else {
+        return new Monster().__init(tableOffset, bb);
       }
-      else return new Monster().__init(tableOffset, bb);
     }
     return null;
   }
diff --git a/tests/MyGame/Example/Monster.go b/tests/MyGame/Example/Monster.go
index 7ba062fdca31d2f3fab1488a216126a00f40587b..8ffbb7d0714b4f38a3987b0669f80d4188c74589 100644
--- a/tests/MyGame/Example/Monster.go
+++ b/tests/MyGame/Example/Monster.go
@@ -131,9 +131,6 @@ func (rcv *Monster) Test4(obj *Test, j int) bool {
 	if o != 0 {
 		x := rcv._tab.Vector(o)
 		x += flatbuffers.UOffsetT(j) * 4
-		if obj == nil {
-			obj = new(Test)
-		}
 		obj.Init(rcv._tab.Bytes, x)
 		return true
 	}
@@ -173,9 +170,6 @@ func (rcv *Monster) Testarrayoftables(obj *Monster, j int) bool {
 		x := rcv._tab.Vector(o)
 		x += flatbuffers.UOffsetT(j) * 4
 		x = rcv._tab.Indirect(x)
-		if obj == nil {
-			obj = new(Monster)
-		}
 		obj.Init(rcv._tab.Bytes, x)
 		return true
 	}
diff --git a/tests/MyGame/Example/Monster.java b/tests/MyGame/Example/Monster.java
index 0633dff08a51e13e91c8154597325d518a109279..a4c16d8aeea644761fa141e13ad6c409c65bc3df 100644
--- a/tests/MyGame/Example/Monster.java
+++ b/tests/MyGame/Example/Monster.java
@@ -140,21 +140,24 @@ public final class Monster extends Table {
   protected int keysCompare(Integer o1, Integer o2, ByteBuffer _bb) { return compareStrings(__offset(10, o1, _bb), __offset(10, o2, _bb), _bb); }
 
   public static Monster lookupByKey(int vectorOffset, String key, ByteBuffer bb) {
-    byte[] byteKey = key.getBytes(StandardCharsets.UTF_8);
-    int vectorLocation = bb.array().length - vectorOffset.Value;
-    int span = bb.getInt(vectorLocation), middle, start = 0, comp, tableOffset; 
+    byte[] byteKey = key.getBytes(Table.UTF8_CHARSET.get());
+    int vectorLocation = bb.array().length - vectorOffset;
+    int span = bb.getInt(vectorLocation);
+    int start = 0;
     vectorLocation += 4;
     while (span != 0) {
       int middle = span / 2;
-      tableOffset = __indirect(vectorLocation + 4 * (start + middle), bb);
-      comp = compareStrings(__offset(10, bb.array().length - tableOffset, bb), byteKey, bb);
-      if (comp > 0) span = middle;
-      else if (comp < 0) {
+      int tableOffset = __indirect(vectorLocation + 4 * (start + middle), bb);
+      int comp = compareStrings(__offset(10, bb.array().length - tableOffset, bb), byteKey, bb);
+      if (comp > 0) {
+        span = middle;
+      } else if (comp < 0) {
         middle++;
         start += middle;
         span -= middle;
+      } else {
+        return new Monster().__init(tableOffset, bb);
       }
-      else return new Monster().__init(tableOffset, bb);
     }
     return null;
   }
diff --git a/tests/test.cpp b/tests/test.cpp
index fd2352bd18bb011618e27ba1b93ba47b59456729..45eb1fe2561df7bc5b872f9a1651c14b3d3904a5 100644
--- a/tests/test.cpp
+++ b/tests/test.cpp
@@ -410,7 +410,8 @@ void ParseAndGenerateTextTest() {
   // to ensure it is correct, we now generate text back from the binary,
   // and compare the two:
   std::string jsongen;
-  GenerateText(parser, parser.builder_.GetBufferPointer(), &jsongen);
+  auto result = GenerateText(parser, parser.builder_.GetBufferPointer(), &jsongen);
+  TEST_EQ(result, true);
 
   if (jsongen != jsonfile) {
     printf("%s----------------\n%s", jsongen.c_str(), jsonfile.c_str());
@@ -827,7 +828,8 @@ void FuzzTest2() {
 
   std::string jsongen;
   parser.opts.indent_step = 0;
-  GenerateText(parser, parser.builder_.GetBufferPointer(), &jsongen);
+  auto result = GenerateText(parser, parser.builder_.GetBufferPointer(), &jsongen);
+  TEST_EQ(result, true);
 
   if (jsongen != json) {
     // These strings are larger than a megabyte, so we show the bytes around
@@ -987,7 +989,8 @@ void UnicodeTest() {
           true);
   std::string jsongen;
   parser.opts.indent_step = -1;
-  GenerateText(parser, parser.builder_.GetBufferPointer(), &jsongen);
+  auto result = GenerateText(parser, parser.builder_.GetBufferPointer(), &jsongen);
+  TEST_EQ(result, true);
   TEST_EQ(jsongen,
           std::string(
             "{F: \"\\u20AC\\u00A2\\u30E6\\u30FC\\u30B6\\u30FC"
@@ -1003,13 +1006,31 @@ void UnicodeTestAllowNonUTF8() {
                        "\\u5225\\u30B5\\u30A4\\u30C8\\x01\\x80\\u0080\\uD83D\\uDE0E\" }"), true);
   std::string jsongen;
   parser.opts.indent_step = -1;
-  GenerateText(parser, parser.builder_.GetBufferPointer(), &jsongen);
+  auto result = GenerateText(parser, parser.builder_.GetBufferPointer(), &jsongen);
+  TEST_EQ(result, true);
   TEST_EQ(jsongen,
           std::string(
             "{F: \"\\u20AC\\u00A2\\u30E6\\u30FC\\u30B6\\u30FC"
             "\\u5225\\u30B5\\u30A4\\u30C8\\u0001\\x80\\u0080\\uD83D\\uDE0E\"}"));
 }
 
+void UnicodeTestGenerateTextFailsOnNonUTF8() {
+  flatbuffers::Parser parser;
+  // Allow non-UTF-8 initially to model what happens when we load a binary flatbuffer from disk
+  // which contains non-UTF-8 strings.
+  parser.opts.allow_non_utf8 = true;
+  TEST_EQ(parser.Parse("table T { F:string; }"
+                       "root_type T;"
+                       "{ F:\"\\u20AC\\u00A2\\u30E6\\u30FC\\u30B6\\u30FC"
+                       "\\u5225\\u30B5\\u30A4\\u30C8\\x01\\x80\\u0080\\uD83D\\uDE0E\" }"), true);
+  std::string jsongen;
+  parser.opts.indent_step = -1;
+  // Now, disallow non-UTF-8 (the default behavior) so GenerateText indicates failure.
+  parser.opts.allow_non_utf8 = false;
+  auto result = GenerateText(parser, parser.builder_.GetBufferPointer(), &jsongen);
+  TEST_EQ(result, false);
+}
+
 void UnicodeSurrogatesTest() {
   flatbuffers::Parser parser;
 
@@ -1157,7 +1178,8 @@ void UnknownFieldsTest() {
 
   std::string jsongen;
   parser.opts.indent_step = -1;
-  GenerateText(parser, parser.builder_.GetBufferPointer(), &jsongen);
+  auto result = GenerateText(parser, parser.builder_.GetBufferPointer(), &jsongen);
+  TEST_EQ(result, true);
   TEST_EQ(jsongen == "{str: \"test\",i: 10}", true);
 }
 
@@ -1222,6 +1244,7 @@ int main(int /*argc*/, const char * /*argv*/[]) {
   IntegerOutOfRangeTest();
   UnicodeTest();
   UnicodeTestAllowNonUTF8();
+  UnicodeTestGenerateTextFailsOnNonUTF8();
   UnicodeSurrogatesTest();
   UnicodeInvalidSurrogatesTest();
   InvalidUTF8Test();