diff --git a/bindings/java/unicorn/MemRegion.java b/bindings/java/unicorn/MemRegion.java
new file mode 100755
index 00000000..b729b3a9
--- /dev/null
+++ b/bindings/java/unicorn/MemRegion.java
@@ -0,0 +1,37 @@
+/*
+
+Java bindings for the Unicorn Emulator Engine
+
+Copyright(c) 2016 Chris Eagle
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+version 2 as published by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+*/
+
+package unicorn;
+
+public class MemRegion {
+
+   public long begin;
+   public long end;
+   public int perms;
+
+   public MemRegion(long begin, long end, int perms) {
+      this.begin = begin;
+      this.end = end;
+      this.perms = perms;
+   }
+
+}
+
diff --git a/bindings/java/unicorn/Unicorn.java b/bindings/java/unicorn/Unicorn.java
old mode 100644
new mode 100755
index 5a28c267..f1a5d15f
--- a/bindings/java/unicorn/Unicorn.java
+++ b/bindings/java/unicorn/Unicorn.java
@@ -288,7 +288,7 @@ public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, S
  *
  * @param  arch  Architecture type (UC_ARCH_*)
  * @param  mode  Hardware mode. This is combined of UC_MODE_*
- * @see    unicorn.UnicornArchs, unicorn.UnicornModes
+ * @see    unicorn.UnicornConst
  *
  */
    public Unicorn(int arch, int mode) throws UnicornException {
@@ -327,7 +327,7 @@ public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, S
  *
  *  @param   arch   Architecture type (UC_ARCH_*)
  *  @return  true if this library supports the given arch.
- *  @see     unicorn.UnicornArchs
+ *  @see     unicorn.UnicornConst
  */
    public native static boolean arch_supported(int arch);
 
@@ -337,12 +337,23 @@ public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, S
  */
    public native void close() throws UnicornException;
    
+/**
+ * Query internal status of engine.
+ *
+ * @param   type     query type. See UC_QUERY_*
+ * @param   result   save the internal status queried
+ * 
+ * @return: error code. see UC_ERR_*
+ * @see     unicorn.UnicornConst
+ */
+   public native int query(int type) throws UnicornException;
+
 /**
  * Report the last error number when some API function fail.
  * Like glibc's errno, uc_errno might not retain its old value once accessed.
  *
  * @return Error code of uc_err enum type (UC_ERR_*, see above)
- * @see unicorn.UnicornErrors
+ * @see unicorn.UnicornConst
  */
    public native int errno();
 
@@ -351,7 +362,7 @@ public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, S
  *
  * @param  code   Error code (see UC_ERR_* above)
  * @return Returns a String that describes the error code
- * @see unicorn.UnicornErrors
+ * @see unicorn.UnicornConst
  */
    public native static String strerror(int code);
 
@@ -625,6 +636,19 @@ public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, S
  */
    public native void mem_map(long address, long size, int perms) throws UnicornException;
 
+/**
+ *  Map existing host memory in for emulation.
+ *  This API adds a memory region that can be used by emulation.
+ *
+ * @param address Base address of the memory range
+ * @param size    Size of the memory block.
+ * @param perms   Permissions on the memory block. A combination of UC_PROT_READ, UC_PROT_WRITE, UC_PROT_EXEC
+ * @param ptr     Block of host memory backing the newly mapped memory. This block is
+ *                expected to be an equal or larger size than provided, and be mapped with at
+ *                least PROT_READ | PROT_WRITE. If it is not, the resulting behavior is undefined.
+ */
+   public native void mem_map_ptr(long address, long size, int perms, byte[] block) throws UnicornException;
+
 /**
  * Unmap a range of memory.
  *
@@ -642,5 +666,13 @@ public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, S
  */
    public native void mem_protect(long address, long size, int perms) throws UnicornException;
 
+/**
+ * Retrieve all memory regions mapped by mem_map() and mem_map_ptr()
+ * NOTE: memory regions may be split by mem_unmap()
+ * 
+ * @return  list of mapped regions.
+*/
+   public native MemRegion[] mem_regions() throws UnicornException;
+
 }
 
diff --git a/bindings/java/unicorn_Unicorn.c b/bindings/java/unicorn_Unicorn.c
old mode 100644
new mode 100755
index a14bd9e4..01af31ee
--- a/bindings/java/unicorn_Unicorn.c
+++ b/bindings/java/unicorn_Unicorn.c
@@ -244,7 +244,28 @@ JNIEXPORT jboolean JNICALL Java_unicorn_Unicorn_arch_1supported
 JNIEXPORT void JNICALL Java_unicorn_Unicorn_close
   (JNIEnv *env, jobject self) {
    uc_engine *eng = getEngine(env, self);
-   uc_close(eng);
+   uc_err err = uc_close(eng);
+   if (err != UC_ERR_OK) {
+      throwException(env, err);
+   }
+   //We also need to ReleaseByteArrayElements for any regions that 
+   //were mapped with uc_mem_map_ptr
+}
+
+/*
+ * Class:     unicorn_Unicorn
+ * Method:    query
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_unicorn_Unicorn_query
+  (JNIEnv *env, jobject self, jint type) {
+   uc_engine *eng = getEngine(env, self);
+   size_t result;
+   uc_err err = uc_query(eng, type, &result);
+   if (err != UC_ERR_OK) {
+      throwException(env, err);
+   }
+   return (jint)result;
 }
 
 /*
@@ -508,6 +529,24 @@ JNIEXPORT void JNICALL Java_unicorn_Unicorn_mem_1map
    }
 }
 
+/*
+ * Class:     unicorn_Unicorn
+ * Method:    mem_map_ptr
+ * Signature: (JJI[B)V
+ */
+JNIEXPORT void JNICALL Java_unicorn_Unicorn_mem_1map_1ptr
+  (JNIEnv *env, jobject self, jlong address, jlong size, jint perms, jbyteArray block) {
+   uc_engine *eng = getEngine(env, self);
+   jbyte *array = (*env)->GetByteArrayElements(env, block, NULL);
+   uc_err err = uc_mem_map_ptr(eng, (uint64_t)address, (size_t)size, (uint32_t)perms, (void*)array);
+   if (err != UC_ERR_OK) {
+      throwException(env, err);
+   }
+   //Need to track address/block/array so that we can ReleaseByteArrayElements when the
+   //block gets unmapped or when uc_close gets called
+   //(*env)->ReleaseByteArrayElements(env, block, array, JNI_ABORT);
+}
+
 /*
  * Class:     unicorn_Unicorn
  * Method:    mem_unmap
@@ -521,6 +560,9 @@ JNIEXPORT void JNICALL Java_unicorn_Unicorn_mem_1unmap
    if (err != UC_ERR_OK) {
       throwException(env, err);
    }
+
+   //If a region was mapped using uc_mem_map_ptr, we also need to
+   //ReleaseByteArrayElements for that region
 }
 
 /*
@@ -537,3 +579,35 @@ JNIEXPORT void JNICALL Java_unicorn_Unicorn_mem_1protect
       throwException(env, err);
    }
 }
+
+/*
+ * Class:     unicorn_Unicorn
+ * Method:    mem_regions
+ * Signature: ()[Lunicorn/MemRegion;
+ */
+JNIEXPORT jobjectArray JNICALL Java_unicorn_Unicorn_mem_1regions
+  (JNIEnv *env, jobject self) {
+   uc_engine *eng = getEngine(env, self);
+
+   uc_mem_region *regions = NULL;
+   uint32_t count = 0;
+   uint32_t i;
+
+   uc_err err = uc_mem_regions(eng, &regions, &count);
+   if (err != UC_ERR_OK) {
+      throwException(env, err);
+   }
+   jclass clz = (*env)->FindClass(env, "unicorn/MemRegion");
+   if ((*env)->ExceptionCheck(env)) {
+      return NULL;
+   }
+   jobjectArray result = (*env)->NewObjectArray(env, (jsize)count, clz, NULL);
+   jmethodID cons = (*env)->GetMethodID(env, clz, "<init>", "(JJI)V");
+   for (i = 0; i < count; i++) {
+      jobject mr = (*env)->NewObject(env, clz, cons, regions[i].begin, regions[i].end, regions[i].perms);
+      (*env)->SetObjectArrayElement(env, result, (jsize)i, mr);
+   }
+   free(regions);
+   
+   return result;
+}