Add a helper to get the referent of a Reference.

Change-Id: I8ac5a69fab563e220d48c94e254f5ed3055abe5f
diff --git a/JNIHelp.cpp b/JNIHelp.cpp
index 4430c56..bc0b49c 100644
--- a/JNIHelp.cpp
+++ b/JNIHelp.cpp
@@ -306,11 +306,15 @@
     }
 }
 
-static struct CachedFields {
-    jclass fileDescriptorClass;
-    jmethodID fileDescriptorCtor;
-    jfieldID descriptorField;
-} gCachedFields;
+static struct {
+    jclass clazz;
+    jmethodID ctor;
+    jfieldID descriptor;
+} gFileDescriptorClassInfo;
+
+static struct {
+    jmethodID get;
+} gReferenceClassInfo;
 
 jint JNI_OnLoad(JavaVM* vm, void*) {
     JNIEnv* env;
@@ -319,21 +323,31 @@
         abort();
     }
 
-    gCachedFields.fileDescriptorClass =
+    gFileDescriptorClassInfo.clazz =
             reinterpret_cast<jclass>(env->NewGlobalRef(env->FindClass("java/io/FileDescriptor")));
-    if (gCachedFields.fileDescriptorClass == NULL) {
+    if (gFileDescriptorClassInfo.clazz == NULL) {
         abort();
     }
 
-    gCachedFields.fileDescriptorCtor =
-            env->GetMethodID(gCachedFields.fileDescriptorClass, "<init>", "()V");
-    if (gCachedFields.fileDescriptorCtor == NULL) {
+    gFileDescriptorClassInfo.ctor =
+            env->GetMethodID(gFileDescriptorClassInfo.clazz, "<init>", "()V");
+    if (gFileDescriptorClassInfo.ctor == NULL) {
         abort();
     }
 
-    gCachedFields.descriptorField =
-            env->GetFieldID(gCachedFields.fileDescriptorClass, "descriptor", "I");
-    if (gCachedFields.descriptorField == NULL) {
+    gFileDescriptorClassInfo.descriptor =
+            env->GetFieldID(gFileDescriptorClassInfo.clazz, "descriptor", "I");
+    if (gFileDescriptorClassInfo.descriptor == NULL) {
+        abort();
+    }
+
+    jclass clazz = reinterpret_cast<jclass>(env->FindClass("java/lang/ref/Reference"));
+    if (clazz == NULL) {
+        abort();
+    }
+
+    gReferenceClassInfo.get = env->GetMethodID(clazz, "get", "()Ljava/lang/Object;");
+    if (gReferenceClassInfo.get == NULL) {
         abort();
     }
 
@@ -343,19 +357,24 @@
 jobject jniCreateFileDescriptor(C_JNIEnv* env, int fd) {
     JNIEnv* e = reinterpret_cast<JNIEnv*>(env);
     jobject fileDescriptor = (*env)->NewObject(e,
-            gCachedFields.fileDescriptorClass, gCachedFields.fileDescriptorCtor);
+            gFileDescriptorClassInfo.clazz, gFileDescriptorClassInfo.ctor);
     jniSetFileDescriptorOfFD(env, fileDescriptor, fd);
     return fileDescriptor;
 }
 
 int jniGetFDFromFileDescriptor(C_JNIEnv* env, jobject fileDescriptor) {
     JNIEnv* e = reinterpret_cast<JNIEnv*>(env);
-    return (*env)->GetIntField(e, fileDescriptor, gCachedFields.descriptorField);
+    return (*env)->GetIntField(e, fileDescriptor, gFileDescriptorClassInfo.descriptor);
 }
 
 void jniSetFileDescriptorOfFD(C_JNIEnv* env, jobject fileDescriptor, int value) {
     JNIEnv* e = reinterpret_cast<JNIEnv*>(env);
-    (*env)->SetIntField(e, fileDescriptor, gCachedFields.descriptorField, value);
+    (*env)->SetIntField(e, fileDescriptor, gFileDescriptorClassInfo.descriptor, value);
+}
+
+jobject jniGetReferent(C_JNIEnv* env, jobject ref) {
+    JNIEnv* e = reinterpret_cast<JNIEnv*>(env);
+    return (*env)->CallObjectMethod(e, ref, gReferenceClassInfo.get);
 }
 
 /*
diff --git a/include/nativehelper/JNIHelp.h b/include/nativehelper/JNIHelp.h
index 446a710..2fadcdf 100644
--- a/include/nativehelper/JNIHelp.h
+++ b/include/nativehelper/JNIHelp.h
@@ -97,6 +97,11 @@
 void jniSetFileDescriptorOfFD(C_JNIEnv* env, jobject fileDescriptor, int value);
 
 /*
+ * Returns the reference from a java.lang.ref.Reference.
+ */
+jobject jniGetReferent(C_JNIEnv* env, jobject ref);
+
+/*
  * Log a message and an exception.
  * If exception is NULL, logs the current exception in the JNI environment.
  */
@@ -157,6 +162,10 @@
     jniSetFileDescriptorOfFD(&env->functions, fileDescriptor, value);
 }
 
+inline jobject jniGetReferent(JNIEnv* env, jobject ref) {
+    return jniGetReferent(&env->functions, ref);
+}
+
 inline void jniLogException(JNIEnv* env, int priority, const char* tag, jthrowable exception = NULL) {
     jniLogException(&env->functions, priority, tag, exception);
 }