You are viewing a plain text version of this content. The canonical link for it is here.
Posted to hdfs-commits@hadoop.apache.org by at...@apache.org on 2012/08/06 23:02:31 UTC

svn commit: r1370015 [3/3] - in /hadoop/common/trunk/hadoop-hdfs-project/hadoop-hdfs: ./ src/ src/main/native/libhdfs/

Modified: hadoop/common/trunk/hadoop-hdfs-project/hadoop-hdfs/src/main/native/libhdfs/hdfs.h
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-hdfs-project/hadoop-hdfs/src/main/native/libhdfs/hdfs.h?rev=1370015&r1=1370014&r2=1370015&view=diff
==============================================================================
--- hadoop/common/trunk/hadoop-hdfs-project/hadoop-hdfs/src/main/native/libhdfs/hdfs.h (original)
+++ hadoop/common/trunk/hadoop-hdfs-project/hadoop-hdfs/src/main/native/libhdfs/hdfs.h Mon Aug  6 21:02:30 2012
@@ -252,7 +252,9 @@ extern  "C" {
      * hdfsDisconnect - Disconnect from the hdfs file system.
      * Disconnect from hdfs.
      * @param fs The configured filesystem handle.
-     * @return Returns 0 on success, -1 on error.  
+     * @return Returns 0 on success, -1 on error.
+     *         Even if there is an error, the resources associated with the
+     *         hdfsFS will be freed.
      */
     int hdfsDisconnect(hdfsFS fs);
         
@@ -280,6 +282,10 @@ extern  "C" {
      * @param fs The configured filesystem handle.
      * @param file The file handle.
      * @return Returns 0 on success, -1 on error.  
+     *         On error, errno will be set appropriately.
+     *         If the hdfs file was valid, the memory associated with it will
+     *         be freed at the end of this call, even if there was an I/O
+     *         error.
      */
     int hdfsCloseFile(hdfsFS fs, hdfsFile file);
 
@@ -336,8 +342,7 @@ extern  "C" {
      * @param position Position from which to read
      * @param buffer The buffer to copy read bytes into.
      * @param length The length of the buffer.
-     * @return Returns the number of bytes actually read, possibly less than
-     * than length;-1 on error.
+     * @return      See hdfsRead
      */
     tSize hdfsPread(hdfsFS fs, hdfsFile file, tOffset position,
                     void* buffer, tSize length);

Modified: hadoop/common/trunk/hadoop-hdfs-project/hadoop-hdfs/src/main/native/libhdfs/jni_helper.c
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-hdfs-project/hadoop-hdfs/src/main/native/libhdfs/jni_helper.c?rev=1370015&r1=1370014&r2=1370015&view=diff
==============================================================================
--- hadoop/common/trunk/hadoop-hdfs-project/hadoop-hdfs/src/main/native/libhdfs/jni_helper.c (original)
+++ hadoop/common/trunk/hadoop-hdfs-project/hadoop-hdfs/src/main/native/libhdfs/jni_helper.c Mon Aug  6 21:02:30 2012
@@ -17,6 +17,7 @@
  */
 
 #include "config.h"
+#include "exception.h"
 #include "jni_helper.h"
 
 #include <stdio.h> 
@@ -85,16 +86,57 @@ static void hdfsThreadDestructor(void *v
     free(tls);
 }
 
+void destroyLocalReference(JNIEnv *env, jobject jObject)
+{
+  if (jObject)
+    (*env)->DeleteLocalRef(env, jObject);
+}
 
-static int validateMethodType(MethType methType)
+static jthrowable validateMethodType(JNIEnv *env, MethType methType)
 {
     if (methType != STATIC && methType != INSTANCE) {
-        fprintf(stderr, "Unimplemented method type\n");
-        return 0;
+        return newRuntimeError(env, "validateMethodType(methType=%d): "
+            "illegal method type.\n", methType);
     }
-    return 1;
+    return NULL;
 }
 
+jthrowable newJavaStr(JNIEnv *env, const char *str, jstring *out)
+{
+    jstring jstr;
+
+    if (!str) {
+        /* Can't pass NULL to NewStringUTF: the result would be
+         * implementation-defined. */
+        *out = NULL;
+        return NULL;
+    }
+    jstr = (*env)->NewStringUTF(env, str);
+    if (!jstr) {
+        /* If NewStringUTF returns NULL, an exception has been thrown,
+         * which we need to handle.  Probaly an OOM. */
+        return getPendingExceptionAndClear(env);
+    }
+    *out = jstr;
+    return NULL;
+}
+
+jthrowable newCStr(JNIEnv *env, jstring jstr, char **out)
+{
+    const char *tmp;
+
+    if (!jstr) {
+        *out = NULL;
+        return NULL;
+    }
+    tmp = (*env)->GetStringUTFChars(env, jstr, NULL);
+    if (!tmp) {
+        return getPendingExceptionAndClear(env);
+    }
+    *out = strdup(tmp);
+    (*env)->ReleaseStringUTFChars(env, jstr, tmp);
+    return NULL;
+}
 
 static int hashTableInit(void)
 {
@@ -156,7 +198,7 @@ static void* searchEntryFromTable(const 
 
 
 
-int invokeMethod(JNIEnv *env, RetVal *retval, Exc *exc, MethType methType,
+jthrowable invokeMethod(JNIEnv *env, jvalue *retval, MethType methType,
                  jobject instObj, const char *className,
                  const char *methName, const char *methSignature, ...)
 {
@@ -167,21 +209,16 @@ int invokeMethod(JNIEnv *env, RetVal *re
     const char *str; 
     char returnType;
     
-    if (! validateMethodType(methType)) {
-      return -1;
-    }
-    cls = globalClassReference(className, env);
-    if (cls == NULL) {
-      return -2;
-    }
-
-    mid = methodIdFromClass(className, methName, methSignature, 
-                            methType, env);
-    if (mid == NULL) {
-        (*env)->ExceptionDescribe(env);
-        return -3;
-    }
-   
+    jthr = validateMethodType(env, methType);
+    if (jthr)
+        return jthr;
+    jthr = globalClassReference(className, env, &cls);
+    if (jthr)
+        return jthr;
+    jthr = methodIdFromClass(className, methName, methSignature, 
+                            methType, env, &mid);
+    if (jthr)
+        return jthr;
     str = methSignature;
     while (*str != ')') str++;
     str++;
@@ -248,43 +285,14 @@ int invokeMethod(JNIEnv *env, RetVal *re
     va_end(args);
 
     jthr = (*env)->ExceptionOccurred(env);
-    if (jthr != NULL) {
-        if (exc != NULL)
-            *exc = jthr;
-        else
-            (*env)->ExceptionDescribe(env);
-        return -1;
+    if (jthr) {
+        (*env)->ExceptionClear(env);
+        return jthr;
     }
-    return 0;
-}
-
-jarray constructNewArrayString(JNIEnv *env, Exc *exc, const char **elements, int size) {
-  const char *className = "java/lang/String";
-  jobjectArray result;
-  int i;
-  jclass arrCls = (*env)->FindClass(env, className);
-  if (arrCls == NULL) {
-    fprintf(stderr, "could not find class %s\n",className);
-    return NULL; /* exception thrown */
-  }
-  result = (*env)->NewObjectArray(env, size, arrCls,
-                                  NULL);
-  if (result == NULL) {
-    fprintf(stderr, "ERROR: could not construct new array\n");
-    return NULL; /* out of memory error thrown */
-  }
-  for (i = 0; i < size; i++) {
-    jstring jelem = (*env)->NewStringUTF(env,elements[i]);
-    if (jelem == NULL) {
-      fprintf(stderr, "ERROR: jelem == NULL\n");
-    }
-    (*env)->SetObjectArrayElement(env, result, i, jelem);
-    (*env)->DeleteLocalRef(env, jelem);
-  }
-  return result;
+    return NULL;
 }
 
-jobject constructNewObjectOfClass(JNIEnv *env, Exc *exc, const char *className, 
+jthrowable constructNewObjectOfClass(JNIEnv *env, jobject *out, const char *className, 
                                   const char *ctorSignature, ...)
 {
     va_list args;
@@ -293,50 +301,37 @@ jobject constructNewObjectOfClass(JNIEnv
     jobject jobj;
     jthrowable jthr;
 
-    cls = globalClassReference(className, env);
-    if (cls == NULL) {
-        (*env)->ExceptionDescribe(env);
-      return NULL;
-    }
-
-    mid = methodIdFromClass(className, "<init>", ctorSignature, 
-                            INSTANCE, env);
-    if (mid == NULL) {
-        (*env)->ExceptionDescribe(env);
-        return NULL;
-    } 
+    jthr = globalClassReference(className, env, &cls);
+    if (jthr)
+        return jthr;
+    jthr = methodIdFromClass(className, "<init>", ctorSignature, 
+                            INSTANCE, env, &mid);
+    if (jthr)
+        return jthr;
     va_start(args, ctorSignature);
     jobj = (*env)->NewObjectV(env, cls, mid, args);
     va_end(args);
-    jthr = (*env)->ExceptionOccurred(env);
-    if (jthr != NULL) {
-        if (exc != NULL)
-            *exc = jthr;
-        else
-            (*env)->ExceptionDescribe(env);
-    }
-    return jobj;
+    if (!jobj)
+        return getPendingExceptionAndClear(env);
+    *out = jobj;
+    return NULL;
 }
 
 
-
-
-jmethodID methodIdFromClass(const char *className, const char *methName, 
+jthrowable methodIdFromClass(const char *className, const char *methName, 
                             const char *methSignature, MethType methType, 
-                            JNIEnv *env)
+                            JNIEnv *env, jmethodID *out)
 {
-    jclass cls = globalClassReference(className, env);
-    if (cls == NULL) {
-      fprintf(stderr, "could not find class %s\n", className);
-      return NULL;
-    }
+    jclass cls;
+    jthrowable jthr;
 
+    jthr = globalClassReference(className, env, &cls);
+    if (jthr)
+        return jthr;
     jmethodID mid = 0;
-    if (!validateMethodType(methType)) {
-      fprintf(stderr, "invalid method type\n");
-      return NULL;
-    }
-
+    jthr = validateMethodType(env, methType);
+    if (jthr)
+        return jthr;
     if (methType == STATIC) {
         mid = (*env)->GetStaticMethodID(env, cls, methName, methSignature);
     }
@@ -344,72 +339,88 @@ jmethodID methodIdFromClass(const char *
         mid = (*env)->GetMethodID(env, cls, methName, methSignature);
     }
     if (mid == NULL) {
-      fprintf(stderr, "could not find method %s from class %s with signature %s\n",methName, className, methSignature);
+        fprintf(stderr, "could not find method %s from class %s with "
+            "signature %s\n", methName, className, methSignature);
+        return getPendingExceptionAndClear(env);
     }
-    return mid;
+    *out = mid;
+    return NULL;
 }
 
-
-jclass globalClassReference(const char *className, JNIEnv *env)
+jthrowable globalClassReference(const char *className, JNIEnv *env, jclass *out)
 {
     jclass clsLocalRef;
     jclass cls = searchEntryFromTable(className);
     if (cls) {
-        return cls; 
+        *out = cls;
+        return NULL;
     }
-
     clsLocalRef = (*env)->FindClass(env,className);
     if (clsLocalRef == NULL) {
-        (*env)->ExceptionDescribe(env);
-        return NULL;
+        return getPendingExceptionAndClear(env);
     }
     cls = (*env)->NewGlobalRef(env, clsLocalRef);
     if (cls == NULL) {
-        (*env)->ExceptionDescribe(env);
-        return NULL;
+        (*env)->DeleteLocalRef(env, clsLocalRef);
+        return getPendingExceptionAndClear(env);
     }
     (*env)->DeleteLocalRef(env, clsLocalRef);
     insertEntryIntoTable(className, cls);
-    return cls;
+    *out = cls;
+    return NULL;
 }
 
-
-char *classNameOfObject(jobject jobj, JNIEnv *env) {
-    jclass cls, clsClass;
+jthrowable classNameOfObject(jobject jobj, JNIEnv *env, char **name)
+{
+    jthrowable jthr;
+    jclass cls, clsClass = NULL;
     jmethodID mid;
-    jstring str;
-    const char *cstr;
+    jstring str = NULL;
+    const char *cstr = NULL;
     char *newstr;
 
     cls = (*env)->GetObjectClass(env, jobj);
     if (cls == NULL) {
-        (*env)->ExceptionDescribe(env);
-        return NULL;
+        jthr = getPendingExceptionAndClear(env);
+        goto done;
     }
     clsClass = (*env)->FindClass(env, "java/lang/Class");
     if (clsClass == NULL) {
-        (*env)->ExceptionDescribe(env);
-        return NULL;
+        jthr = getPendingExceptionAndClear(env);
+        goto done;
     }
     mid = (*env)->GetMethodID(env, clsClass, "getName", "()Ljava/lang/String;");
     if (mid == NULL) {
-        (*env)->ExceptionDescribe(env);
-        return NULL;
+        jthr = getPendingExceptionAndClear(env);
+        goto done;
     }
     str = (*env)->CallObjectMethod(env, cls, mid);
     if (str == NULL) {
-        (*env)->ExceptionDescribe(env);
-        return NULL;
+        jthr = getPendingExceptionAndClear(env);
+        goto done;
     }
-
     cstr = (*env)->GetStringUTFChars(env, str, NULL);
+    if (!cstr) {
+        jthr = getPendingExceptionAndClear(env);
+        goto done;
+    }
     newstr = strdup(cstr);
-    (*env)->ReleaseStringUTFChars(env, str, cstr);
     if (newstr == NULL) {
-        perror("classNameOfObject: strdup");
-        return NULL;
+        jthr = newRuntimeError(env, "classNameOfObject: out of memory");
+        goto done;
+    }
+    *name = newstr;
+    jthr = NULL;
+
+done:
+    destroyLocalReference(env, cls);
+    destroyLocalReference(env, clsClass);
+    if (str) {
+        if (cstr)
+            (*env)->ReleaseStringUTFChars(env, str, cstr);
+        (*env)->DeleteLocalRef(env, str);
     }
-    return newstr;
+    return jthr;
 }
 
 
@@ -429,6 +440,7 @@ static JNIEnv* getGlobalJNIEnv(void)
     JNIEnv *env;
     jint rv = 0; 
     jint noVMs = 0;
+    jthrowable jthr;
 
     rv = JNI_GetCreatedJavaVMs(&(vmBuf[0]), vmBufLength, &noVMs);
     if (rv != 0) {
@@ -501,10 +513,11 @@ static JNIEnv* getGlobalJNIEnv(void)
                     "with error: %d\n", rv);
             return NULL;
         }
-        if (invokeMethod(env, NULL, NULL, STATIC, NULL,
+        jthr = invokeMethod(env, NULL, STATIC, NULL,
                          "org/apache/hadoop/fs/FileSystem",
-                         "loadFileSystems", "()V") != 0) {
-            (*env)->ExceptionDescribe(env);
+                         "loadFileSystems", "()V");
+        if (jthr) {
+            printExceptionAndFree(env, jthr, PRINT_EXC_ALL, "loadFileSystems");
         }
     }
     else {

Modified: hadoop/common/trunk/hadoop-hdfs-project/hadoop-hdfs/src/main/native/libhdfs/jni_helper.h
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-hdfs-project/hadoop-hdfs/src/main/native/libhdfs/jni_helper.h?rev=1370015&r1=1370014&r2=1370015&view=diff
==============================================================================
--- hadoop/common/trunk/hadoop-hdfs-project/hadoop-hdfs/src/main/native/libhdfs/jni_helper.h (original)
+++ hadoop/common/trunk/hadoop-hdfs-project/hadoop-hdfs/src/main/native/libhdfs/jni_helper.h Mon Aug  6 21:02:30 2012
@@ -37,14 +37,35 @@ typedef enum {
     INSTANCE
 } MethType;
 
+/**
+ * Create a new malloc'ed C string from a Java string.
+ *
+ * @param env       The JNI environment
+ * @param jstr      The Java string
+ * @param out       (out param) the malloc'ed C string
+ *
+ * @return          NULL on success; the exception otherwise
+ */
+jthrowable newCStr(JNIEnv *env, jstring jstr, char **out);
 
-/** Used for returning an appropriate return value after invoking
- * a method
+/**
+ * Create a new Java string from a C string.
+ *
+ * @param env       The JNI environment
+ * @param str       The C string
+ * @param out       (out param) the java string
+ *
+ * @return          NULL on success; the exception otherwise
  */
-typedef jvalue RetVal;
+jthrowable newJavaStr(JNIEnv *env, const char *str, jstring *out);
 
-/** Used for returning the exception after invoking a method */
-typedef jthrowable Exc;
+/**
+ * Helper function to destroy a local reference of java.lang.Object
+ * @param env: The JNIEnv pointer. 
+ * @param jFile: The local reference of java.lang.Object object
+ * @return None.
+ */
+void destroyLocalReference(JNIEnv *env, jobject jObject);
 
 /** invokeMethod: Invoke a Static or Instance method.
  * className: Name of the class where the method can be found
@@ -63,33 +84,27 @@ typedef jthrowable Exc;
  * RETURNS: -1 on error and 0 on success. If -1 is returned, exc will have 
    a valid exception reference, and the result stored at retval is undefined.
  */
-int invokeMethod(JNIEnv *env, RetVal *retval, Exc *exc, MethType methType,
+jthrowable invokeMethod(JNIEnv *env, jvalue *retval, MethType methType,
                  jobject instObj, const char *className, const char *methName, 
                  const char *methSignature, ...);
 
-/** constructNewObjectOfClass: Invoke a constructor.
- * className: Name of the class
- * ctorSignature: the signature of the constructor "(arg-types)V"
- * env: The JNIEnv pointer
- * exc: If the ctor throws any exception, this will contain the reference
- * Arguments to the ctor must be passed after ctorSignature 
- */
-jobject constructNewObjectOfClass(JNIEnv *env, Exc *exc, const char *className, 
+jthrowable constructNewObjectOfClass(JNIEnv *env, jobject *out, const char *className, 
                                   const char *ctorSignature, ...);
 
-jmethodID methodIdFromClass(const char *className, const char *methName, 
+jthrowable methodIdFromClass(const char *className, const char *methName, 
                             const char *methSignature, MethType methType, 
-                            JNIEnv *env);
+                            JNIEnv *env, jmethodID *out);
 
-jclass globalClassReference(const char *className, JNIEnv *env);
+jthrowable globalClassReference(const char *className, JNIEnv *env, jclass *out);
 
 /** classNameOfObject: Get an object's class name.
  * @param jobj: The object.
  * @param env: The JNIEnv pointer.
- * @return Returns a pointer to a string containing the class name. This string
- * must be freed by the caller.
+ * @param name: (out param) On success, will contain a string containing the
+ * class name. This string must be freed by the caller.
+ * @return NULL on success, or the exception
  */
-char *classNameOfObject(jobject jobj, JNIEnv *env);
+jthrowable classNameOfObject(jobject jobj, JNIEnv *env, char **name);
 
 /** getJNIEnv: A helper function to get the JNIEnv* for the given thread.
  * If no JVM exists, then one will be created. JVM command line arguments
@@ -99,8 +114,6 @@ char *classNameOfObject(jobject jobj, JN
  * */
 JNIEnv* getJNIEnv(void);
 
-jarray constructNewArrayString(JNIEnv *env, Exc *exc, const char **elements, int size) ;
-
 #endif /*LIBHDFS_JNI_HELPER_H*/
 
 /**

Modified: hadoop/common/trunk/hadoop-hdfs-project/hadoop-hdfs/src/main/native/libhdfs/native_mini_dfs.c
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-hdfs-project/hadoop-hdfs/src/main/native/libhdfs/native_mini_dfs.c?rev=1370015&r1=1370014&r2=1370015&view=diff
==============================================================================
--- hadoop/common/trunk/hadoop-hdfs-project/hadoop-hdfs/src/main/native/libhdfs/native_mini_dfs.c (original)
+++ hadoop/common/trunk/hadoop-hdfs-project/hadoop-hdfs/src/main/native/libhdfs/native_mini_dfs.c Mon Aug  6 21:02:30 2012
@@ -16,6 +16,7 @@
  * limitations under the License.
  */
 
+#include "exception.h"
 #include "jni_helper.h"
 #include "native_mini_dfs.h"
 
@@ -41,6 +42,8 @@ struct NativeMiniDfsCluster* nmdCreate(s
     jobject bld = NULL, bld2 = NULL, cobj = NULL;
     jvalue  val;
     JNIEnv *env = getJNIEnv();
+    jthrowable jthr;
+
     if (!env) {
         fprintf(stderr, "nmdCreate: unable to construct JNIEnv.\n");
         goto error;
@@ -50,35 +53,38 @@ struct NativeMiniDfsCluster* nmdCreate(s
         fprintf(stderr, "nmdCreate: OOM");
         goto error;
     }
-    cobj = constructNewObjectOfClass(env, NULL, HADOOP_CONF, "()V");
-    if (!cobj) {
-        fprintf(stderr, "nmdCreate: unable to construct Configuration\n");
+    jthr = constructNewObjectOfClass(env, &cobj, HADOOP_CONF, "()V");
+    if (jthr) {
+        printExceptionAndFree(env, jthr, PRINT_EXC_ALL,
+            "nmdCreate: new Configuration");
         goto error_free_cl;
     }
-    bld = constructNewObjectOfClass(env, NULL, MINIDFS_CLUSTER_BUILDER,
+    jthr = constructNewObjectOfClass(env, &bld, MINIDFS_CLUSTER_BUILDER,
                     "(L"HADOOP_CONF";)V", cobj);
-    if (!bld) {
-        fprintf(stderr, "nmdCreate: unable to construct "
-                "NativeMiniDfsCluster#Builder\n");
+    if (jthr) {
+        printExceptionAndFree(env, jthr, PRINT_EXC_ALL,
+            "nmdCreate: NativeMiniDfsCluster#Builder#Builder");
         goto error_dlr_cobj;
     }
-    if (invokeMethod(env, &val, NULL, INSTANCE, bld,
-            MINIDFS_CLUSTER_BUILDER, "format",
-            "(Z)L" MINIDFS_CLUSTER_BUILDER ";", conf->doFormat)) {
-        fprintf(stderr, "nmdCreate: failed to call Builder#doFormat\n");
+    jthr = invokeMethod(env, &val, INSTANCE, bld, MINIDFS_CLUSTER_BUILDER,
+            "format", "(Z)L" MINIDFS_CLUSTER_BUILDER ";", conf->doFormat);
+    if (jthr) {
+        printExceptionAndFree(env, jthr, PRINT_EXC_ALL, "nmdCreate: "
+                              "Builder::format");
         goto error_dlr_bld;
     }
     bld2 = val.l;
-    if (invokeMethod(env, &val, NULL, INSTANCE, bld,
-            MINIDFS_CLUSTER_BUILDER, "build",
-            "()L" MINIDFS_CLUSTER ";")) {
-        fprintf(stderr, "nmdCreate: failed to call Builder#build\n");
+    jthr = invokeMethod(env, &val, INSTANCE, bld, MINIDFS_CLUSTER_BUILDER,
+            "build", "()L" MINIDFS_CLUSTER ";");
+    if (jthr) {
+        printExceptionAndFree(env, jthr, PRINT_EXC_ALL,
+                              "nmdCreate: Builder#build");
         goto error_dlr_bld2;
     }
 	cl->obj = (*env)->NewGlobalRef(env, val.l);
     if (!cl->obj) {
-        fprintf(stderr, "nmdCreate: failed to create global reference to "
-            "MiniDFSCluster\n");
+        printPendingExceptionAndFree(env, PRINT_EXC_ALL,
+            "nmdCreate: NewGlobalRef");
         goto error_dlr_val;
     }
     (*env)->DeleteLocalRef(env, val.l);
@@ -116,13 +122,17 @@ void nmdFree(struct NativeMiniDfsCluster
 int nmdShutdown(struct NativeMiniDfsCluster* cl)
 {
     JNIEnv *env = getJNIEnv();
+    jthrowable jthr;
+
     if (!env) {
         fprintf(stderr, "nmdShutdown: getJNIEnv failed\n");
         return -EIO;
     }
-    if (invokeMethod(env, NULL, NULL, INSTANCE, cl->obj,
-            MINIDFS_CLUSTER, "shutdown", "()V")) {
-        fprintf(stderr, "nmdShutdown: MiniDFSCluster#shutdown failure\n");
+    jthr = invokeMethod(env, NULL, INSTANCE, cl->obj,
+            MINIDFS_CLUSTER, "shutdown", "()V");
+    if (jthr) {
+        printExceptionAndFree(env, jthr, PRINT_EXC_ALL,
+            "nmdShutdown: MiniDFSCluster#shutdown");
         return -EIO;
     }
     return 0;
@@ -130,15 +140,17 @@ int nmdShutdown(struct NativeMiniDfsClus
 
 int nmdWaitClusterUp(struct NativeMiniDfsCluster *cl)
 {
+    jthrowable jthr;
     JNIEnv *env = getJNIEnv();
     if (!env) {
         fprintf(stderr, "nmdWaitClusterUp: getJNIEnv failed\n");
         return -EIO;
     }
-    if (invokeMethod(env, NULL, NULL, INSTANCE, cl->obj,
-            MINIDFS_CLUSTER, "waitClusterUp", "()V")) {
-        fprintf(stderr, "nmdWaitClusterUp: MiniDFSCluster#waitClusterUp "
-                "failure\n");
+    jthr = invokeMethod(env, NULL, INSTANCE, cl->obj,
+            MINIDFS_CLUSTER, "waitClusterUp", "()V");
+    if (jthr) {
+        printExceptionAndFree(env, jthr, PRINT_EXC_ALL,
+            "nmdWaitClusterUp: MiniDFSCluster#waitClusterUp ");
         return -EIO;
     }
     return 0;
@@ -148,6 +160,7 @@ int nmdGetNameNodePort(struct NativeMini
 {
     JNIEnv *env = getJNIEnv();
     jvalue jVal;
+    jthrowable jthr;
 
     if (!env) {
         fprintf(stderr, "nmdHdfsConnect: getJNIEnv failed\n");
@@ -155,10 +168,11 @@ int nmdGetNameNodePort(struct NativeMini
     }
     // Note: this will have to be updated when HA nativeMiniDfs clusters are
     // supported
-    if (invokeMethod(env, &jVal, NULL, INSTANCE, cl->obj,
-            MINIDFS_CLUSTER, "getNameNodePort", "()I")) {
-        fprintf(stderr, "nmdHdfsConnect: MiniDFSCluster#getNameNodePort "
-                "failure\n");
+    jthr = invokeMethod(env, &jVal, INSTANCE, cl->obj,
+            MINIDFS_CLUSTER, "getNameNodePort", "()I");
+    if (jthr) {
+        printExceptionAndFree(env, jthr, PRINT_EXC_ALL,
+            "nmdHdfsConnect: MiniDFSCluster#getNameNodePort");
         return -EIO;
     }
     return jVal.i;