[java-atk-wrapper] Fix freeing objects



commit d4b439228d1c56fd9c71fa5783d09f600ee5ac6b
Author: Samuel Thibault <samuel thibault ens-lyon org>
Date:   Mon Apr 1 23:51:46 2019 +0200

    Fix freeing objects
    
    java-atk-wrapper actually never frees its jaw_impl objects. Indeed, there
    is never a g_object_unref() call for them. And then the corresponding java
    widget objects never get garbage-collected, since jaw_impl are keeping a
    global ref on them.
    
    A way for java-atk-wrapper to know when it should free a jaw_impl object is
    to use global weak references: the GC will then feel free to collect the
    objects. java-atk-wrapper can then use IsSameObject(obj, NULL) to determine
    whether the object was collected, and then release the corresponding
    jaw_impl. This is what I have done here, going through the hash table of
    jaw_impl after GC has run.
    
    Now, since we only have weak references on the widgets, we need to acquire a
    non-weak reference while working on them. This adds taking and releasing it
    in all cases.
    
    We can keep global non-weak references for subparts of the widget (e.g.
    jawaction's jstrActionName etc.), they won't get collected until we release
    the jaw_impl of the widget, that is fine (and simpler).
    
    Fixes https://bugzilla.gnome.org/show_bug.cgi?id=793819

 jni/src/AtkWrapper.c                               |   6 +
 jni/src/AtkWrapper.h                               |   7 +
 jni/src/jawaction.c                                |  63 ++++--
 jni/src/jawcomponent.c                             |  53 ++++--
 jni/src/jaweditabletext.c                          |  58 ++++--
 jni/src/jawhyperlink.c                             |  52 +++--
 jni/src/jawhypertext.c                             |  34 +++-
 jni/src/jawimage.c                                 |  28 ++-
 jni/src/jawimpl.c                                  |  91 ++++++---
 jni/src/jawimpl.h                                  |   2 +
 jni/src/jawobject.c                                |  81 ++++++--
 jni/src/jawselection.c                             |  61 ++++--
 jni/src/jawtable.c                                 | 212 +++++++++++++++------
 jni/src/jawtablecell.c                             |  50 +++--
 jni/src/jawtext.c                                  | 116 ++++++++---
 jni/src/jawvalue.c                                 |  40 ++--
 wrapper/module-info.java                           |   1 +
 wrapper/org/GNOME/Accessibility/AtkWrapper.java.in |  15 ++
 18 files changed, 728 insertions(+), 242 deletions(-)
---
diff --git a/jni/src/AtkWrapper.c b/jni/src/AtkWrapper.c
index e38bba7..f456b0b 100644
--- a/jni/src/AtkWrapper.c
+++ b/jni/src/AtkWrapper.c
@@ -156,6 +156,12 @@ JNICALL Java_org_GNOME_Accessibility_AtkWrapper_loadAtkBridge()
   }
 }
 
+JNIEXPORT void
+JNICALL Java_org_GNOME_Accessibility_AtkWrapper_GC(JNIEnv *jniEnv)
+{
+  object_table_gc(jniEnv);
+}
+
 enum _SignalType {
   Sig_Text_Caret_Moved = 0,
   Sig_Text_Property_Changed_Insert = 1,
diff --git a/jni/src/AtkWrapper.h b/jni/src/AtkWrapper.h
index 1bac790..68abfc2 100644
--- a/jni/src/AtkWrapper.h
+++ b/jni/src/AtkWrapper.h
@@ -21,6 +21,13 @@ JNIEXPORT jboolean JNICALL Java_org_GNOME_Accessibility_AtkWrapper_initNativeLib
  */
 JNIEXPORT void JNICALL Java_org_GNOME_Accessibility_AtkWrapper_loadAtkBridge(void);
 
+/*
+ * Class:     org_GNOME_Accessibility_AtkWrapper
+ * Method:    GC
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_org_GNOME_Accessibility_AtkWrapper_GC(JNIEnv *);
+
 /*
  * Class:     org_GNOME_Accessibility_AtkWrapper
  * Method:    focusNotify
diff --git a/jni/src/jawaction.c b/jni/src/jawaction.c
index 3c7b6f9..2ebeeee 100644
--- a/jni/src/jawaction.c
+++ b/jni/src/jawaction.c
@@ -70,7 +70,7 @@ jaw_action_data_init (jobject ac)
                                           "<init>",
                                           "(Ljavax/accessibility/AccessibleContext;)V");
   jobject jatk_action = (*jniEnv)->NewObject(jniEnv, classAction, jmid, ac);
-  data->atk_action = (*jniEnv)->NewGlobalRef(jniEnv, jatk_action);
+  data->atk_action = (*jniEnv)->NewWeakGlobalRef(jniEnv, jatk_action);
 
   return data;
 }
@@ -115,7 +115,7 @@ jaw_action_data_finalize (gpointer p)
       data->action_keybinding = NULL;
     }
 
-    (*jniEnv)->DeleteGlobalRef(jniEnv, data->atk_action);
+    (*jniEnv)->DeleteWeakGlobalRef(jniEnv, data->atk_action);
     data->atk_action = NULL;
   }
 }
@@ -125,9 +125,12 @@ jaw_action_do_action (AtkAction *action, gint i)
 {
   JawObject *jaw_obj = JAW_OBJECT(action);
   ActionData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_ACTION);
-  jobject atk_action = data->atk_action;
-
   JNIEnv *jniEnv = jaw_util_get_jni_env();
+  jobject atk_action = (*jniEnv)->NewGlobalRef(jniEnv, data->atk_action);
+  if (!atk_action) {
+    return FALSE;
+  }
+
   jclass classAtkAction = (*jniEnv)->FindClass(jniEnv,
                                                "org/GNOME/Accessibility/AtkAction");
   jmethodID jmid = (*jniEnv)->GetMethodID(jniEnv,
@@ -138,6 +141,7 @@ jaw_action_do_action (AtkAction *action, gint i)
                                                   atk_action,
                                                   jmid,
                                                   (jint)i);
+  (*jniEnv)->DeleteGlobalRef(jniEnv, atk_action);
 
   if (jresult == JNI_TRUE)
     return TRUE;
@@ -150,16 +154,21 @@ jaw_action_get_n_actions (AtkAction *action)
 {
   JawObject *jaw_obj = JAW_OBJECT(action);
   ActionData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_ACTION);
-  jobject atk_action = data->atk_action;
-
   JNIEnv *jniEnv = jaw_util_get_jni_env();
+  jobject atk_action = (*jniEnv)->NewGlobalRef(jniEnv, data->atk_action);
+  if (!atk_action) {
+    return 0;
+  }
+
   jclass classAtkAction = (*jniEnv)->FindClass(jniEnv,
                                                "org/GNOME/Accessibility/AtkAction");
   jmethodID jmid = (*jniEnv)->GetMethodID(jniEnv,
                                           classAtkAction,
                                           "get_n_actions", "()I");
 
-  return (gint)(*jniEnv)->CallIntMethod(jniEnv, atk_action, jmid);
+  gint ret = (gint)(*jniEnv)->CallIntMethod(jniEnv, atk_action, jmid);
+  (*jniEnv)->DeleteGlobalRef(jniEnv, atk_action);
+  return ret;
 }
 
 static const gchar*
@@ -167,9 +176,12 @@ jaw_action_get_description (AtkAction *action, gint i)
 {
   JawObject *jaw_obj = JAW_OBJECT(action);
   ActionData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_ACTION);
-  jobject atk_action = data->atk_action;
-
   JNIEnv *jniEnv = jaw_util_get_jni_env();
+  jobject atk_action = (*jniEnv)->NewGlobalRef(jniEnv, data->atk_action);
+  if (!atk_action) {
+    return NULL;
+  }
+
   jclass classAtkAction = (*jniEnv)->FindClass(jniEnv,
                                                "org/GNOME/Accessibility/AtkAction");
   jmethodID jmid = (*jniEnv)->GetMethodID(jniEnv,
@@ -180,6 +192,7 @@ jaw_action_get_description (AtkAction *action, gint i)
                                              atk_action,
                                              jmid,
                                              (jint)i);
+  (*jniEnv)->DeleteGlobalRef(jniEnv, atk_action);
 
   if (data->action_description != NULL)
   {
@@ -202,9 +215,12 @@ jaw_action_set_description (AtkAction *action, gint i, const gchar *description)
 {
   JawObject *jaw_obj = JAW_OBJECT(action);
   ActionData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_ACTION);
-  jobject atk_action = data->atk_action;
-
   JNIEnv *jniEnv = jaw_util_get_jni_env();
+  jobject atk_action = (*jniEnv)->NewGlobalRef(jniEnv, data->atk_action);
+  if (!atk_action) {
+    return FALSE;
+  }
+
   jclass classAtkAction = (*jniEnv)->FindClass(jniEnv,
                                                "org/GNOME/Accessibility/AtkAction");
   jmethodID jmid = (*jniEnv)->GetMethodID(jniEnv,
@@ -216,6 +232,7 @@ jaw_action_set_description (AtkAction *action, gint i, const gchar *description)
                                                  jmid,
                                                  (jint)i,
                                                  (jstring)description);
+  (*jniEnv)->DeleteGlobalRef(jniEnv, atk_action);
 
   if (jisset == JNI_TRUE)
   {
@@ -230,9 +247,12 @@ jaw_action_get_name (AtkAction *action, gint i)
 {
   JawObject *jaw_obj = JAW_OBJECT(action);
   ActionData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_ACTION);
-  jobject atk_action = data->atk_action;
-
   JNIEnv *jniEnv = jaw_util_get_jni_env();
+  jobject atk_action = (*jniEnv)->NewGlobalRef(jniEnv, data->atk_action);
+  if (!atk_action) {
+    return NULL;
+  }
+
   jclass classAtkAction = (*jniEnv)->FindClass(jniEnv,
                                                "org/GNOME/Accessibility/AtkAction");
   jmethodID jmid = (*jniEnv)->GetMethodID(jniEnv,
@@ -240,6 +260,7 @@ jaw_action_get_name (AtkAction *action, gint i)
                                           "get_name",
                                           "(I)Ljava/lang/String;");
   jstring jstr = (*jniEnv)->CallObjectMethod(jniEnv, atk_action, jmid, (jint)i);
+  (*jniEnv)->DeleteGlobalRef(jniEnv, atk_action);
 
   if (data->action_name != NULL)
   {
@@ -262,15 +283,19 @@ jaw_action_get_localized_name (AtkAction *action, gint i)
 {
   JawObject *jaw_obj = JAW_OBJECT(action);
   ActionData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_ACTION);
-  jobject atk_action = data->atk_action;
-
   JNIEnv *env = jaw_util_get_jni_env();
+  jobject atk_action = (*env)->NewGlobalRef(env, data->atk_action);
+  if (!atk_action) {
+    return NULL;
+  }
+
   jclass classAtkAction = (*env)->FindClass(env, "org/GNOME/Accessibility/AtkAction");
   jmethodID jmid = (*env)->GetMethodID(env,
                                        classAtkAction,
                                        "getLocalizedName",
                                        "(I)Ljava/lang/String;");
   jstring jstr = (*env)->CallObjectMethod(env, atk_action, jmid, (jint)i);
+  (*env)->DeleteGlobalRef(env, atk_action);
   if (data->action_name != NULL)
   {
     (*env)->ReleaseStringUTFChars(env, data->jstrLocalizedName, data->action_name);
@@ -289,9 +314,12 @@ jaw_action_get_keybinding (AtkAction *action, gint i)
     return NULL;
 
   ActionData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_ACTION);
-  jobject atk_action = data->atk_action;
-
   JNIEnv *jniEnv = jaw_util_get_jni_env();
+  jobject atk_action = (*jniEnv)->NewGlobalRef(jniEnv, data->atk_action);
+  if (!atk_action) {
+    return NULL;
+  }
+
   jclass classAtkAction = (*jniEnv)->FindClass(jniEnv,
                                                "org/GNOME/Accessibility/AtkAction");
   jmethodID jmid = (*jniEnv)->GetMethodID(jniEnv,
@@ -299,6 +327,7 @@ jaw_action_get_keybinding (AtkAction *action, gint i)
                                           "get_keybinding",
                                           "(I)Ljava/lang/String;");
   jstring jstr = (*jniEnv)->CallObjectMethod(jniEnv, atk_action, jmid, (jint)i);
+  (*jniEnv)->DeleteGlobalRef(jniEnv, atk_action);
 
   if (data->action_keybinding != NULL)
   {
diff --git a/jni/src/jawcomponent.c b/jni/src/jawcomponent.c
index e5318bc..1879cdd 100644
--- a/jni/src/jawcomponent.c
+++ b/jni/src/jawcomponent.c
@@ -86,7 +86,7 @@ jaw_component_data_init (jobject ac)
                                           "(Ljavax/accessibility/AccessibleContext;)V");
 
   jobject jatk_component = (*jniEnv)->NewObject(jniEnv, classComponent, jmid, ac);
-  data->atk_component = (*jniEnv)->NewGlobalRef(jniEnv, jatk_component);
+  data->atk_component = (*jniEnv)->NewWeakGlobalRef(jniEnv, jatk_component);
 
   return data;
 }
@@ -99,7 +99,7 @@ jaw_component_data_finalize (gpointer p)
 
   if (data && data->atk_component)
   {
-    (*jniEnv)->DeleteGlobalRef(jniEnv, data->atk_component);
+    (*jniEnv)->DeleteWeakGlobalRef(jniEnv, data->atk_component);
     data->atk_component = NULL;
   }
 }
@@ -109,9 +109,12 @@ jaw_component_contains (AtkComponent *component, gint x, gint y, AtkCoordType co
 {
   JawObject *jaw_obj = JAW_OBJECT(component);
   ComponentData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_COMPONENT);
-  jobject atk_component = data->atk_component;
-
   JNIEnv *jniEnv = jaw_util_get_jni_env();
+  jobject atk_component = (*jniEnv)->NewGlobalRef(jniEnv, data->atk_component);
+  if (!atk_component) {
+    return FALSE;
+  }
+
   jclass classAtkComponent = (*jniEnv)->FindClass(jniEnv,
                                                   "org/GNOME/Accessibility/AtkComponent");
 
@@ -126,6 +129,7 @@ jaw_component_contains (AtkComponent *component, gint x, gint y, AtkCoordType co
                                                     (jint)x,
                                                     (jint)y,
                                                     (jint)coord_type);
+  (*jniEnv)->DeleteGlobalRef(jniEnv, atk_component);
 
   if (jcontains == JNI_TRUE)
   {
@@ -140,9 +144,12 @@ jaw_component_ref_accessible_at_point (AtkComponent *component, gint x, gint y,
 {
   JawObject *jaw_obj = JAW_OBJECT(component);
   ComponentData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_COMPONENT);
-  jobject atk_component = data->atk_component;
-
   JNIEnv *jniEnv = jaw_util_get_jni_env();
+  jobject atk_component = (*jniEnv)->NewGlobalRef(jniEnv, data->atk_component);
+  if (!atk_component) {
+    return NULL;
+  }
+
   jclass classAtkComponent = (*jniEnv)->FindClass(jniEnv,
                                                   "org/GNOME/Accessibility/AtkComponent");
   jmethodID jmid = (*jniEnv)->GetMethodID(jniEnv,
@@ -155,6 +162,7 @@ jaw_component_ref_accessible_at_point (AtkComponent *component, gint x, gint y,
                                                  (jint)x,
                                                  (jint)y,
                                                  (jint)coord_type);
+  (*jniEnv)->DeleteGlobalRef(jniEnv, atk_component);
 
   JawImpl* jaw_impl = jaw_impl_get_instance( jniEnv, child_ac );
 
@@ -180,9 +188,12 @@ jaw_component_get_extents (AtkComponent *component,
   JawObject *jaw_obj = JAW_OBJECT(component);
   ComponentData *data = jaw_object_get_interface_data(jaw_obj,
                                                       INTERFACE_COMPONENT);
-  jobject atk_component = data->atk_component;
-
   JNIEnv *jniEnv = jaw_util_get_jni_env();
+  jobject atk_component = (*jniEnv)->NewGlobalRef(jniEnv, data->atk_component);
+  if (!atk_component) {
+    return;
+  }
+
   jclass classAtkComponent = (*jniEnv)->FindClass(jniEnv,
                                                   "org/GNOME/Accessibility/AtkComponent");
   jmethodID jmid = (*jniEnv)->GetMethodID(jniEnv,
@@ -191,6 +202,7 @@ jaw_component_get_extents (AtkComponent *component,
                                           "()Ljava/awt/Rectangle;");
 
   jobject jrectangle = (*jniEnv)->CallObjectMethod(jniEnv, atk_component, jmid);
+  (*jniEnv)->DeleteGlobalRef(jniEnv, atk_component);
 
   if (jrectangle == NULL)
   {
@@ -223,9 +235,12 @@ jaw_component_set_extents (AtkComponent *component,
 
   JawObject *jaw_obj = JAW_OBJECT(component);
   ComponentData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_COMPONENT);
-  jobject atk_component = data->atk_component;
-
   JNIEnv *jniEnv = jaw_util_get_jni_env();
+  jobject atk_component = (*jniEnv)->NewGlobalRef(jniEnv, data->atk_component);
+  if (!atk_component) {
+    return FALSE;
+  }
+
   jclass classAtkComponent = (*jniEnv)->FindClass(jniEnv,
                                                   "org/GNOME/Accessibility/AtkComponent");
 
@@ -249,6 +264,7 @@ jaw_component_set_extents (AtkComponent *component,
     height = 0;
     x = 0;
     y = 0;
+    (*jniEnv)->DeleteGlobalRef(jniEnv, atk_component);
     return FALSE;
   }
 
@@ -271,6 +287,7 @@ jaw_component_set_extents (AtkComponent *component,
                                                atk_component,
                                                "height",
                                                "I");
+  (*jniEnv)->DeleteGlobalRef(jniEnv, atk_component);
 
   jint jwidth = (*jniEnv)->GetIntField(jniEnv, classRectangle, jfidWidth);
   jint jheight = (*jniEnv)->GetIntField(jniEnv, classRectangle, jfidHeight);
@@ -290,9 +307,12 @@ jaw_component_grab_focus (AtkComponent *component)
 {
   JawObject *jaw_obj = JAW_OBJECT(component);
   ComponentData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_COMPONENT);
-  jobject atk_component = data->atk_component;
-
   JNIEnv *jniEnv = jaw_util_get_jni_env();
+  jobject atk_component = (*jniEnv)->NewGlobalRef(jniEnv, data->atk_component);
+  if (!atk_component) {
+    return FALSE;
+  }
+
   jclass classAtkComponent = (*jniEnv)->FindClass(jniEnv,
                                                   "org/GNOME/Accessibility/AtkComponent");
   jmethodID jmid = (*jniEnv)->GetMethodID(jniEnv,
@@ -300,6 +320,7 @@ jaw_component_grab_focus (AtkComponent *component)
                                           "grab_focus",
                                           "()Z");
   jboolean jresult = (*jniEnv)->CallBooleanMethod(jniEnv, atk_component, jmid);
+  (*jniEnv)->DeleteGlobalRef(jniEnv, atk_component);
 
   if (jresult == JNI_TRUE)
   {
@@ -315,9 +336,12 @@ jaw_component_get_layer (AtkComponent *component)
   JawObject *jaw_obj = JAW_OBJECT(component);
   ComponentData *data = jaw_object_get_interface_data(jaw_obj,
                                                       INTERFACE_COMPONENT);
-  jobject atk_component = data->atk_component;
-
   JNIEnv *jniEnv = jaw_util_get_jni_env();
+  jobject atk_component = (*jniEnv)->NewGlobalRef(jniEnv, data->atk_component);
+  if (!atk_component) {
+    return 0;
+  }
+
   jclass classAtkComponent = (*jniEnv)->FindClass(jniEnv,
                                                   "org/GNOME/Accessibility/AtkComponent");
   jmethodID jmid = (*jniEnv)->GetMethodID(jniEnv,
@@ -326,6 +350,7 @@ jaw_component_get_layer (AtkComponent *component)
                                           "()I");
 
   jint jlayer = (*jniEnv)->CallIntMethod(jniEnv, atk_component, jmid);
+  (*jniEnv)->DeleteGlobalRef(jniEnv, atk_component);
 
   return (AtkLayer)jlayer;
 }
diff --git a/jni/src/jaweditabletext.c b/jni/src/jaweditabletext.c
index 792e5b6..6658a24 100644
--- a/jni/src/jaweditabletext.c
+++ b/jni/src/jaweditabletext.c
@@ -82,7 +82,7 @@ jaw_editable_text_data_init (jobject ac)
                                                     classEditableText,
                                                     jmid,
                                                     ac);
-  data->atk_editable_text = (*jniEnv)->NewGlobalRef(jniEnv,
+  data->atk_editable_text = (*jniEnv)->NewWeakGlobalRef(jniEnv,
                                                     jatk_editable_text);
 
   return data;
@@ -96,7 +96,7 @@ jaw_editable_text_data_finalize (gpointer p)
 
   if (data && data->atk_editable_text)
   {
-    (*jniEnv)->DeleteGlobalRef(jniEnv, data->atk_editable_text);
+    (*jniEnv)->DeleteWeakGlobalRef(jniEnv, data->atk_editable_text);
     data->atk_editable_text = NULL;
   }
 }
@@ -107,9 +107,12 @@ jaw_editable_text_set_text_contents (AtkEditableText *text,
 {
   JawObject *jaw_obj = JAW_OBJECT(text);
   EditableTextData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_EDITABLE_TEXT);
-  jobject atk_editable_text = data->atk_editable_text;
-
   JNIEnv *jniEnv = jaw_util_get_jni_env();
+  jobject atk_editable_text = (*jniEnv)->NewGlobalRef(jniEnv, data->atk_editable_text);
+  if (!atk_editable_text) {
+    return;
+  }
+
   jclass classAtkEditableText = (*jniEnv)->FindClass(jniEnv,
                                                      "org/GNOME/Accessibility/AtkEditableText");
   jmethodID jmid = (*jniEnv)->GetMethodID(jniEnv,
@@ -119,6 +122,7 @@ jaw_editable_text_set_text_contents (AtkEditableText *text,
 
   jstring jstr = (*jniEnv)->NewStringUTF(jniEnv, string);
   (*jniEnv)->CallVoidMethod(jniEnv, atk_editable_text, jmid, jstr);
+  (*jniEnv)->DeleteGlobalRef(jniEnv, atk_editable_text);
 }
 
 void
@@ -129,9 +133,12 @@ jaw_editable_text_insert_text (AtkEditableText *text,
 {
   JawObject *jaw_obj = JAW_OBJECT(text);
   EditableTextData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_EDITABLE_TEXT);
-  jobject atk_editable_text = data->atk_editable_text;
-
   JNIEnv *jniEnv = jaw_util_get_jni_env();
+  jobject atk_editable_text = (*jniEnv)->NewGlobalRef(jniEnv, data->atk_editable_text);
+  if (!atk_editable_text) {
+    return;
+  }
+
   jclass classAtkEditableText = (*jniEnv)->FindClass(jniEnv,
                                                      "org/GNOME/Accessibility/AtkEditableText");
   jmethodID jmid = (*jniEnv)->GetMethodID(jniEnv,
@@ -144,6 +151,7 @@ jaw_editable_text_insert_text (AtkEditableText *text,
                             atk_editable_text,
                             jmid, jstr,
                             (jint)*position);
+  (*jniEnv)->DeleteGlobalRef(jniEnv, atk_editable_text);
   *position = *position + length;
   atk_text_set_caret_offset(ATK_TEXT(jaw_obj), *position);
 }
@@ -156,9 +164,12 @@ jaw_editable_text_copy_text (AtkEditableText *text,
   JawObject *jaw_obj = JAW_OBJECT(text);
   EditableTextData *data = jaw_object_get_interface_data(jaw_obj,
                                                          INTERFACE_EDITABLE_TEXT);
-  jobject atk_editable_text = data->atk_editable_text;
-
   JNIEnv *jniEnv = jaw_util_get_jni_env();
+  jobject atk_editable_text = (*jniEnv)->NewGlobalRef(jniEnv, data->atk_editable_text);
+  if (!atk_editable_text) {
+    return;
+  }
+
   jclass classAtkEditableText = (*jniEnv)->FindClass(jniEnv,
                                                      "org/GNOME/Accessibility/AtkEditableText");
   jmethodID jmid = (*jniEnv)->GetMethodID(jniEnv,
@@ -170,6 +181,7 @@ jaw_editable_text_copy_text (AtkEditableText *text,
                             jmid,
                             (jint)start_pos,
                             (jint)end_pos);
+  (*jniEnv)->DeleteGlobalRef(jniEnv, atk_editable_text);
 }
 
 void
@@ -178,9 +190,12 @@ jaw_editable_text_cut_text (AtkEditableText *text,
 {
   JawObject *jaw_obj = JAW_OBJECT(text);
   EditableTextData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_EDITABLE_TEXT);
-  jobject atk_editable_text = data->atk_editable_text;
-
   JNIEnv *jniEnv = jaw_util_get_jni_env();
+  jobject atk_editable_text = (*jniEnv)->NewGlobalRef(jniEnv, data->atk_editable_text);
+  if (!atk_editable_text) {
+    return;
+  }
+
   jclass classAtkEditableText = (*jniEnv)->FindClass(jniEnv,
                                                      "org/GNOME/Accessibility/AtkEditableText");
   jmethodID jmid = (*jniEnv)->GetMethodID(jniEnv,
@@ -192,6 +207,7 @@ jaw_editable_text_cut_text (AtkEditableText *text,
                             jmid,
                             (jint)start_pos,
                             (jint)end_pos);
+  (*jniEnv)->DeleteGlobalRef(jniEnv, atk_editable_text);
 }
 
 void
@@ -202,9 +218,12 @@ jaw_editable_text_delete_text (AtkEditableText *text,
   JawObject *jaw_obj = JAW_OBJECT(text);
   EditableTextData *data = jaw_object_get_interface_data(jaw_obj,
                                                          INTERFACE_EDITABLE_TEXT);
-  jobject atk_editable_text = data->atk_editable_text;
-
   JNIEnv *jniEnv = jaw_util_get_jni_env();
+  jobject atk_editable_text = (*jniEnv)->NewGlobalRef(jniEnv, data->atk_editable_text);
+  if (!atk_editable_text) {
+    return;
+  }
+
   jclass classAtkEditableText = (*jniEnv)->FindClass(jniEnv,
                                                      "org/GNOME/Accessibility/AtkEditableText");
   jmethodID jmid = (*jniEnv)->GetMethodID(jniEnv,
@@ -216,6 +235,7 @@ jaw_editable_text_delete_text (AtkEditableText *text,
                             jmid,
                             (jint)start_pos,
                             (jint)end_pos);
+  (*jniEnv)->DeleteGlobalRef(jniEnv, atk_editable_text);
 }
 
 void
@@ -225,9 +245,12 @@ jaw_editable_text_paste_text (AtkEditableText *text,
   JawObject *jaw_obj = JAW_OBJECT(text);
   EditableTextData *data = jaw_object_get_interface_data(jaw_obj,
                                                          INTERFACE_EDITABLE_TEXT);
-  jobject atk_editable_text = data->atk_editable_text;
-
   JNIEnv *jniEnv = jaw_util_get_jni_env();
+  jobject atk_editable_text = (*jniEnv)->NewGlobalRef(jniEnv, data->atk_editable_text);
+  if (!atk_editable_text) {
+    return;
+  }
+
   jclass classAtkEditableText = (*jniEnv)->FindClass(jniEnv,
                                                      "org/GNOME/Accessibility/AtkEditableText");
   jmethodID jmid = (*jniEnv)->GetMethodID(jniEnv,
@@ -238,6 +261,7 @@ jaw_editable_text_paste_text (AtkEditableText *text,
                             atk_editable_text,
                             jmid,
                             (jint)position);
+  (*jniEnv)->DeleteGlobalRef(jniEnv, atk_editable_text);
 }
 
 static gboolean
@@ -248,8 +272,11 @@ jaw_editable_text_set_run_attributes(AtkEditableText *text,
 {
   JawObject *jaw_obj = JAW_OBJECT(text);
   EditableTextData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_EDITABLE_TEXT);
-  jobject atk_editable_text = data->atk_editable_text;
   JNIEnv *env = jaw_util_get_jni_env();
+  jobject atk_editable_text = (*env)->NewGlobalRef(env, data->atk_editable_text);
+  if (!atk_editable_text) {
+    return FALSE;
+  }
   jclass classAtkEditableText = (*env)->FindClass(env, "org/GNOME/Accessibility/AtkEditableText");
   jmethodID jmid = (*env)->GetMethodID(env,
                                                                    classAtkEditableText,
@@ -261,6 +288,7 @@ jaw_editable_text_set_run_attributes(AtkEditableText *text,
                                                                             (jobject)attrib_set,
                                                                             (jint)start_offset,
                                                                             (jint)end_offset);
+  (*env)->DeleteGlobalRef(env, atk_editable_text);
   if (jresult == JNI_TRUE)
     return TRUE;
 
diff --git a/jni/src/jawhyperlink.c b/jni/src/jawhyperlink.c
index 364c6fa..b69873f 100644
--- a/jni/src/jawhyperlink.c
+++ b/jni/src/jawhyperlink.c
@@ -43,7 +43,7 @@ jaw_hyperlink_new (jobject jhyperlink)
 {
        JawHyperlink* jaw_hyperlink = g_object_new(JAW_TYPE_HYPERLINK, NULL);
        JNIEnv *jniEnv = jaw_util_get_jni_env();
-       jaw_hyperlink->jhyperlink = (*jniEnv)->NewGlobalRef(jniEnv, jhyperlink);
+       jaw_hyperlink->jhyperlink = (*jniEnv)->NewWeakGlobalRef(jniEnv, jhyperlink);
 
        return jaw_hyperlink;
 }
@@ -82,7 +82,7 @@ jaw_hyperlink_finalize(GObject *gobject)
        JawHyperlink *jaw_hyperlink = JAW_HYPERLINK(gobject);
 
        JNIEnv *jniEnv = jaw_util_get_jni_env();
-       (*jniEnv)->DeleteGlobalRef(jniEnv, jaw_hyperlink->jhyperlink);
+       (*jniEnv)->DeleteWeakGlobalRef(jniEnv, jaw_hyperlink->jhyperlink);
        jaw_hyperlink->jhyperlink = NULL;
 
        /* Chain up to parent's finalize */
@@ -94,12 +94,16 @@ jaw_hyperlink_get_uri (AtkHyperlink *atk_hyperlink,
                        gint i)
 {
        JawHyperlink *jaw_hyperlink = JAW_HYPERLINK(atk_hyperlink);
-       jobject jhyperlink = jaw_hyperlink->jhyperlink;
-
        JNIEnv *jniEnv = jaw_util_get_jni_env();
+       jobject jhyperlink = (*jniEnv)->NewGlobalRef(jniEnv, jaw_hyperlink->jhyperlink);
+       if (!jhyperlink) {
+               return NULL;
+       }
+
        jclass classAtkHyperlink = (*jniEnv)->FindClass(jniEnv, "org/GNOME/Accessibility/AtkHyperlink");
        jmethodID jmid = (*jniEnv)->GetMethodID(jniEnv, classAtkHyperlink, "get_uri", 
"(I)Ljava/lang/String;");
        jstring jstr = (*jniEnv)->CallObjectMethod(jniEnv, jhyperlink, jmid, (jint)i);
+       (*jniEnv)->DeleteGlobalRef(jniEnv, jhyperlink);
        
        if (jaw_hyperlink->uri != NULL) {
                (*jniEnv)->ReleaseStringUTFChars(jniEnv, jaw_hyperlink->jstrUri, jaw_hyperlink->uri);
@@ -117,12 +121,16 @@ jaw_hyperlink_get_object (AtkHyperlink *atk_hyperlink,
                        gint i)
 {
        JawHyperlink *jaw_hyperlink = JAW_HYPERLINK(atk_hyperlink);
-       jobject jhyperlink = jaw_hyperlink->jhyperlink;
-
        JNIEnv *jniEnv = jaw_util_get_jni_env();
+       jobject jhyperlink = (*jniEnv)->NewGlobalRef(jniEnv, jaw_hyperlink->jhyperlink);
+       if (!jhyperlink) {
+               return NULL;
+       }
+
        jclass classAtkHyperlink = (*jniEnv)->FindClass(jniEnv, "org/GNOME/Accessibility/AtkHyperlink");
        jmethodID jmid = (*jniEnv)->GetMethodID(jniEnv, classAtkHyperlink, "get_object", 
"(I)Ljava/lang/String;");
        jobject jobj = (*jniEnv)->CallObjectMethod(jniEnv, jhyperlink, jmid, (jint)i);
+       (*jniEnv)->DeleteGlobalRef(jniEnv, jhyperlink);
        if (jobj == NULL) {
                return NULL;
        }
@@ -140,12 +148,16 @@ static gint
 jaw_hyperlink_get_end_index (AtkHyperlink *atk_hyperlink)
 {
        JawHyperlink *jaw_hyperlink = JAW_HYPERLINK(atk_hyperlink);
-       jobject jhyperlink = jaw_hyperlink->jhyperlink;
-
        JNIEnv *jniEnv = jaw_util_get_jni_env();
+       jobject jhyperlink = (*jniEnv)->NewGlobalRef(jniEnv, jaw_hyperlink->jhyperlink);
+       if (!jhyperlink) {
+               return 0;
+       }
+
        jclass classAtkHyperlink = (*jniEnv)->FindClass(jniEnv, "org/GNOME/Accessibility/AtkHyperlink");
        jmethodID jmid = (*jniEnv)->GetMethodID(jniEnv, classAtkHyperlink, "get_end_index", "()I");
        jint jindex = (*jniEnv)->CallIntMethod(jniEnv, jhyperlink, jmid);
+       (*jniEnv)->DeleteGlobalRef(jniEnv, jhyperlink);
 
        return jindex;
 }
@@ -153,12 +165,16 @@ jaw_hyperlink_get_end_index (AtkHyperlink *atk_hyperlink)
 static gint jaw_hyperlink_get_start_index (AtkHyperlink        *atk_hyperlink)
 {
        JawHyperlink *jaw_hyperlink = JAW_HYPERLINK(atk_hyperlink);
-       jobject jhyperlink = jaw_hyperlink->jhyperlink;
-
        JNIEnv *jniEnv = jaw_util_get_jni_env();
+       jobject jhyperlink = (*jniEnv)->NewGlobalRef(jniEnv, jaw_hyperlink->jhyperlink);
+       if (!jhyperlink) {
+               return 0;
+       }
+
        jclass classAtkHyperlink = (*jniEnv)->FindClass(jniEnv, "org/GNOME/Accessibility/AtkHyperlink");
        jmethodID jmid = (*jniEnv)->GetMethodID(jniEnv, classAtkHyperlink, "get_start_index", "()I");
        jint jindex = (*jniEnv)->CallIntMethod(jniEnv, jhyperlink, jmid);
+       (*jniEnv)->DeleteGlobalRef(jniEnv, jhyperlink);
 
        return jindex;
 }
@@ -166,12 +182,16 @@ static gint jaw_hyperlink_get_start_index (AtkHyperlink   *atk_hyperlink)
 static gboolean jaw_hyperlink_is_valid (AtkHyperlink *atk_hyperlink)
 {
        JawHyperlink *jaw_hyperlink = JAW_HYPERLINK(atk_hyperlink);
-       jobject jhyperlink = jaw_hyperlink->jhyperlink;
-
        JNIEnv *jniEnv = jaw_util_get_jni_env();
+       jobject jhyperlink = (*jniEnv)->NewGlobalRef(jniEnv, jaw_hyperlink->jhyperlink);
+       if (!jhyperlink) {
+               return FALSE;
+       }
+
        jclass classAtkHyperlink = (*jniEnv)->FindClass(jniEnv, "org/GNOME/Accessibility/AtkHyperlink");
        jmethodID jmid = (*jniEnv)->GetMethodID(jniEnv, classAtkHyperlink, "is_valid", "()Z");
        jboolean jvalid = (*jniEnv)->CallBooleanMethod(jniEnv, jhyperlink, jmid);
+       (*jniEnv)->DeleteGlobalRef(jniEnv, jhyperlink);
 
        return jvalid;
 }
@@ -179,12 +199,16 @@ static gboolean jaw_hyperlink_is_valid (AtkHyperlink *atk_hyperlink)
 static gint jaw_hyperlink_get_n_anchors (AtkHyperlink *atk_hyperlink)
 {
        JawHyperlink *jaw_hyperlink = JAW_HYPERLINK(atk_hyperlink);
-       jobject jhyperlink = jaw_hyperlink->jhyperlink;
-
        JNIEnv *jniEnv = jaw_util_get_jni_env();
+       jobject jhyperlink = (*jniEnv)->NewGlobalRef(jniEnv, jaw_hyperlink->jhyperlink);
+       if (!jhyperlink) {
+               return 0;
+       }
+
        jclass classAtkHyperlink = (*jniEnv)->FindClass(jniEnv, "org/GNOME/Accessibility/AtkHyperlink");
        jmethodID jmid = (*jniEnv)->GetMethodID(jniEnv, classAtkHyperlink, "get_n_anchors", "()I");
        jint janchors = (*jniEnv)->CallIntMethod(jniEnv, jhyperlink, jmid);
+       (*jniEnv)->DeleteGlobalRef(jniEnv, jhyperlink);
 
        return janchors;
 }
diff --git a/jni/src/jawhypertext.c b/jni/src/jawhypertext.c
index f162a45..9ab9040 100644
--- a/jni/src/jawhypertext.c
+++ b/jni/src/jawhypertext.c
@@ -63,7 +63,7 @@ jaw_hypertext_data_init (jobject ac)
        jclass classHypertext = (*jniEnv)->FindClass(jniEnv, "org/GNOME/Accessibility/AtkHypertext");
        jmethodID jmid = (*jniEnv)->GetMethodID(jniEnv, classHypertext, "<init>", 
"(Ljavax/accessibility/AccessibleContext;)V");
        jobject jatk_hypertext = (*jniEnv)->NewObject(jniEnv, classHypertext, jmid, ac);
-       data->atk_hypertext = (*jniEnv)->NewGlobalRef(jniEnv, jatk_hypertext);
+       data->atk_hypertext = (*jniEnv)->NewWeakGlobalRef(jniEnv, jatk_hypertext);
 
        data->link_table = g_hash_table_new_full(NULL, NULL, NULL, link_destroy_notify);
 
@@ -79,7 +79,7 @@ jaw_hypertext_data_finalize (gpointer p)
        if (data && data->atk_hypertext) {
                g_hash_table_remove_all(data->link_table);
 
-               (*jniEnv)->DeleteGlobalRef(jniEnv, data->atk_hypertext);
+               (*jniEnv)->DeleteWeakGlobalRef(jniEnv, data->atk_hypertext);
                data->atk_hypertext = NULL;
        }
 }
@@ -89,12 +89,16 @@ jaw_hypertext_get_link (AtkHypertext *hypertext, gint link_index)
 {
        JawObject *jaw_obj = JAW_OBJECT(hypertext);
        HypertextData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_HYPERTEXT);
-       jobject atk_hypertext = data->atk_hypertext;
-       
        JNIEnv *jniEnv = jaw_util_get_jni_env();
+       jobject atk_hypertext = (*jniEnv)->NewGlobalRef(jniEnv, data->atk_hypertext);
+       if (!atk_hypertext) {
+               return NULL;
+       }
+
        jclass classAtkHypertext = (*jniEnv)->FindClass(jniEnv, "org/GNOME/Accessibility/AtkHypertext");
        jmethodID jmid = (*jniEnv)->GetMethodID(jniEnv, classAtkHypertext, "get_link", 
"(I)Lorg/GNOME/Accessibility/AtkHyperlink;");
        jobject jhyperlink = (*jniEnv)->CallObjectMethod(jniEnv, atk_hypertext, jmid, (jint)link_index);
+       (*jniEnv)->DeleteGlobalRef(jniEnv, atk_hypertext);
 
        if (!jhyperlink) {
                return NULL;
@@ -111,13 +115,18 @@ jaw_hypertext_get_n_links (AtkHypertext *hypertext)
 {
        JawObject *jaw_obj = JAW_OBJECT(hypertext);
        HypertextData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_HYPERTEXT);
-       jobject atk_hypertext = data->atk_hypertext;
-       
        JNIEnv *jniEnv = jaw_util_get_jni_env();
+       jobject atk_hypertext = (*jniEnv)->NewGlobalRef(jniEnv, data->atk_hypertext);
+       if (!atk_hypertext) {
+               return 0;
+       }
+
        jclass classAtkHypertext = (*jniEnv)->FindClass(jniEnv, "org/GNOME/Accessibility/AtkHypertext");
        jmethodID jmid = (*jniEnv)->GetMethodID(jniEnv, classAtkHypertext, "get_n_links", "()I");
        
-       return (gint)(*jniEnv)->CallIntMethod(jniEnv, atk_hypertext, jmid);
+       gint ret = (gint)(*jniEnv)->CallIntMethod(jniEnv, atk_hypertext, jmid);
+       (*jniEnv)->DeleteGlobalRef(jniEnv, atk_hypertext);
+       return ret;
 }
 
 static gint
@@ -125,12 +134,17 @@ jaw_hypertext_get_link_index (AtkHypertext *hypertext, gint char_index)
 {
        JawObject *jaw_obj = JAW_OBJECT(hypertext);
        HypertextData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_HYPERTEXT);
-       jobject atk_hypertext = data->atk_hypertext;
-       
        JNIEnv *jniEnv = jaw_util_get_jni_env();
+       jobject atk_hypertext = (*jniEnv)->NewGlobalRef(jniEnv, data->atk_hypertext);
+       if (!atk_hypertext) {
+               return 0;
+       }
+
        jclass classAtkHypertext = (*jniEnv)->FindClass(jniEnv, "org/GNOME/Accessibility/AtkHypertext");
        jmethodID jmid = (*jniEnv)->GetMethodID(jniEnv, classAtkHypertext, "get_link_index", "(I)I");
        
-       return (gint)(*jniEnv)->CallIntMethod(jniEnv, atk_hypertext, jmid, (jint)char_index);
+       gint ret = (gint)(*jniEnv)->CallIntMethod(jniEnv, atk_hypertext, jmid, (jint)char_index);
+       (*jniEnv)->DeleteGlobalRef(jniEnv, atk_hypertext);
+       return ret;
 }
 
diff --git a/jni/src/jawimage.c b/jni/src/jawimage.c
index 26b1b2d..e7425fe 100644
--- a/jni/src/jawimage.c
+++ b/jni/src/jawimage.c
@@ -59,7 +59,7 @@ jaw_image_data_init (jobject ac)
        jclass classImage = (*jniEnv)->FindClass(jniEnv, "org/GNOME/Accessibility/AtkImage");
        jmethodID jmid = (*jniEnv)->GetMethodID(jniEnv, classImage, "<init>", 
"(Ljavax/accessibility/AccessibleContext;)V");
        jobject jatk_image = (*jniEnv)->NewObject(jniEnv, classImage, jmid, ac);
-       data->atk_image = (*jniEnv)->NewGlobalRef(jniEnv, jatk_image);
+       data->atk_image = (*jniEnv)->NewWeakGlobalRef(jniEnv, jatk_image);
 
        return data;
 }
@@ -79,7 +79,7 @@ jaw_image_data_finalize (gpointer p)
                }
 
 
-               (*jniEnv)->DeleteGlobalRef(jniEnv, data->atk_image);
+               (*jniEnv)->DeleteWeakGlobalRef(jniEnv, data->atk_image);
                data->atk_image = NULL;
        }
 }
@@ -90,12 +90,16 @@ jaw_image_get_image_position (AtkImage *image,
 {
        JawObject *jaw_obj = JAW_OBJECT(image);
        ImageData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_IMAGE);
-       jobject atk_image = data->atk_image;
-
        JNIEnv *jniEnv = jaw_util_get_jni_env();
+       jobject atk_image = (*jniEnv)->NewGlobalRef(jniEnv, data->atk_image);
+       if (!atk_image) {
+               return;
+       }
+
        jclass classAtkImage = (*jniEnv)->FindClass(jniEnv, "org/GNOME/Accessibility/AtkImage");
        jmethodID jmid = (*jniEnv)->GetMethodID(jniEnv, classAtkImage, "get_image_position", 
"(I)Ljava/awt/Point;");
        jobject jpoint = (*jniEnv)->CallObjectMethod(jniEnv, atk_image, jmid, (jint)coord_type);
+       (*jniEnv)->DeleteGlobalRef(jniEnv, atk_image);
        
        if (jpoint == NULL) {
                (*x) = 0;
@@ -118,12 +122,16 @@ jaw_image_get_image_description (AtkImage *image)
 {
        JawObject *jaw_obj = JAW_OBJECT(image);
        ImageData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_IMAGE);
-       jobject atk_image = data->atk_image;
-
        JNIEnv *jniEnv = jaw_util_get_jni_env();
+       jobject atk_image = (*jniEnv)->NewGlobalRef(jniEnv, data->atk_image);
+       if (!atk_image) {
+               return NULL;
+       }
+
        jclass classAtkImage = (*jniEnv)->FindClass(jniEnv, "org/GNOME/Accessibility/AtkImage");
        jmethodID jmid = (*jniEnv)->GetMethodID(jniEnv, classAtkImage, "get_image_description", 
"()Ljava/lang/String;");
        jstring jstr = (*jniEnv)->CallObjectMethod(jniEnv, atk_image, jmid);
+       (*jniEnv)->DeleteGlobalRef(jniEnv, atk_image);
        
        if (data->image_description != NULL) {
                (*jniEnv)->ReleaseStringUTFChars(jniEnv, data->jstrImageDescription, data->image_description);
@@ -141,12 +149,16 @@ jaw_image_get_image_size (AtkImage *image, gint *width, gint *height)
 {
        JawObject *jaw_obj = JAW_OBJECT(image);
        ImageData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_IMAGE);
-       jobject atk_image = data->atk_image;
-
        JNIEnv *jniEnv = jaw_util_get_jni_env();
+       jobject atk_image = (*jniEnv)->NewGlobalRef(jniEnv, data->atk_image);
+       if (!atk_image) {
+               return;
+       }
+
        jclass classAtkImage = (*jniEnv)->FindClass(jniEnv, "org/GNOME/Accessibility/AtkImage");
        jmethodID jmid = (*jniEnv)->GetMethodID(jniEnv, classAtkImage, "get_image_size", 
"()Ljava/awt/Dimension;");
        jobject jdimension = (*jniEnv)->CallObjectMethod(jniEnv, atk_image, jmid);
+       (*jniEnv)->DeleteGlobalRef(jniEnv, atk_image);
 
        if (jdimension == NULL) {
                (*width) = 0;
diff --git a/jni/src/jawimpl.c b/jni/src/jawimpl.c
index ba488aa..f2f19fa 100644
--- a/jni/src/jawimpl.c
+++ b/jni/src/jawimpl.c
@@ -107,9 +107,9 @@ object_table_insert (JNIEnv *jniEnv, jobject ac, JawImpl* jaw_impl)
                                           classAccessibleContext,
                                           "hashCode",
                                           "()I");
-  gint hash_key = (gint)(*jniEnv)->CallIntMethod(jniEnv, ac, jmid);
+  jaw_impl->hash_key = (gint)(*jniEnv)->CallIntMethod(jniEnv, ac, jmid);
   g_mutex_lock(&objectTableMutex);
-  g_hash_table_insert(objectTable, GINT_TO_POINTER(hash_key), GINT_TO_POINTER(jaw_impl));
+  g_hash_table_insert(objectTable, GINT_TO_POINTER(jaw_impl->hash_key), jaw_impl);
   g_mutex_unlock(&objectTableMutex);
 }
 
@@ -137,19 +137,44 @@ object_table_lookup (JNIEnv *jniEnv, jobject ac)
 }
 
 static void
-object_table_remove(JNIEnv *jniEnv, jobject ac)
+object_table_remove(JNIEnv *jniEnv, JawImpl *jaw_impl)
 {
-  jclass classAccessibleContext = (*jniEnv)->FindClass( jniEnv,
-                                                       "javax/accessibility/AccessibleContext" );
-  jmethodID jmid = (*jniEnv)->GetMethodID(jniEnv,
-                                          classAccessibleContext,
-                                          "hashCode",
-                                          "()I" );
-  gint hash_key = (gint)(*jniEnv)->CallIntMethod( jniEnv, ac, jmid );
+  g_mutex_lock(&objectTableMutex);
+  g_hash_table_remove(objectTable, GINT_TO_POINTER(jaw_impl->hash_key));
+  g_mutex_unlock(&objectTableMutex);
+}
+
+/* Called on completion of Java GC, take the opportunity to look for stale jaw_impl */
+void
+object_table_gc(JNIEnv *jniEnv)
+{
+  GHashTableIter iter;
+  gpointer key, value;
+  GSList *list = NULL, *cur, *next;
 
   g_mutex_lock(&objectTableMutex);
-  g_hash_table_remove(objectTable, GINT_TO_POINTER(hash_key));
+  if (objectTable)
+  {
+    g_hash_table_iter_init(&iter, objectTable);
+    while (g_hash_table_iter_next(&iter, &key, &value))
+    {
+      JawImpl *jaw_impl = value;
+      if ((*jniEnv)->IsSameObject(jniEnv, jaw_impl->parent.acc_context, NULL))
+      {
+       /* Got garbage-collected, mark for dropping */
+       list = g_slist_prepend(list, jaw_impl);
+      }
+    }
+  }
   g_mutex_unlock(&objectTableMutex);
+
+  for (cur = list; cur != NULL; cur = next)
+  {
+    JawImpl *jaw_impl = cur->data;
+    g_object_unref(G_OBJECT(jaw_impl));
+    next = g_slist_next(cur);
+    g_slist_free_1(cur);
+  }
 }
 
 GHashTable*
@@ -169,7 +194,7 @@ aggregate_interface(JNIEnv *jniEnv, JawObject *jaw_obj, guint tflag)
 {
   JawImpl *jaw_impl = JAW_IMPL(tflag, jaw_obj);
 
-  jobject ac = jaw_obj->acc_context;
+  jobject ac = (*jniEnv)->NewGlobalRef(jniEnv, jaw_obj->acc_context);
   jaw_impl->ifaceTable = g_hash_table_new(NULL, NULL);
 
   if (tflag & INTERFACE_ACTION)
@@ -271,6 +296,8 @@ aggregate_interface(JNIEnv *jniEnv, JawObject *jaw_obj, guint tflag)
                         (gpointer)INTERFACE_TABLE_CELL,
                         (gpointer)info);
   }
+
+  (*jniEnv)->DeleteGlobalRef(jniEnv, ac);
 }
 
 JawImpl*
@@ -291,10 +318,10 @@ jaw_impl_get_instance (JNIEnv *jniEnv, jobject ac)
 
   if (jaw_impl == NULL)
   {
-    jobject global_ac = (*jniEnv)->NewGlobalRef(jniEnv, ac);
-    if (global_ac != NULL)
+    jobject temp_ref = (*jniEnv)->NewGlobalRef(jniEnv, ac);
+    if (temp_ref != NULL)
     {
-      guint tflag = jaw_util_get_tflag_from_jobj(jniEnv, global_ac);
+      guint tflag = jaw_util_get_tflag_from_jobj(jniEnv, temp_ref);
       jaw_impl = (JawImpl*)g_object_new(JAW_TYPE_IMPL(tflag), NULL);
       if (jaw_impl != NULL)
       {
@@ -302,15 +329,17 @@ jaw_impl_get_instance (JNIEnv *jniEnv, jobject ac)
 
         if (jaw_obj != NULL)
         {
-          jaw_obj->acc_context = global_ac;
+          jobject weak_ref = (*jniEnv)->NewWeakGlobalRef(jniEnv, temp_ref);
+          jaw_obj->acc_context = weak_ref;
           jaw_obj->storedData = g_hash_table_new(g_str_hash, g_str_equal);
           aggregate_interface(jniEnv, jaw_obj, tflag);
           atk_object_initialize(ATK_OBJECT(jaw_impl), NULL);
-          object_table_insert(jniEnv, global_ac, jaw_impl);
+          object_table_insert(jniEnv, weak_ref, jaw_impl);
         } else
         {
           if (jaw_debug)
             g_warning("jaw_impl_get_instance: jaw_obj == NULL");
+          (*jniEnv)->DeleteGlobalRef(jniEnv, temp_ref);
           return NULL;
         }
       } else
@@ -318,6 +347,7 @@ jaw_impl_get_instance (JNIEnv *jniEnv, jobject ac)
         if (jaw_debug)
           g_warning("jaw_impl_get_instance: jaw_impl == NULL");
       }
+      (*jniEnv)->DeleteGlobalRef(jniEnv, temp_ref);
     } else
     {
       if (jaw_debug)
@@ -528,14 +558,12 @@ static void
 jaw_impl_finalize(GObject *gobject)
 {
   JawObject *jaw_obj = JAW_OBJECT(gobject);
-  jobject global_ac = jaw_obj->acc_context;
-
   JawImpl *jaw_impl = (JawImpl*)jaw_obj;
 
   JNIEnv *jniEnv = jaw_util_get_jni_env();
-  object_table_remove( jniEnv, global_ac );
+  object_table_remove( jniEnv, jaw_impl );
 
-  (*jniEnv)->DeleteGlobalRef(jniEnv, global_ac);
+  (*jniEnv)->DeleteWeakGlobalRef(jniEnv, jaw_obj->acc_context);
   jaw_obj->acc_context = NULL;
 
   /* Interface finalize */
@@ -583,8 +611,8 @@ jaw_impl_initialize (AtkObject *atk_obj, gpointer data)
   ATK_OBJECT_CLASS(jaw_impl_parent_class)->initialize(atk_obj, data);
 
   JawObject *jaw_obj = JAW_OBJECT(atk_obj);
-  jobject ac = jaw_obj->acc_context;
   JNIEnv *jniEnv = jaw_util_get_jni_env();
+  jobject ac = (*jniEnv)->NewGlobalRef(jniEnv, jaw_obj->acc_context);
 
   jclass classAtkWrapper = (*jniEnv)->FindClass(jniEnv,
                                                 "org/GNOME/Accessibility/AtkWrapper");
@@ -593,6 +621,7 @@ jaw_impl_initialize (AtkObject *atk_obj, gpointer data)
                                                 "registerPropertyChangeListener",
                                                 "(Ljavax/accessibility/AccessibleContext;)V");
   (*jniEnv)->CallStaticVoidMethod(jniEnv, classAtkWrapper, jmid, ac);
+  (*jniEnv)->DeleteGlobalRef(jniEnv, ac);
 }
 
 static AtkObject*
@@ -604,8 +633,11 @@ jaw_impl_get_parent (AtkObject *atk_obj)
   }
 
   JawObject *jaw_obj = JAW_OBJECT(atk_obj);
-  jobject ac = jaw_obj->acc_context;
   JNIEnv *jniEnv = jaw_util_get_jni_env();
+  jobject ac = (*jniEnv)->NewGlobalRef(jniEnv, jaw_obj->acc_context);
+  if (!ac) {
+    return NULL;
+  }
 
   jclass classAccessibleContext = (*jniEnv)->FindClass(jniEnv,
                                                        "javax/accessibility/AccessibleContext" );
@@ -614,6 +646,7 @@ jaw_impl_get_parent (AtkObject *atk_obj)
                                           "getAccessibleParent",
                                           "()Ljavax/accessibility/Accessible;");
   jobject jparent = (*jniEnv)->CallObjectMethod( jniEnv, ac, jmid );
+  (*jniEnv)->DeleteGlobalRef(jniEnv, ac);
   if (jparent != NULL )
   {
     jclass classAccessible = (*jniEnv)->FindClass(jniEnv,
@@ -637,8 +670,11 @@ static AtkObject*
 jaw_impl_ref_child (AtkObject *atk_obj, gint i)
 {
   JawObject *jaw_obj = JAW_OBJECT(atk_obj);
-  jobject ac = jaw_obj->acc_context;
   JNIEnv *jniEnv = jaw_util_get_jni_env();
+  jobject ac = (*jniEnv)->NewGlobalRef(jniEnv, jaw_obj->acc_context);
+  if (!ac) {
+    return NULL;
+  }
 
   jclass classAccessibleContext = (*jniEnv)->FindClass(jniEnv,
                                                        "javax/accessibility/AccessibleContext" );
@@ -647,6 +683,7 @@ jaw_impl_ref_child (AtkObject *atk_obj, gint i)
                                           "getAccessibleChild",
                                           "(I)Ljavax/accessibility/Accessible;" );
   jobject jchild = (*jniEnv)->CallObjectMethod( jniEnv, ac, jmid, i );
+  (*jniEnv)->DeleteGlobalRef(jniEnv, ac);
   if (jchild == NULL)
   {
     return NULL;
@@ -767,8 +804,11 @@ jaw_impl_ref_relation_set (AtkObject *atk_obj)
     return NULL;
 
   JawObject *jaw_obj = JAW_OBJECT(atk_obj);
-  jobject ac = jaw_obj->acc_context;
   JNIEnv *jniEnv = jaw_util_get_jni_env();
+  jobject ac = (*jniEnv)->NewGlobalRef(jniEnv, jaw_obj->acc_context);
+  if (!ac) {
+    return NULL;
+  }
 
   jclass classAccessibleContext = (*jniEnv)->FindClass(jniEnv,
                                                        "javax/accessibility/AccessibleContext" );
@@ -777,6 +817,7 @@ jaw_impl_ref_relation_set (AtkObject *atk_obj)
                                           "getAccessibleRelationSet",
                                           "()Ljavax/accessibility/AccessibleRelationSet;" );
   jobject jrel_set = (*jniEnv)->CallObjectMethod( jniEnv, ac, jmid );
+  (*jniEnv)->DeleteGlobalRef(jniEnv, ac);
 
   jclass classAccessibleRelationSet = (*jniEnv)->FindClass( jniEnv,
                                                            "javax/accessibility/AccessibleRelationSet");
diff --git a/jni/src/jawimpl.h b/jni/src/jawimpl.h
index 8984ead..818c06c 100644
--- a/jni/src/jawimpl.h
+++ b/jni/src/jawimpl.h
@@ -47,12 +47,14 @@ struct _JawImpl
        JawObject parent;
 
        GHashTable *ifaceTable;
+       gint hash_key;
 };
 
 JawImpl* jaw_impl_get_instance(JNIEnv*, jobject);
 JawImpl* jaw_impl_find_instance(JNIEnv*, jobject);
 GHashTable* jaw_impl_get_object_hash_table(void);
 GMutex* jaw_impl_get_object_hash_table_mutex(void);
+void object_table_gc(JNIEnv *jniEnv);
 
 GType jaw_impl_get_type (guint);
 AtkRelationType jaw_impl_get_atk_relation_type(JNIEnv *jniEnv, jstring jrel_key);
diff --git a/jni/src/jawobject.c b/jni/src/jawobject.c
index 1a5a342..d0c31d4 100644
--- a/jni/src/jawobject.c
+++ b/jni/src/jawobject.c
@@ -205,8 +205,11 @@ static AtkObject* jaw_object_get_parent(AtkObject *atk_obj)
   }
 
   JawObject *jaw_obj = JAW_OBJECT(atk_obj);
-  jobject ac = jaw_obj->acc_context;
   JNIEnv *jniEnv = jaw_util_get_jni_env();
+  jobject ac = (*jniEnv)->NewGlobalRef(jniEnv, jaw_obj->acc_context);
+  if (!ac) {
+    return NULL;
+  }
 
   jclass classAccessibleContext = (*jniEnv)->FindClass(jniEnv,
                                                        "javax/accessibility/AccessibleContext" );
@@ -215,6 +218,7 @@ static AtkObject* jaw_object_get_parent(AtkObject *atk_obj)
                                           "getAccessibleParent",
                                           "()Ljavax/accessibility/AccessibleContext;");
   jobject jparent = (*jniEnv)->CallObjectMethod( jniEnv, ac, jmid );
+  (*jniEnv)->DeleteGlobalRef(jniEnv, ac);
   if (jparent != NULL )
   {
     jclass classAccessible = (*jniEnv)->FindClass(jniEnv,
@@ -235,8 +239,11 @@ static void
 jaw_object_set_parent(AtkObject *atk_obj, AtkObject *parent)
 {
   JawObject *jaw_obj = JAW_OBJECT(atk_obj);
-  jobject ac = jaw_obj->acc_context;
   JNIEnv *jniEnv = jaw_util_get_jni_env();
+  jobject ac = (*jniEnv)->NewGlobalRef(jniEnv, jaw_obj->acc_context);
+  if (!ac) {
+    return;
+  }
 
   jclass classAccessibleContext = (*jniEnv)->FindClass(jniEnv,
                                                        "javax/accessibility/AccessibleContext" );
@@ -245,6 +252,7 @@ jaw_object_set_parent(AtkObject *atk_obj, AtkObject *parent)
                                           "setAccessibleParent",
                                           "(Ljavax/accessibility/AccessibleContext;)");
   jobject jparent = (*jniEnv)->CallObjectMethod( jniEnv, ac, jmid );
+  (*jniEnv)->DeleteGlobalRef(jniEnv, ac);
   if (jparent != NULL )
   {
     jclass classAccessible = (*jniEnv)->FindClass(jniEnv,
@@ -264,7 +272,6 @@ static const gchar*
 jaw_object_get_name (AtkObject *atk_obj)
 {
   JawObject *jaw_obj = JAW_OBJECT(atk_obj);
-  jobject ac = jaw_obj->acc_context;
   JNIEnv *jniEnv = jaw_util_get_jni_env();
 
   atk_obj->name = (gchar *)ATK_OBJECT_CLASS (parent_class)->get_name (atk_obj);
@@ -283,6 +290,11 @@ jaw_object_get_name (AtkObject *atk_obj)
     }
   }
 
+  jobject ac = (*jniEnv)->NewGlobalRef(jniEnv, jaw_obj->acc_context);
+  if (!ac) {
+    return NULL;
+  }
+
   jclass classAccessibleContext = (*jniEnv)->FindClass(jniEnv,
                                                        "javax/accessibility/AccessibleContext" );
   jmethodID jmid = (*jniEnv)->GetMethodID(jniEnv,
@@ -290,6 +302,7 @@ jaw_object_get_name (AtkObject *atk_obj)
                                           "getAccessibleName",
                                           "()Ljava/lang/String;");
   jstring jstr = (*jniEnv)->CallObjectMethod( jniEnv, ac, jmid );
+  (*jniEnv)->DeleteGlobalRef(jniEnv, ac);
 
   if (atk_obj->name != NULL)
   {
@@ -313,8 +326,11 @@ jaw_object_get_name (AtkObject *atk_obj)
 static void jaw_object_set_name (AtkObject *atk_obj, const gchar *name)
 {
   JawObject *jaw_obj = JAW_OBJECT(atk_obj);
-  jobject ac = jaw_obj->acc_context;
   JNIEnv *jniEnv = jaw_util_get_jni_env();
+  jobject ac = (*jniEnv)->NewGlobalRef(jniEnv, jaw_obj->acc_context);
+  if (!ac) {
+    return;
+  }
 
   atk_obj->name = (gchar *)ATK_OBJECT_CLASS (parent_class)->get_name (atk_obj);
 
@@ -325,6 +341,7 @@ static void jaw_object_set_name (AtkObject *atk_obj, const gchar *name)
                                           "setAccessibleName",
                                           "(Ljava/lang/String;)");
   jstring jstr = (*jniEnv)->CallObjectMethod( jniEnv, ac, jmid );
+  (*jniEnv)->DeleteGlobalRef(jniEnv, ac);
 
   if (atk_obj->name != NULL)
   {
@@ -352,8 +369,11 @@ static const gchar*
 jaw_object_get_description (AtkObject *atk_obj)
 {
   JawObject *jaw_obj = JAW_OBJECT(atk_obj);
-  jobject ac = jaw_obj->acc_context;
   JNIEnv *jniEnv = jaw_util_get_jni_env();
+  jobject ac = (*jniEnv)->NewGlobalRef(jniEnv, jaw_obj->acc_context);
+  if (!ac) {
+    return NULL;
+  }
 
   jclass classAccessibleContext = (*jniEnv)->FindClass( jniEnv,
                                                        "javax/accessibility/AccessibleContext" );
@@ -362,6 +382,7 @@ jaw_object_get_description (AtkObject *atk_obj)
                                           "getAccessibleDescription",
                                           "()Ljava/lang/String;");
   jstring jstr = (*jniEnv)->CallObjectMethod( jniEnv, ac, jmid );
+  (*jniEnv)->DeleteGlobalRef(jniEnv, ac);
 
   if (atk_obj->description != NULL)
   {
@@ -384,8 +405,11 @@ jaw_object_get_description (AtkObject *atk_obj)
 static void jaw_object_set_description (AtkObject *atk_obj, const gchar *description)
 {
   JawObject *jaw_obj = JAW_OBJECT(atk_obj);
-  jobject ac = jaw_obj->acc_context;
   JNIEnv *jniEnv = jaw_util_get_jni_env();
+  jobject ac = (*jniEnv)->NewGlobalRef(jniEnv, jaw_obj->acc_context);
+  if (!ac) {
+    return;
+  }
 
   jclass classAccessibleContext = (*jniEnv)->FindClass( jniEnv,
                                                        "javax/accessibility/AccessibleContext" );
@@ -394,6 +418,7 @@ static void jaw_object_set_description (AtkObject *atk_obj, const gchar *descrip
                                           "setAccessibleDescription",
                                           "(Ljava/lang/String;)");
   jstring jstr = (*jniEnv)->CallObjectMethod( jniEnv, ac, jmid );
+  (*jniEnv)->DeleteGlobalRef(jniEnv, ac);
 
   if (description != NULL)
   {
@@ -420,8 +445,11 @@ static gint
 jaw_object_get_n_children (AtkObject *atk_obj)
 {
   JawObject *jaw_obj = JAW_OBJECT(atk_obj);
-  jobject ac = jaw_obj->acc_context;
   JNIEnv *jniEnv = jaw_util_get_jni_env();
+  jobject ac = (*jniEnv)->NewGlobalRef(jniEnv, jaw_obj->acc_context);
+  if (!ac) {
+    return 0;
+  }
 
   jclass classAccessibleContext = (*jniEnv)->FindClass(jniEnv,
                                                        "javax/accessibility/AccessibleContext" );
@@ -430,6 +458,7 @@ jaw_object_get_n_children (AtkObject *atk_obj)
                                           "getAccessibleChildrenCount",
                                           "()I");
   jint count = (*jniEnv)->CallIntMethod( jniEnv, ac, jmid );
+  (*jniEnv)->DeleteGlobalRef(jniEnv, ac);
 
   return (gint)count;
 }
@@ -443,8 +472,11 @@ jaw_object_get_index_in_parent (AtkObject *atk_obj)
   }
 
   JawObject *jaw_obj = JAW_OBJECT(atk_obj);
-  jobject ac = jaw_obj->acc_context;
   JNIEnv *jniEnv = jaw_util_get_jni_env();
+  jobject ac = (*jniEnv)->NewGlobalRef(jniEnv, jaw_obj->acc_context);
+  if (!ac) {
+    return 0;
+  }
 
   jclass classAccessibleContext = (*jniEnv)->FindClass(jniEnv,
                                                        "javax/accessibility/AccessibleContext" );
@@ -453,6 +485,7 @@ jaw_object_get_index_in_parent (AtkObject *atk_obj)
                                           "getAccessibleIndexInParent",
                                           "()I");
   jint index = (*jniEnv)->CallIntMethod( jniEnv, ac, jmid );
+  (*jniEnv)->DeleteGlobalRef(jniEnv, ac);
 
   return (gint)index;
 }
@@ -461,7 +494,13 @@ static AtkRole
 jaw_object_get_role (AtkObject *atk_obj)
 {
   JawObject *jaw_obj = JAW_OBJECT(atk_obj);
-  atk_obj->role = jaw_util_get_atk_role_from_jobj(jaw_obj->acc_context);
+  JNIEnv *jniEnv = jaw_util_get_jni_env();
+  jobject ac = (*jniEnv)->NewGlobalRef(jniEnv, jaw_obj->acc_context);
+  if (!ac) {
+    return 0;
+  }
+  atk_obj->role = jaw_util_get_atk_role_from_jobj(ac);
+  (*jniEnv)->DeleteGlobalRef(jniEnv, ac);
   return atk_obj->role;
 }
 
@@ -480,8 +519,11 @@ jaw_object_ref_state_set (AtkObject *atk_obj)
   AtkStateSet* state_set = jaw_obj->state_set;
   atk_state_set_clear_states( state_set );
 
-  jobject ac = jaw_obj->acc_context;
   JNIEnv *jniEnv = jaw_util_get_jni_env();
+  jobject ac = (*jniEnv)->NewGlobalRef(jniEnv, jaw_obj->acc_context);
+  if (!ac) {
+    return NULL;
+  }
   jclass classAccessibleContext = (*jniEnv)->FindClass(jniEnv,
                                                        "javax/accessibility/AccessibleContext" );
   jmethodID jmid = (*jniEnv)->GetMethodID(jniEnv,
@@ -489,6 +531,7 @@ jaw_object_ref_state_set (AtkObject *atk_obj)
                                           "getAccessibleStateSet",
                                           "()Ljavax/accessibility/AccessibleStateSet;" );
   jobject jstate_set = (*jniEnv)->CallObjectMethod( jniEnv, ac, jmid );
+  (*jniEnv)->DeleteGlobalRef(jniEnv, ac);
   if (jstate_set == NULL)
     return NULL;
 
@@ -523,8 +566,11 @@ jaw_object_ref_state_set (AtkObject *atk_obj)
 static const gchar *jaw_object_get_object_locale (AtkObject *atk_obj)
 {
   JawObject *jaw_obj = JAW_OBJECT(atk_obj);
-  jobject ac = jaw_obj->acc_context;
   JNIEnv *jniEnv = jaw_util_get_jni_env();
+  jobject ac = (*jniEnv)->NewGlobalRef(jniEnv, jaw_obj->acc_context);
+  if (!ac) {
+    return NULL;
+  }
 
   jclass classAccessibleContext = (*jniEnv)->FindClass(jniEnv,
                                                        "javax/accessibility/AccessibleContext" );
@@ -533,6 +579,7 @@ static const gchar *jaw_object_get_object_locale (AtkObject *atk_obj)
                                           "getLocale",
                                           "()Ljavax/accessibility/AccessibleContext;");
   jobject locale = (*jniEnv)->CallObjectMethod( jniEnv, ac, jmid );
+  (*jniEnv)->DeleteGlobalRef(jniEnv, ac);
   JawImpl *target_obj = jaw_impl_get_instance(jniEnv, locale);
   if(target_obj == NULL)
     return NULL;
@@ -550,8 +597,11 @@ jaw_object_ref_relation_set (AtkObject *atk_obj)
     return NULL;
 
   JawObject *jaw_obj = JAW_OBJECT(atk_obj);
-  jobject ac = jaw_obj->acc_context;
   JNIEnv *jniEnv = jaw_util_get_jni_env();
+  jobject ac = (*jniEnv)->NewGlobalRef(jniEnv, jaw_obj->acc_context);
+  if (!ac) {
+    return NULL;
+  }
 
   jclass classAccessibleContext = (*jniEnv)->FindClass(jniEnv,
                                                        "javax/accessibility/AccessibleContext" );
@@ -560,6 +610,7 @@ jaw_object_ref_relation_set (AtkObject *atk_obj)
                                           "getAccessibleRelationSet",
                                           "()Ljavax/accessibility/AccessibleRelationSet;" );
   jobject jrel_set = (*jniEnv)->CallObjectMethod( jniEnv, ac, jmid );
+  (*jniEnv)->DeleteGlobalRef(jniEnv, ac);
 
   jclass classAccessibleRelationSet = (*jniEnv)->FindClass( jniEnv,
                                                            "javax/accessibility/AccessibleRelationSet");
@@ -623,8 +674,11 @@ static AtkObject*
 jaw_object_ref_child(AtkObject *atk_obj, gint i)
 {
   JawObject *jaw_obj = JAW_OBJECT(atk_obj);
-  jobject ac = jaw_obj->acc_context;
   JNIEnv *jniEnv = jaw_util_get_jni_env();
+  jobject ac = (*jniEnv)->NewGlobalRef(jniEnv, jaw_obj->acc_context);
+  if (!ac) {
+    return NULL;
+  }
 
   jclass classAccessibleContext = (*jniEnv)->FindClass(jniEnv,
                                                        "javax/accessibility/AccessibleContext" );
@@ -633,6 +687,7 @@ jaw_object_ref_child(AtkObject *atk_obj, gint i)
                                           "getAccessibleChild",
                                           "(I)Ljavax/accessibility/Accessible;" );
   jobject jchild = (*jniEnv)->CallObjectMethod( jniEnv, ac, jmid, i );
+  (*jniEnv)->DeleteGlobalRef(jniEnv, ac);
   if (jchild == NULL)
   {
     return NULL;
diff --git a/jni/src/jawselection.c b/jni/src/jawselection.c
index a56ced2..e882b50 100644
--- a/jni/src/jawselection.c
+++ b/jni/src/jawselection.c
@@ -63,7 +63,7 @@ jaw_selection_data_init (jobject ac)
        jclass classSelection = (*jniEnv)->FindClass(jniEnv, "org/GNOME/Accessibility/AtkSelection");
        jmethodID jmid = (*jniEnv)->GetMethodID(jniEnv, classSelection, "<init>", 
"(Ljavax/accessibility/AccessibleContext;)V");
        jobject jatk_selection = (*jniEnv)->NewObject(jniEnv, classSelection, jmid, ac);
-       data->atk_selection = (*jniEnv)->NewGlobalRef(jniEnv, jatk_selection);
+       data->atk_selection = (*jniEnv)->NewWeakGlobalRef(jniEnv, jatk_selection);
 
        return data;
 }
@@ -75,7 +75,7 @@ jaw_selection_data_finalize (gpointer p)
        JNIEnv *jniEnv = jaw_util_get_jni_env();
 
        if (data && data->atk_selection) {
-               (*jniEnv)->DeleteGlobalRef(jniEnv, data->atk_selection);
+               (*jniEnv)->DeleteWeakGlobalRef(jniEnv, data->atk_selection);
                data->atk_selection = NULL;
        }
 }
@@ -85,12 +85,16 @@ jaw_selection_add_selection (AtkSelection *selection, gint i)
 {
        JawObject *jaw_obj = JAW_OBJECT(selection);
        SelectionData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_SELECTION);
-       jobject atk_selection = data->atk_selection;
-
        JNIEnv *jniEnv = jaw_util_get_jni_env();
+       jobject atk_selection = (*jniEnv)->NewGlobalRef(jniEnv, data->atk_selection);
+       if (!atk_selection) {
+               return FALSE;
+       }
+
        jclass classAtkSelection = (*jniEnv)->FindClass(jniEnv, "org/GNOME/Accessibility/AtkSelection");
        jmethodID jmid = (*jniEnv)->GetMethodID(jniEnv, classAtkSelection, "add_selection", "(I)Z");
        jboolean jbool = (*jniEnv)->CallBooleanMethod(jniEnv, atk_selection, jmid, (jint)i);
+       (*jniEnv)->DeleteGlobalRef(jniEnv, atk_selection);
 
        if (jbool == JNI_TRUE) {
                return TRUE;
@@ -104,12 +108,16 @@ jaw_selection_clear_selection (AtkSelection *selection)
 {
        JawObject *jaw_obj = JAW_OBJECT(selection);
        SelectionData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_SELECTION);
-       jobject atk_selection = data->atk_selection;
-
        JNIEnv *jniEnv = jaw_util_get_jni_env();
+       jobject atk_selection = (*jniEnv)->NewGlobalRef(jniEnv, data->atk_selection);
+       if (!atk_selection) {
+               return FALSE;
+       }
+
        jclass classAtkSelection = (*jniEnv)->FindClass(jniEnv, "org/GNOME/Accessibility/AtkSelection");
        jmethodID jmid = (*jniEnv)->GetMethodID(jniEnv, classAtkSelection, "clear_selection", "()Z");
        jboolean jbool = (*jniEnv)->CallBooleanMethod(jniEnv, atk_selection, jmid);
+       (*jniEnv)->DeleteGlobalRef(jniEnv, atk_selection);
 
        if (jbool == JNI_TRUE) {
                return TRUE;
@@ -123,13 +131,16 @@ jaw_selection_ref_selection (AtkSelection *selection, gint i)
 {
        JawObject *jaw_obj = JAW_OBJECT(selection);
        SelectionData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_SELECTION);
-       jobject atk_selection = data->atk_selection;
-
        JNIEnv *jniEnv = jaw_util_get_jni_env();
+       jobject atk_selection = (*jniEnv)->NewGlobalRef(jniEnv, data->atk_selection);
+       if (!atk_selection) {
+               return NULL;
+       }
+
        jclass classAtkSelection = (*jniEnv)->FindClass(jniEnv, "org/GNOME/Accessibility/AtkSelection");
        jmethodID jmid = (*jniEnv)->GetMethodID(jniEnv, classAtkSelection, "ref_selection", 
"(I)Ljavax/accessibility/Accessible;");
        jobject jchild = (*jniEnv)->CallObjectMethod(jniEnv, atk_selection, jmid, (jint)i);
-
+       (*jniEnv)->DeleteGlobalRef(jniEnv, atk_selection);
        if (!jchild) {
                return NULL;
        }
@@ -149,12 +160,16 @@ jaw_selection_get_selection_count (AtkSelection *selection)
 {
        JawObject *jaw_obj = JAW_OBJECT(selection);
        SelectionData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_SELECTION);
-       jobject atk_selection = data->atk_selection;
-
        JNIEnv *jniEnv = jaw_util_get_jni_env();
+       jobject atk_selection = (*jniEnv)->NewGlobalRef(jniEnv, data->atk_selection);
+       if (!atk_selection) {
+               return 0;
+       }
+
        jclass classAtkSelection = (*jniEnv)->FindClass(jniEnv, "org/GNOME/Accessibility/AtkSelection");
        jmethodID jmid = (*jniEnv)->GetMethodID(jniEnv, classAtkSelection, "get_selection_count", "()I");
        jint jcount = (*jniEnv)->CallIntMethod(jniEnv, atk_selection, jmid);
+       (*jniEnv)->DeleteGlobalRef(jniEnv, atk_selection);
 
        return (gint)jcount;
 }
@@ -164,12 +179,16 @@ jaw_selection_is_child_selected (AtkSelection *selection, gint i)
 {
        JawObject *jaw_obj = JAW_OBJECT(selection);
        SelectionData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_SELECTION);
-       jobject atk_selection = data->atk_selection;
-
        JNIEnv *jniEnv = jaw_util_get_jni_env();
+       jobject atk_selection = (*jniEnv)->NewGlobalRef(jniEnv, data->atk_selection);
+       if (!atk_selection) {
+               return FALSE;
+       }
+
        jclass classAtkSelection = (*jniEnv)->FindClass(jniEnv, "org/GNOME/Accessibility/AtkSelection");
        jmethodID jmid = (*jniEnv)->GetMethodID(jniEnv, classAtkSelection, "is_child_selected", "(I)Z");
        jboolean jbool = (*jniEnv)->CallBooleanMethod(jniEnv, atk_selection, jmid, (jint)i);
+       (*jniEnv)->DeleteGlobalRef(jniEnv, atk_selection);
 
        if (jbool == JNI_TRUE) {
                return TRUE;
@@ -183,12 +202,16 @@ jaw_selection_remove_selection (AtkSelection *selection, gint i)
 {
        JawObject *jaw_obj = JAW_OBJECT(selection);
        SelectionData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_SELECTION);
-       jobject atk_selection = data->atk_selection;
-
        JNIEnv *jniEnv = jaw_util_get_jni_env();
+       jobject atk_selection = (*jniEnv)->NewGlobalRef(jniEnv, data->atk_selection);
+       if (!atk_selection) {
+               return FALSE;
+       }
+
        jclass classAtkSelection = (*jniEnv)->FindClass(jniEnv, "org/GNOME/Accessibility/AtkSelection");
        jmethodID jmid = (*jniEnv)->GetMethodID(jniEnv, classAtkSelection, "remove_selection", "(I)Z");
        jboolean jbool = (*jniEnv)->CallBooleanMethod(jniEnv, atk_selection, jmid, (jint)i);
+       (*jniEnv)->DeleteGlobalRef(jniEnv, atk_selection);
 
        if (jbool == JNI_TRUE) {
                return TRUE;
@@ -202,12 +225,16 @@ jaw_selection_select_all_selection (AtkSelection *selection)
 {
        JawObject *jaw_obj = JAW_OBJECT(selection);
        SelectionData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_SELECTION);
-       jobject atk_selection = data->atk_selection;
-
        JNIEnv *jniEnv = jaw_util_get_jni_env();
+       jobject atk_selection = (*jniEnv)->NewGlobalRef(jniEnv, data->atk_selection);
+       if (!atk_selection) {
+               return FALSE;
+       }
+
        jclass classAtkSelection = (*jniEnv)->FindClass(jniEnv, "org/GNOME/Accessibility/AtkSelection");
        jmethodID jmid = (*jniEnv)->GetMethodID(jniEnv, classAtkSelection, "select_all_selection", "()Z");
        jboolean jbool = (*jniEnv)->CallBooleanMethod(jniEnv, atk_selection, jmid);
+       (*jniEnv)->DeleteGlobalRef(jniEnv, atk_selection);
 
        if (jbool == JNI_TRUE) {
                return TRUE;
diff --git a/jni/src/jawtable.c b/jni/src/jawtable.c
index 2f17f0a..5fc6c32 100644
--- a/jni/src/jawtable.c
+++ b/jni/src/jawtable.c
@@ -108,7 +108,7 @@ jaw_table_data_init (jobject ac)
                                        "(Ljavax/accessibility/AccessibleContext;)V");
 
   jobject jatk_table = (*env)->NewObject(env, classTable, jmid, ac);
-  data->atk_table = (*env)->NewGlobalRef(env, jatk_table);
+  data->atk_table = (*env)->NewWeakGlobalRef(env, jatk_table);
 
   return data;
 }
@@ -129,7 +129,7 @@ jaw_table_data_finalize (gpointer p)
       data->description = NULL;
     }
 
-    (*env)->DeleteGlobalRef(env, data->atk_table);
+    (*env)->DeleteWeakGlobalRef(env, data->atk_table);
     data->atk_table = NULL;
   }
 }
@@ -139,15 +139,19 @@ jaw_table_ref_at (AtkTable *table, gint   row, gint column)
 {
   JawObject *jaw_obj = JAW_OBJECT(table);
   TableData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_TABLE);
-  jobject atk_table = data->atk_table;
-
   JNIEnv *env = jaw_util_get_jni_env();
+  jobject atk_table = (*env)->NewGlobalRef(env, data->atk_table);
+  if (!atk_table) {
+    return NULL;
+  }
+
   jclass classAtkTable = (*env)->FindClass(env, "org/GNOME/Accessibility/AtkTable");
   jmethodID jmid = (*env)->GetMethodID(env,
                                        classAtkTable,
                                        "ref_at",
                                        "(II)Ljavax/accessibility/AccessibleContext;");
   jobject jac = (*env)->CallObjectMethod(env, atk_table, jmid, (jint)row, (jint)column);
+  (*env)->DeleteGlobalRef(env, atk_table);
 
   if (!jac)
     return NULL;
@@ -165,12 +169,16 @@ jaw_table_get_column_at_index (AtkTable *table, gint index)
 {
   JawObject *jaw_obj = JAW_OBJECT(table);
   TableData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_TABLE);
-  jobject atk_table = data->atk_table;
-
   JNIEnv *env = jaw_util_get_jni_env();
+  jobject atk_table = (*env)->NewGlobalRef(env, data->atk_table);
+  if (!atk_table) {
+    return 0;
+  }
+
   jclass classAtkTable = (*env)->FindClass(env, "org/GNOME/Accessibility/AtkTable");
   jmethodID jmid = (*env)->GetMethodID(env, classAtkTable, "get_column_at_index", "(I)I");
   jint jcolumn = (*env)->CallIntMethod(env, atk_table, jmid, (jint)index);
+  (*env)->DeleteGlobalRef(env, atk_table);
 
   return (gint)jcolumn;
 }
@@ -180,12 +188,16 @@ jaw_table_get_row_at_index (AtkTable *table, gint index)
 {
   JawObject *jaw_obj = JAW_OBJECT(table);
   TableData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_TABLE);
-  jobject atk_table = data->atk_table;
-
   JNIEnv *env = jaw_util_get_jni_env();
+  jobject atk_table = (*env)->NewGlobalRef(env, data->atk_table);
+  if (!atk_table) {
+    return 0;
+  }
+
   jclass classAtkTable = (*env)->FindClass(env, "org/GNOME/Accessibility/AtkTable");
   jmethodID jmid = (*env)->GetMethodID(env, classAtkTable, "get_row_at_index", "(I)I");
   jint jrow = (*env)->CallIntMethod(env, atk_table, jmid, (jint)index);
+  (*env)->DeleteGlobalRef(env, atk_table);
 
   return (gint)jrow;
 }
@@ -195,12 +207,16 @@ jaw_table_get_n_columns   (AtkTable *table)
 {
   JawObject *jaw_obj = JAW_OBJECT(table);
   TableData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_TABLE);
-  jobject atk_table = data->atk_table;
-
   JNIEnv *env = jaw_util_get_jni_env();
+  jobject atk_table = (*env)->NewGlobalRef(env, data->atk_table);
+  if (!atk_table) {
+    return 0;
+  }
+
   jclass classAtkTable = (*env)->FindClass(env, "org/GNOME/Accessibility/AtkTable");
   jmethodID jmid = (*env)->GetMethodID(env, classAtkTable, "get_n_columns", "()I");
   jint jcolumns = (*env)->CallIntMethod(env, atk_table, jmid);
+  (*env)->DeleteGlobalRef(env, atk_table);
 
   return (gint)jcolumns;
 }
@@ -210,12 +226,16 @@ jaw_table_get_n_rows (AtkTable *table)
 {
   JawObject *jaw_obj = JAW_OBJECT(table);
   TableData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_TABLE);
-  jobject atk_table = data->atk_table;
-
   JNIEnv *env = jaw_util_get_jni_env();
+  jobject atk_table = (*env)->NewGlobalRef(env, data->atk_table);
+  if (!atk_table) {
+    return 0;
+  }
+
   jclass classAtkTable = (*env)->FindClass(env, "org/GNOME/Accessibility/AtkTable");
   jmethodID jmid = (*env)->GetMethodID(env, classAtkTable, "get_n_rows", "()I");
   jint jrows = (*env)->CallIntMethod(env, atk_table, jmid);
+  (*env)->DeleteGlobalRef(env, atk_table);
 
   return (gint)jrows;
 }
@@ -225,12 +245,16 @@ jaw_table_get_column_extent_at (AtkTable *table, gint row, gint   column)
 {
   JawObject *jaw_obj = JAW_OBJECT(table);
   TableData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_TABLE);
-  jobject atk_table = data->atk_table;
-
   JNIEnv *env = jaw_util_get_jni_env();
+  jobject atk_table = (*env)->NewGlobalRef(env, data->atk_table);
+  if (!atk_table) {
+    return 0;
+  }
+
   jclass classAtkTable = (*env)->FindClass(env, "org/GNOME/Accessibility/AtkTable");
   jmethodID jmid = (*env)->GetMethodID(env, classAtkTable, "get_column_extent_at", "(II)I");
   jint jextent = (*env)->CallIntMethod(env, atk_table, jmid, (jint)row, (jint)column);
+  (*env)->DeleteGlobalRef(env, atk_table);
 
   return (gint)jextent;
 }
@@ -240,12 +264,16 @@ jaw_table_get_row_extent_at (AtkTable *table, gint row, gint column)
 {
   JawObject *jaw_obj = JAW_OBJECT(table);
   TableData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_TABLE);
-  jobject atk_table = data->atk_table;
-
   JNIEnv *env = jaw_util_get_jni_env();
+  jobject atk_table = (*env)->NewGlobalRef(env, data->atk_table);
+  if (!atk_table) {
+    return 0;
+  }
+
   jclass classAtkTable = (*env)->FindClass(env, "org/GNOME/Accessibility/AtkTable");
   jmethodID jmid = (*env)->GetMethodID(env, classAtkTable, "get_row_extent_at", "(II)I");
   jint jextent = (*env)->CallIntMethod(env, atk_table, jmid, (jint)row, (jint)column);
+  (*env)->DeleteGlobalRef(env, atk_table);
 
   return (gint)jextent;
 }
@@ -255,9 +283,12 @@ jaw_table_get_caption (AtkTable    *table)
 {
   JawObject *jaw_obj = JAW_OBJECT(table);
   TableData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_TABLE);
-  jobject atk_table = data->atk_table;
-
   JNIEnv *env = jaw_util_get_jni_env();
+  jobject atk_table = (*env)->NewGlobalRef(env, data->atk_table);
+  if (!atk_table) {
+    return NULL;
+  }
+
   jclass classAtkTable = (*env)->FindClass(env, "org/GNOME/Accessibility/AtkTable");
   jmethodID jmid = (*env)->GetMethodID(env,
                                        classAtkTable,
@@ -265,6 +296,7 @@ jaw_table_get_caption (AtkTable     *table)
                                        "()Ljavax/accessibility/AccessibleContext;");
 
   jobject jac = (*env)->CallObjectMethod(env, atk_table, jmid);
+  (*env)->DeleteGlobalRef(env, atk_table);
 
   if (!jac)
     return NULL;
@@ -279,12 +311,16 @@ jaw_table_get_column_description (AtkTable *table, gint   column)
 {
   JawObject *jaw_obj = JAW_OBJECT(table);
   TableData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_TABLE);
-  jobject atk_table = data->atk_table;
-
   JNIEnv *env = jaw_util_get_jni_env();
+  jobject atk_table = (*env)->NewGlobalRef(env, data->atk_table);
+  if (!atk_table) {
+    return NULL;
+  }
+
   jclass classAtkTable = (*env)->FindClass(env, "org/GNOME/Accessibility/AtkTable");
   jmethodID jmid = (*env)->GetMethodID(env, classAtkTable, "get_column_description", 
"(I)Ljava/lang/String;");
   jstring jstr = (*env)->CallObjectMethod(env, atk_table, jmid, (jint)column);
+  (*env)->DeleteGlobalRef(env, atk_table);
 
   if (data->description != NULL)
   {
@@ -303,12 +339,16 @@ jaw_table_get_row_description (AtkTable *table, gint row)
 {
   JawObject *jaw_obj = JAW_OBJECT(table);
   TableData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_TABLE);
-  jobject atk_table = data->atk_table;
-
   JNIEnv *env = jaw_util_get_jni_env();
+  jobject atk_table = (*env)->NewGlobalRef(env, data->atk_table);
+  if (!atk_table) {
+    return NULL;
+  }
+
   jclass classAtkTable = (*env)->FindClass(env, "org/GNOME/Accessibility/AtkTable");
   jmethodID jmid = (*env)->GetMethodID(env, classAtkTable, "get_row_description", "(I)Ljava/lang/String;");
   jstring jstr = (*env)->CallObjectMethod(env, atk_table, jmid, (jint)row);
+  (*env)->DeleteGlobalRef(env, atk_table);
 
   if (data->description != NULL)
   {
@@ -327,12 +367,16 @@ jaw_table_get_column_header (AtkTable *table, gint column)
 {
   JawObject *jaw_obj = JAW_OBJECT(table);
   TableData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_TABLE);
-  jobject atk_table = data->atk_table;
-
   JNIEnv *env = jaw_util_get_jni_env();
+  jobject atk_table = (*env)->NewGlobalRef(env, data->atk_table);
+  if (!atk_table) {
+    return NULL;
+  }
+
   jclass classAtkTable = (*env)->FindClass(env, "org/GNOME/Accessibility/AtkTable");
   jmethodID jmid = (*env)->GetMethodID(env, classAtkTable, "get_column_header", 
"(I)Ljavax/accessibility/AccessibleContext;");
   jobject jac = (*env)->CallObjectMethod(env, atk_table, jmid, (jint)column);
+  (*env)->DeleteGlobalRef(env, atk_table);
 
   if (!jac)
     return NULL;
@@ -347,12 +391,16 @@ jaw_table_get_row_header (AtkTable *table, gint row)
 {
   JawObject *jaw_obj = JAW_OBJECT(table);
   TableData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_TABLE);
-  jobject atk_table = data->atk_table;
-
   JNIEnv *env = jaw_util_get_jni_env();
+  jobject atk_table = (*env)->NewGlobalRef(env, data->atk_table);
+  if (!atk_table) {
+    return NULL;
+  }
+
   jclass classAtkTable = (*env)->FindClass(env, "org/GNOME/Accessibility/AtkTable");
   jmethodID jmid = (*env)->GetMethodID(env, classAtkTable, "get_row_header", 
"(I)Ljavax/accessibility/AccessibleContext;");
   jobject jac = (*env)->CallObjectMethod(env, atk_table, jmid, (jint)row);
+  (*env)->DeleteGlobalRef(env, atk_table);
 
   if (!jac)
     return NULL;
@@ -367,12 +415,16 @@ jaw_table_get_summary (AtkTable *table)
 {
   JawObject *jaw_obj = JAW_OBJECT(table);
   TableData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_TABLE);
-  jobject atk_table = data->atk_table;
-
   JNIEnv *env = jaw_util_get_jni_env();
+  jobject atk_table = (*env)->NewGlobalRef(env, data->atk_table);
+  if (!atk_table) {
+    return NULL;
+  }
+
   jclass classAtkTable = (*env)->FindClass(env, "org/GNOME/Accessibility/AtkTable");
   jmethodID jmid = (*env)->GetMethodID(env, classAtkTable, "get_summary", 
"()Ljavax/accessibility/AccessibleContext;");
   jobject jac = (*env)->CallObjectMethod(env, atk_table, jmid);
+  (*env)->DeleteGlobalRef(env, atk_table);
 
   if (!jac)
     return NULL;
@@ -387,12 +439,16 @@ jaw_table_get_selected_columns (AtkTable *table, gint **selected)
 {
   JawObject *jaw_obj = JAW_OBJECT(table);
   TableData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_TABLE);
-  jobject atk_table = data->atk_table;
-
   JNIEnv *env = jaw_util_get_jni_env();
+  jobject atk_table = (*env)->NewGlobalRef(env, data->atk_table);
+  if (!atk_table) {
+    return 0;
+  }
+
   jclass classAtkTable = (*env)->FindClass(env, "org/GNOME/Accessibility/AtkTable");
   jmethodID jmid = (*env)->GetMethodID(env, classAtkTable, "get_selected_columns", "()[I");
   jintArray jcolumnArray = (*env)->CallObjectMethod(env, atk_table, jmid);
+  (*env)->DeleteGlobalRef(env, atk_table);
 
   if (!jcolumnArray)
     return 0;
@@ -416,12 +472,16 @@ jaw_table_get_selected_rows (AtkTable *table, gint **selected)
 {
   JawObject *jaw_obj = JAW_OBJECT(table);
   TableData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_TABLE);
-  jobject atk_table = data->atk_table;
-
   JNIEnv *env = jaw_util_get_jni_env();
+  jobject atk_table = (*env)->NewGlobalRef(env, data->atk_table);
+  if (!atk_table) {
+    return 0;
+  }
+
   jclass classAtkTable = (*env)->FindClass(env, "org/GNOME/Accessibility/AtkTable");
   jmethodID jmid = (*env)->GetMethodID(env, classAtkTable, "get_selected_rows", "()[I");
   jintArray jrowArray = (*env)->CallObjectMethod(env, atk_table, jmid);
+  (*env)->DeleteGlobalRef(env, atk_table);
 
   if (!jrowArray)
     return 0;
@@ -445,12 +505,16 @@ jaw_table_is_column_selected (AtkTable *table, gint column)
 {
   JawObject *jaw_obj = JAW_OBJECT(table);
   TableData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_TABLE);
-  jobject atk_table = data->atk_table;
-
   JNIEnv *env = jaw_util_get_jni_env();
+  jobject atk_table = (*env)->NewGlobalRef(env, data->atk_table);
+  if (!atk_table) {
+    return FALSE;
+  }
+
   jclass classAtkTable = (*env)->FindClass(env, "org/GNOME/Accessibility/AtkTable");
   jmethodID jmid = (*env)->GetMethodID(env, classAtkTable, "is_column_selected", "(I)Z");
   jboolean jselected = (*env)->CallBooleanMethod(env, atk_table, jmid, (jint)column);
+  (*env)->DeleteGlobalRef(env, atk_table);
 
   if (jselected == JNI_TRUE)
     return TRUE;
@@ -463,12 +527,16 @@ jaw_table_is_row_selected (AtkTable *table, gint row)
 {
   JawObject *jaw_obj = JAW_OBJECT(table);
   TableData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_TABLE);
-  jobject atk_table = data->atk_table;
-
   JNIEnv *env = jaw_util_get_jni_env();
+  jobject atk_table = (*env)->NewGlobalRef(env, data->atk_table);
+  if (!atk_table) {
+    return FALSE;
+  }
+
   jclass classAtkTable = (*env)->FindClass(env, "org/GNOME/Accessibility/AtkTable");
   jmethodID jmid = (*env)->GetMethodID(env, classAtkTable, "is_row_selected", "(I)Z");
   jboolean jselected = (*env)->CallBooleanMethod(env, atk_table, jmid, (jint)row);
+  (*env)->DeleteGlobalRef(env, atk_table);
 
   if (jselected == JNI_TRUE)
     return TRUE;
@@ -481,12 +549,16 @@ jaw_table_is_selected (AtkTable *table, gint row, gint column)
 {
   JawObject *jaw_obj = JAW_OBJECT(table);
   TableData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_TABLE);
-  jobject atk_table = data->atk_table;
-
   JNIEnv *env = jaw_util_get_jni_env();
+  jobject atk_table = (*env)->NewGlobalRef(env, data->atk_table);
+  if (!atk_table) {
+    return FALSE;
+  }
+
   jclass classAtkTable = (*env)->FindClass(env, "org/GNOME/Accessibility/AtkTable");
   jmethodID jmid = (*env)->GetMethodID(env, classAtkTable, "is_selected", "(II)Z");
   jboolean jselected = (*env)->CallBooleanMethod(env, atk_table, jmid, (jint)row, (jint)column);
+  (*env)->DeleteGlobalRef(env, atk_table);
 
   if (jselected == JNI_TRUE)
     return TRUE;
@@ -499,12 +571,16 @@ jaw_table_add_row_selection(AtkTable *table, gint row)
 {
   JawObject *jaw_obj = JAW_OBJECT(table);
   TableData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_TABLE);
-  jobject atk_table = data->atk_table;
-
   JNIEnv *env = jaw_util_get_jni_env();
+  jobject atk_table = (*env)->NewGlobalRef(env, data->atk_table);
+  if (!atk_table) {
+    return FALSE;
+  }
+
   jclass classAtkTable = (*env)->FindClass(env, "org/GNOME/Accessibility/AtkTable");
   jmethodID jmid = (*env)->GetMethodID(env, classAtkTable, "addRowSelection", "(I)Z");
   jboolean jselected = (*env)->CallBooleanMethod(env, atk_table, jmid, (jint)row);
+  (*env)->DeleteGlobalRef(env, atk_table);
 
   if (jselected == JNI_TRUE)
     return TRUE;
@@ -517,12 +593,16 @@ jaw_table_add_column_selection(AtkTable *table, gint column)
 {
   JawObject *jaw_obj = JAW_OBJECT(table);
   TableData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_TABLE);
-  jobject atk_table = data->atk_table;
-
   JNIEnv *env = jaw_util_get_jni_env();
+  jobject atk_table = (*env)->NewGlobalRef(env, data->atk_table);
+  if (!atk_table) {
+    return FALSE;
+  }
+
   jclass classAtkTable = (*env)->FindClass(env, "org/GNOME/Accessibility/AtkTable");
   jmethodID jmid = (*env)->GetMethodID(env, classAtkTable, "addColumnSelection", "(I)Z");
   jboolean jselected = (*env)->CallBooleanMethod(env, atk_table, jmid, (jint)column);
+  (*env)->DeleteGlobalRef(env, atk_table);
 
   if (jselected == JNI_TRUE)
     return TRUE;
@@ -535,9 +615,12 @@ jaw_table_set_row_description(AtkTable *table, gint row, const gchar *descriptio
 {
   JawObject *jaw_obj = JAW_OBJECT(table);
   TableData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_TABLE);
-  jobject atk_table = data->atk_table;
-
   JNIEnv *env = jaw_util_get_jni_env();
+  jobject atk_table = (*env)->NewGlobalRef(env, data->atk_table);
+  if (!atk_table) {
+    return;
+  }
+
   jclass classAtkTable = (*env)->FindClass(env, "org/GNOME/Accessibility/AtkTable");
   jmethodID jmid = (*env)->GetMethodID(env,
                                        classAtkTable,
@@ -545,6 +628,7 @@ jaw_table_set_row_description(AtkTable *table, gint row, const gchar *descriptio
                                        "(ILjava/lang/String;)V");
   jstring jstr = (*env)->NewStringUTF(env, description);
   (*env)->CallVoidMethod(env, atk_table, jmid, (jint)row, jstr);
+  (*env)->DeleteGlobalRef(env, atk_table);
 }
 
 static void
@@ -552,9 +636,12 @@ jaw_table_set_column_description(AtkTable *table, gint column, const gchar *desc
 {
   JawObject *jaw_obj = JAW_OBJECT(table);
   TableData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_TABLE);
-  jobject atk_table = data->atk_table;
-
   JNIEnv *env = jaw_util_get_jni_env();
+  jobject atk_table = (*env)->NewGlobalRef(env, data->atk_table);
+  if (!atk_table) {
+    return;
+  }
+
   jclass classAtkTable = (*env)->FindClass(env, "org/GNOME/Accessibility/AtkTable");
   jmethodID jmid = (*env)->GetMethodID(env,
                                        classAtkTable,
@@ -562,6 +649,7 @@ jaw_table_set_column_description(AtkTable *table, gint column, const gchar *desc
                                        "(ILjava/lang/String;)V");
   jstring jstr = (*env)->NewStringUTF(env, description);
   (*env)->CallVoidMethod(env, atk_table, jmid, (jint)column, jstr);
+  (*env)->DeleteGlobalRef(env, atk_table);
 }
 
 static void
@@ -569,15 +657,19 @@ jaw_table_set_row_header(AtkTable *table, gint row, AtkObject *header)
 {
   JawObject *jaw_obj = JAW_OBJECT(table);
   TableData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_TABLE);
-  jobject atk_table = data->atk_table;
-
   JNIEnv *env = jaw_util_get_jni_env();
+  jobject atk_table = (*env)->NewGlobalRef(env, data->atk_table);
+  if (!atk_table) {
+    return;
+  }
+
   jclass classAtkTable = (*env)->FindClass(env, "org/GNOME/Accessibility/AtkTable");
   jmethodID jmid = (*env)->GetMethodID(env,
                                        classAtkTable,
                                        "setRowHeader",
                                        "(ILjavax/accessibility/AccessibleTable;)V");
   (*env)->CallVoidMethod(env, atk_table, jmid, (jint)row, (jobject)header);
+  (*env)->DeleteGlobalRef(env, atk_table);
 }
 
 static void
@@ -585,15 +677,19 @@ jaw_table_set_column_header(AtkTable *table, gint column, AtkObject *header)
 {
   JawObject *jaw_obj = JAW_OBJECT(table);
   TableData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_TABLE);
-  jobject atk_table = data->atk_table;
-
   JNIEnv *env = jaw_util_get_jni_env();
+  jobject atk_table = (*env)->NewGlobalRef(env, data->atk_table);
+  if (!atk_table) {
+    return;
+  }
+
   jclass classAtkTable = (*env)->FindClass(env, "org/GNOME/Accessibility/AtkTable");
   jmethodID jmid = (*env)->GetMethodID(env,
                                        classAtkTable,
                                        "setColumnHeader",
                                        "(ILjavax/accessibility/AccessibleTable;)V");
   (*env)->CallVoidMethod(env, atk_table, jmid, (jint)column, (jobject)header);
+  (*env)->DeleteGlobalRef(env, atk_table);
 }
 
 static void
@@ -601,15 +697,19 @@ jaw_table_set_caption(AtkTable *table, AtkObject *caption)
 {
   JawObject *jaw_obj = JAW_OBJECT(table);
   TableData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_TABLE);
-  jobject atk_table = data->atk_table;
-
   JNIEnv *env = jaw_util_get_jni_env();
+  jobject atk_table = (*env)->NewGlobalRef(env, data->atk_table);
+  if (!atk_table) {
+    return;
+  }
+
   jclass classAtkTable = (*env)->FindClass(env, "org/GNOME/Accessibility/AtkTable");
   jmethodID jmid = (*env)->GetMethodID(env,
                                        classAtkTable,
                                        "setCaption",
                                        "(Ljavax/accessibility/Accessible;)V");
   (*env)->CallVoidMethod(env, atk_table, jmid, (jobject)caption);
+  (*env)->DeleteGlobalRef(env, atk_table);
 }
 
 static void
@@ -617,13 +717,17 @@ jaw_table_set_summary(AtkTable *table, AtkObject *summary)
 {
   JawObject *jaw_obj = JAW_OBJECT(table);
   TableData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_TABLE);
-  jobject atk_table = data->atk_table;
-
   JNIEnv *env = jaw_util_get_jni_env();
+  jobject atk_table = (*env)->NewGlobalRef(env, data->atk_table);
+  if (!atk_table) {
+    return;
+  }
+
   jclass classAtkTable = (*env)->FindClass(env, "org/GNOME/Accessibility/AtkTable");
   jmethodID jmid = (*env)->GetMethodID(env,
                                        classAtkTable,
                                        "setSummary",
                                        "(Ljavax/accessibility/Accessible;)V");
   (*env)->CallVoidMethod(env, atk_table, jmid, (jobject)summary);
+  (*env)->DeleteGlobalRef(env, atk_table);
 }
diff --git a/jni/src/jawtablecell.c b/jni/src/jawtablecell.c
index 1133112..db67e4d 100644
--- a/jni/src/jawtablecell.c
+++ b/jni/src/jawtablecell.c
@@ -61,7 +61,7 @@ jaw_table_cell_data_init (jobject ac)
   jclass classTableCell = (*jniEnv)->FindClass(jniEnv, "org/GNOME/Accessibility/AtkTableCell");
   jmethodID jmid = (*jniEnv)->GetMethodID(jniEnv, classTableCell, "<init>", 
"(Ljavax/accessibility/AccessibleContext;)V");
   jobject jatk_table_cell = (*jniEnv)->NewObject(jniEnv, classTableCell, jmid, ac);
-  data->atk_table_cell = (*jniEnv)->NewGlobalRef(jniEnv, jatk_table_cell);
+  data->atk_table_cell = (*jniEnv)->NewWeakGlobalRef(jniEnv, jatk_table_cell);
 
   return data;
 }
@@ -82,7 +82,7 @@ jaw_table_cell_data_finalize (gpointer p)
       data->description = NULL;
     }
 
-    (*jniEnv)->DeleteGlobalRef(jniEnv, data->atk_table_cell);
+    (*jniEnv)->DeleteWeakGlobalRef(jniEnv, data->atk_table_cell);
     data->atk_table_cell = NULL;
   }
 }
@@ -92,9 +92,12 @@ jaw_table_cell_get_table(AtkTableCell *cell)
 {
   JawObject *jaw_obj = JAW_OBJECT(cell);
   TableCellData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_TABLE_CELL);
-  jobject jatk_table_cell = data->atk_table_cell;
-
   JNIEnv *jniEnv = jaw_util_get_jni_env();
+  jobject jatk_table_cell = (*jniEnv)->NewGlobalRef(jniEnv, data->atk_table_cell);
+  if (!jatk_table_cell) {
+    return NULL;
+  }
+
   jclass classAtkTableCell = (*jniEnv)->FindClass(jniEnv,
                                                   "org/GNOME/Accessibility/AtkTableCell");
   jmethodID jmid = (*jniEnv)->GetMethodID(jniEnv,
@@ -102,6 +105,7 @@ jaw_table_cell_get_table(AtkTableCell *cell)
                                           "getTable",
                                           "()Ljavax/accessibility/AccessibleTable;");
   jobject jac = (*jniEnv)->CallObjectMethod(jniEnv, jatk_table_cell, jmid);
+  (*jniEnv)->DeleteGlobalRef(jniEnv, jatk_table_cell);
 
   if (!jac)
     return NULL;
@@ -116,9 +120,12 @@ jaw_table_cell_get_position(AtkTableCell *cell, gint *row, gint *column)
 {
   JawObject *jaw_obj = JAW_OBJECT(cell);
   TableCellData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_TABLE_CELL);
-  jobject jatk_table_cell = data->atk_table_cell;
-
   JNIEnv *jniEnv = jaw_util_get_jni_env();
+  jobject jatk_table_cell = (*jniEnv)->NewGlobalRef(jniEnv, data->atk_table_cell);
+  if (!jatk_table_cell) {
+    return FALSE;
+  }
+
   jclass classAtkTableCell = (*jniEnv)->FindClass(jniEnv,
                                                   "org/GNOME/Accessibility/AtkTableCell");
   jmethodID jmid = (*jniEnv)->GetMethodID(jniEnv,
@@ -130,6 +137,7 @@ jaw_table_cell_get_position(AtkTableCell *cell, gint *row, gint *column)
                                                    jmid,
                                                    (jint)GPOINTER_TO_INT(row),
                                                    (jint)GPOINTER_TO_INT(column));
+  (*jniEnv)->DeleteGlobalRef(jniEnv, jatk_table_cell);
 
   if (jposition == JNI_TRUE)
     return TRUE;
@@ -145,9 +153,12 @@ static gboolean jaw_table_cell_get_row_column_span(AtkTableCell *cell,
 {
   JawObject *jaw_obj = JAW_OBJECT(cell);
   TableCellData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_TABLE_CELL);
-  jobject jatk_table_cell = data->atk_table_cell;
-
   JNIEnv *jniEnv = jaw_util_get_jni_env();
+  jobject jatk_table_cell = (*jniEnv)->NewGlobalRef(jniEnv, data->atk_table_cell);
+  if (!jatk_table_cell) {
+    return FALSE;
+  }
+
   jclass classAtkTableCell = (*jniEnv)->FindClass(jniEnv,
                                                   "org/GNOME/Accessibility/AtkTableCell");
   jmethodID jmid = (*jniEnv)->GetMethodID(jniEnv,
@@ -162,6 +173,7 @@ static gboolean jaw_table_cell_get_row_column_span(AtkTableCell *cell,
                                                 (jint)GPOINTER_TO_INT(row_span),
                                                 (jint)GPOINTER_TO_INT(column_span)
                                                 );
+  (*jniEnv)->DeleteGlobalRef(jniEnv, jatk_table_cell);
   if (jspan == JNI_TRUE)
     return TRUE;
 
@@ -173,16 +185,21 @@ jaw_table_cell_get_row_span(AtkTableCell *cell)
 {
   JawObject *jaw_obj = JAW_OBJECT(cell);
   TableCellData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_TABLE_CELL);
-  jobject jatk_table_cell = data->atk_table_cell;
-
   JNIEnv *env = jaw_util_get_jni_env();
+  jobject jatk_table_cell = (*env)->NewGlobalRef(env, data->atk_table_cell);
+  if (!jatk_table_cell) {
+    return 0;
+  }
+
   jclass classAtkTableCell = (*env)->FindClass(env,
                                                "org/GNOME/Accessibility/AtkTableCell");
   jmethodID jmid = (*env)->GetMethodID(env,
                                        classAtkTableCell,
                                        "getRowSpan",
                                        "()I;");
-  return (gint) (*env)->CallIntMethod(env, jatk_table_cell, jmid);
+  gint ret = (gint) (*env)->CallIntMethod(env, jatk_table_cell, jmid);
+  (*env)->DeleteGlobalRef(env, jatk_table_cell);
+  return ret;
 }
 
 static gint
@@ -190,15 +207,20 @@ jaw_table_cell_get_column_span(AtkTableCell *cell)
 {
   JawObject *jaw_obj = JAW_OBJECT(cell);
   TableCellData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_TABLE_CELL);
-  jobject jatk_table_cell = data->atk_table_cell;
-
   JNIEnv *env = jaw_util_get_jni_env();
+  jobject jatk_table_cell = (*env)->NewGlobalRef(env, data->atk_table_cell);
+  if (!jatk_table_cell) {
+    return 0;
+  }
+
   jclass classAtkTableCell = (*env)->FindClass(env,
                                                "org/GNOME/Accessibility/AtkTableCell");
   jmethodID jmid = (*env)->GetMethodID(env,
                                        classAtkTableCell,
                                        "getColumnSpan",
                                        "()I;");
-  return (gint) (*env)->CallIntMethod(env, jatk_table_cell, jmid);
+  gint ret = (gint) (*env)->CallIntMethod(env, jatk_table_cell, jmid);
+  (*env)->DeleteGlobalRef(env, jatk_table_cell);
+  return ret;
 }
 
diff --git a/jni/src/jawtext.c b/jni/src/jawtext.c
index c4fe5b8..d7d4c25 100644
--- a/jni/src/jawtext.c
+++ b/jni/src/jawtext.c
@@ -118,7 +118,7 @@ jaw_text_data_init (jobject ac)
                                           "<init>",
                                           "(Ljavax/accessibility/AccessibleContext;)V");
   jobject jatk_text = (*jniEnv)->NewObject(jniEnv, classText, jmid, ac);
-  data->atk_text = (*jniEnv)->NewGlobalRef(jniEnv, jatk_text);
+  data->atk_text = (*jniEnv)->NewWeakGlobalRef(jniEnv, jatk_text);
 
   return data;
 }
@@ -139,7 +139,7 @@ jaw_text_data_finalize (gpointer p)
       data->text = NULL;
     }
 
-    (*jniEnv)->DeleteGlobalRef(jniEnv, data->atk_text);
+    (*jniEnv)->DeleteWeakGlobalRef(jniEnv, data->atk_text);
     data->atk_text = NULL;
   }
 }
@@ -164,9 +164,12 @@ jaw_text_get_text (AtkText *text, gint start_offset, gint end_offset)
 {
   JawObject *jaw_obj = JAW_OBJECT(text);
   TextData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_TEXT);
-  jobject atk_text = data->atk_text;
-
   JNIEnv *jniEnv = jaw_util_get_jni_env();
+  jobject atk_text = (*jniEnv)->NewGlobalRef(jniEnv, data->atk_text);
+  if (!atk_text) {
+    return NULL;
+  }
+
   jclass classAtkText = (*jniEnv)->FindClass(jniEnv,
                                              "org/GNOME/Accessibility/AtkText");
   jmethodID jmid = (*jniEnv)->GetMethodID(jniEnv,
@@ -179,6 +182,7 @@ jaw_text_get_text (AtkText *text, gint start_offset, gint end_offset)
                                              jmid,
                                              (jint)start_offset,
                                              (jint)end_offset );
+  (*jniEnv)->DeleteGlobalRef(jniEnv, atk_text);
 
   return jaw_text_get_gtext_from_jstr(jniEnv, data, jstr);
 }
@@ -188,9 +192,12 @@ jaw_text_get_character_at_offset (AtkText *text, gint offset)
 {
   JawObject *jaw_obj = JAW_OBJECT(text);
   TextData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_TEXT);
-  jobject atk_text = data->atk_text;
-
   JNIEnv *jniEnv = jaw_util_get_jni_env();
+  jobject atk_text = (*jniEnv)->NewGlobalRef(jniEnv, data->atk_text);
+  if (!atk_text) {
+    return 0;
+  }
+
   jclass classAtkText = (*jniEnv)->FindClass(jniEnv,
                                              "org/GNOME/Accessibility/AtkText");
   jmethodID jmid = (*jniEnv)->GetMethodID(jniEnv,
@@ -200,6 +207,7 @@ jaw_text_get_character_at_offset (AtkText *text, gint offset)
                                                atk_text,
                                                jmid,
                                                (jint)offset );
+  (*jniEnv)->DeleteGlobalRef(jniEnv, atk_text);
 
   return (gunichar)jcharacter;
 }
@@ -212,9 +220,12 @@ jaw_text_get_text_at_offset (AtkText *text,
 {
   JawObject *jaw_obj = JAW_OBJECT(text);
   TextData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_TEXT);
-  jobject atk_text = data->atk_text;
-
   JNIEnv *jniEnv = jaw_util_get_jni_env();
+  jobject atk_text = (*jniEnv)->NewGlobalRef(jniEnv, data->atk_text);
+  if (!atk_text) {
+    return NULL;
+  }
+
   jclass classAtkText = (*jniEnv)->FindClass(jniEnv,
                                              "org/GNOME/Accessibility/AtkText");
   jmethodID jmid = (*jniEnv)->GetMethodID(jniEnv,
@@ -226,6 +237,7 @@ jaw_text_get_text_at_offset (AtkText *text,
                                                 jmid,
                                                 (jint)offset,
                                                 (jint)boundary_type );
+  (*jniEnv)->DeleteGlobalRef(jniEnv, atk_text);
 
   if (jStrSeq == NULL)
   {
@@ -262,9 +274,12 @@ jaw_text_get_caret_offset (AtkText *text)
 {
   JawObject *jaw_obj = JAW_OBJECT(text);
   TextData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_TEXT);
-  jobject atk_text = data->atk_text;
-
   JNIEnv *jniEnv = jaw_util_get_jni_env();
+  jobject atk_text = (*jniEnv)->NewGlobalRef(jniEnv, data->atk_text);
+  if (!atk_text) {
+    return 0;
+  }
+
   jclass classAtkText = (*jniEnv)->FindClass(jniEnv,
                                              "org/GNOME/Accessibility/AtkText");
   jmethodID jmid = (*jniEnv)->GetMethodID(jniEnv,
@@ -272,6 +287,7 @@ jaw_text_get_caret_offset (AtkText *text)
                                           "get_caret_offset",
                                           "()I");
   jint joffset = (*jniEnv)->CallIntMethod(jniEnv, atk_text, jmid);
+  (*jniEnv)->DeleteGlobalRef(jniEnv, atk_text);
 
   return (gint)joffset;
 }
@@ -284,9 +300,12 @@ jaw_text_get_character_extents (AtkText *text,
 {
   JawObject *jaw_obj = JAW_OBJECT(text);
   TextData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_TEXT);
-  jobject atk_text = data->atk_text;
-
   JNIEnv *jniEnv = jaw_util_get_jni_env();
+  jobject atk_text = (*jniEnv)->NewGlobalRef(jniEnv, data->atk_text);
+  if (!atk_text) {
+    return;
+  }
+
   jclass classAtkText = (*jniEnv)->FindClass(jniEnv,
                                              "org/GNOME/Accessibility/AtkText");
   jmethodID jmid = (*jniEnv)->GetMethodID(jniEnv,
@@ -298,6 +317,7 @@ jaw_text_get_character_extents (AtkText *text,
                                               jmid,
                                               (jint)offset,
                                               (jint)coords);
+  (*jniEnv)->DeleteGlobalRef(jniEnv, atk_text);
 
   if (jrect == NULL)
   {
@@ -312,9 +332,12 @@ jaw_text_get_character_count (AtkText *text)
 {
   JawObject *jaw_obj = JAW_OBJECT(text);
   TextData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_TEXT);
-  jobject atk_text = data->atk_text;
-
   JNIEnv *jniEnv = jaw_util_get_jni_env();
+  jobject atk_text = (*jniEnv)->NewGlobalRef(jniEnv, data->atk_text);
+  if (!atk_text) {
+    return 0;
+  }
+
   jclass classAtkText = (*jniEnv)->FindClass(jniEnv,
                                              "org/GNOME/Accessibility/AtkText");
   jmethodID jmid = (*jniEnv)->GetMethodID(jniEnv,
@@ -322,6 +345,7 @@ jaw_text_get_character_count (AtkText *text)
                                           "get_character_count",
                                           "()I");
   jint jcount = (*jniEnv)->CallIntMethod(jniEnv, atk_text, jmid);
+  (*jniEnv)->DeleteGlobalRef(jniEnv, atk_text);
 
   return (gint)jcount;
 }
@@ -331,9 +355,12 @@ jaw_text_get_offset_at_point (AtkText *text, gint x, gint y, AtkCoordType coords
 {
   JawObject *jaw_obj = JAW_OBJECT(text);
   TextData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_TEXT);
-  jobject atk_text = data->atk_text;
-
   JNIEnv *jniEnv = jaw_util_get_jni_env();
+  jobject atk_text = (*jniEnv)->NewGlobalRef(jniEnv, data->atk_text);
+  if (!atk_text) {
+    return 0;
+  }
+
   jclass classAtkText = (*jniEnv)->FindClass(jniEnv, "org/GNOME/Accessibility/AtkText");
   jmethodID jmid = (*jniEnv)->GetMethodID(jniEnv,
                                           classAtkText,
@@ -345,6 +372,7 @@ jaw_text_get_offset_at_point (AtkText *text, gint x, gint y, AtkCoordType coords
                                           (jint)x,
                                           (jint)y,
                                           (jint)coords);
+  (*jniEnv)->DeleteGlobalRef(jniEnv, atk_text);
 
   return (gint)joffset;
 }
@@ -363,9 +391,12 @@ jaw_text_get_range_extents (AtkText *text,
 
   JawObject *jaw_obj = JAW_OBJECT(text);
   TextData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_TEXT);
-  jobject atk_text = data->atk_text;
-
   JNIEnv *jniEnv = jaw_util_get_jni_env();
+  jobject atk_text = (*jniEnv)->NewGlobalRef(jniEnv, data->atk_text);
+  if (!atk_text) {
+    return;
+  }
+
   jclass classAtkText = (*jniEnv)->FindClass(jniEnv,
                                              "org/GNOME/Accessibility/AtkText");
   jmethodID jmid = (*jniEnv)->GetMethodID(jniEnv,
@@ -378,6 +409,7 @@ jaw_text_get_range_extents (AtkText *text,
                                               (jint)start_offset,
                                               (jint)end_offset,
                                               (jint)coord_type);
+  (*jniEnv)->DeleteGlobalRef(jniEnv, atk_text);
 
   if (!jrect)
   {
@@ -392,9 +424,12 @@ jaw_text_get_n_selections (AtkText *text)
 {
   JawObject *jaw_obj = JAW_OBJECT(text);
   TextData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_TEXT);
-  jobject atk_text = data->atk_text;
-
   JNIEnv *jniEnv = jaw_util_get_jni_env();
+  jobject atk_text = (*jniEnv)->NewGlobalRef(jniEnv, data->atk_text);
+  if (!atk_text) {
+    return 0;
+  }
+
   jclass classAtkText = (*jniEnv)->FindClass(jniEnv,
                                              "org/GNOME/Accessibility/AtkText");
   jmethodID jmid = (*jniEnv)->GetMethodID(jniEnv,
@@ -402,6 +437,7 @@ jaw_text_get_n_selections (AtkText *text)
                                           "get_n_selections",
                                           "()I");
   jint jselections = (*jniEnv)->CallIntMethod(jniEnv, atk_text, jmid);
+  (*jniEnv)->DeleteGlobalRef(jniEnv, atk_text);
 
   return (gint)jselections;
 }
@@ -411,15 +447,19 @@ jaw_text_get_selection (AtkText *text, gint selection_num, gint *start_offset, g
 {
   JawObject *jaw_obj = JAW_OBJECT(text);
   TextData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_TEXT);
-  jobject atk_text = data->atk_text;
-
   JNIEnv *jniEnv = jaw_util_get_jni_env();
+  jobject atk_text = (*jniEnv)->NewGlobalRef(jniEnv, data->atk_text);
+  if (!atk_text) {
+    return NULL;
+  }
+
   jclass classAtkText = (*jniEnv)->FindClass(jniEnv, "org/GNOME/Accessibility/AtkText");
   jmethodID jmid = (*jniEnv)->GetMethodID(jniEnv,
                                           classAtkText,
                                           "get_selection",
                                           "()Lorg/GNOME/Accessibility/AtkText$StringSequence;");
   jobject jStrSeq = (*jniEnv)->CallObjectMethod(jniEnv, atk_text, jmid);
+  (*jniEnv)->DeleteGlobalRef(jniEnv, atk_text);
 
   if (jStrSeq == NULL)
   {
@@ -453,9 +493,12 @@ jaw_text_add_selection (AtkText *text, gint start_offset, gint end_offset)
 {
   JawObject *jaw_obj = JAW_OBJECT(text);
   TextData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_TEXT);
-  jobject atk_text = data->atk_text;
-
   JNIEnv *jniEnv = jaw_util_get_jni_env();
+  jobject atk_text = (*jniEnv)->NewGlobalRef(jniEnv, data->atk_text);
+  if (!atk_text) {
+    return FALSE;
+  }
+
   jclass classAtkText = (*jniEnv)->FindClass(jniEnv, "org/GNOME/Accessibility/AtkText");
   jmethodID jmid = (*jniEnv)->GetMethodID(jniEnv,
                                          classAtkText,
@@ -466,6 +509,7 @@ jaw_text_add_selection (AtkText *text, gint start_offset, gint end_offset)
                                                   jmid,
                                                   (jint)start_offset,
                                                   (jint)end_offset);
+  (*jniEnv)->DeleteGlobalRef(jniEnv, atk_text);
 
   if (jresult == JNI_TRUE)
   {
@@ -480,9 +524,12 @@ jaw_text_remove_selection (AtkText *text, gint selection_num)
 {
   JawObject *jaw_obj = JAW_OBJECT(text);
   TextData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_TEXT);
-  jobject atk_text = data->atk_text;
-
   JNIEnv *jniEnv = jaw_util_get_jni_env();
+  jobject atk_text = (*jniEnv)->NewGlobalRef(jniEnv, data->atk_text);
+  if (!atk_text) {
+    return FALSE;
+  }
+
   jclass classAtkText = (*jniEnv)->FindClass(jniEnv,
                                              "org/GNOME/Accessibility/AtkText");
   jmethodID jmid = (*jniEnv)->GetMethodID(jniEnv,
@@ -493,6 +540,7 @@ jaw_text_remove_selection (AtkText *text, gint selection_num)
                                                   atk_text,
                                                   jmid,
                                                   (jint)selection_num);
+  (*jniEnv)->DeleteGlobalRef(jniEnv, atk_text);
 
   if (jresult == JNI_TRUE)
   {
@@ -507,9 +555,12 @@ jaw_text_set_selection (AtkText *text, gint selection_num, gint start_offset, gi
 {
   JawObject *jaw_obj = JAW_OBJECT(text);
   TextData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_TEXT);
-  jobject atk_text = data->atk_text;
-
   JNIEnv *jniEnv = jaw_util_get_jni_env();
+  jobject atk_text = (*jniEnv)->NewGlobalRef(jniEnv, data->atk_text);
+  if (!atk_text) {
+    return FALSE;
+  }
+
   jclass classAtkText = (*jniEnv)->FindClass(jniEnv, "org/GNOME/Accessibility/AtkText");
   jmethodID jmid = (*jniEnv)->GetMethodID(jniEnv, classAtkText, "set_selection", "(III)Z");
   jboolean jresult = (*jniEnv)->CallBooleanMethod(jniEnv,
@@ -518,6 +569,7 @@ jaw_text_set_selection (AtkText *text, gint selection_num, gint start_offset, gi
                                                   (jint)selection_num,
                                                   (jint)start_offset,
                                                   (jint)end_offset);
+  (*jniEnv)->DeleteGlobalRef(jniEnv, atk_text);
 
   if (jresult == JNI_TRUE) {
     return TRUE;
@@ -531,9 +583,12 @@ jaw_text_set_caret_offset (AtkText *text, gint offset)
 {
   JawObject *jaw_obj = JAW_OBJECT(text);
   TextData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_TEXT);
-  jobject atk_text = data->atk_text;
-
   JNIEnv *jniEnv = jaw_util_get_jni_env();
+  jobject atk_text = (*jniEnv)->NewGlobalRef(jniEnv, data->atk_text);
+  if (!atk_text) {
+    return FALSE;
+  }
+
   jclass classAtkText = (*jniEnv)->FindClass(jniEnv,
                                              "org/GNOME/Accessibility/AtkText");
   jmethodID jmid = (*jniEnv)->GetMethodID(jniEnv,
@@ -544,6 +599,7 @@ jaw_text_set_caret_offset (AtkText *text, gint offset)
                                                   atk_text,
                                                   jmid,
                                                   (jint)offset);
+  (*jniEnv)->DeleteGlobalRef(jniEnv, atk_text);
 
   if (jresult == JNI_TRUE)
   {
diff --git a/jni/src/jawvalue.c b/jni/src/jawvalue.c
index b8f3ac2..ef36a6d 100644
--- a/jni/src/jawvalue.c
+++ b/jni/src/jawvalue.c
@@ -62,7 +62,7 @@ jaw_value_data_init (jobject ac)
                                           "<init>",
                                           "(Ljavax/accessibility/AccessibleContext;)V");
   jobject jatk_value = (*jniEnv)->NewObject(jniEnv, classValue, jmid, ac);
-  data->atk_value = (*jniEnv)->NewGlobalRef(jniEnv, jatk_value);
+  data->atk_value = (*jniEnv)->NewWeakGlobalRef(jniEnv, jatk_value);
 
   return data;
 }
@@ -75,7 +75,7 @@ jaw_value_data_finalize (gpointer p)
 
   if (data && data->atk_value)
   {
-    (*jniEnv)->DeleteGlobalRef(jniEnv, data->atk_value);
+    (*jniEnv)->DeleteWeakGlobalRef(jniEnv, data->atk_value);
     data->atk_value = NULL;
   }
 }
@@ -153,9 +153,12 @@ jaw_value_get_current_value (AtkValue *obj, GValue *value)
 
   JawObject *jaw_obj = JAW_OBJECT(obj);
   ValueData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_VALUE);
-  jobject atk_value = data->atk_value;
-
   JNIEnv *jniEnv = jaw_util_get_jni_env();
+  jobject atk_value = (*jniEnv)->NewGlobalRef(jniEnv, data->atk_value);
+  if (!atk_value) {
+    return;
+  }
+
   jclass classAtkValue = (*jniEnv)->FindClass(jniEnv,
                                               "org/GNOME/Accessibility/AtkValue");
   jmethodID jmid = (*jniEnv)->GetMethodID(jniEnv,
@@ -165,6 +168,7 @@ jaw_value_get_current_value (AtkValue *obj, GValue *value)
   jobject jnumber = (*jniEnv)->CallObjectMethod(jniEnv,
                                                 atk_value,
                                                 jmid);
+  (*jniEnv)->DeleteGlobalRef(jniEnv, atk_value);
 
   if (!jnumber)
   {
@@ -182,15 +186,19 @@ jaw_value_set_value(AtkValue *obj, const gdouble value)
 
   JawObject *jaw_obj = JAW_OBJECT(obj);
   ValueData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_VALUE);
-  jobject atk_value = data->atk_value;
-
   JNIEnv *env = jaw_util_get_jni_env();
+  jobject atk_value = (*env)->NewGlobalRef(env, data->atk_value);
+  if (!atk_value) {
+    return;
+  }
+
   jclass classAtkValue = (*env)->FindClass(env, "org/GNOME/Accessibility/AtkValue");
   jmethodID jmid = (*env)->GetMethodID(env,
                                        classAtkValue,
                                           "setValue",
                                           "(Ljava/lang/Number;)V");
   (*env)->CallVoidMethod(env, atk_value, jmid,(jdouble)value);
+  (*env)->DeleteGlobalRef(env, atk_value);
 }
 
 static AtkRange*
@@ -199,15 +207,20 @@ jaw_value_get_range(AtkValue *obj)
 
   JawObject *jaw_obj = JAW_OBJECT(obj);
   ValueData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_VALUE);
-  jobject atk_value = data->atk_value;
-
   JNIEnv *env = jaw_util_get_jni_env();
+  jobject atk_value = (*env)->NewGlobalRef(env, data->atk_value);
+  if (!atk_value) {
+    return NULL;
+  }
+
   jclass classAtkValue = (*env)->FindClass(env, "org/GNOME/Accessibility/AtkValue");
   jmethodID jmidMin = (*env)->GetMethodID(env, classAtkValue, "getMinimumValue", "()D");
   jmethodID jmidMax = (*env)->GetMethodID(env, classAtkValue, "getMaximumValue", "()D");
-  return atk_range_new((gdouble)(*env)->CallDoubleMethod(env, atk_value, jmidMin),
+  AtkRange *ret = atk_range_new((gdouble)(*env)->CallDoubleMethod(env, atk_value, jmidMin),
                        (gdouble)(*env)->CallDoubleMethod(env, atk_value, jmidMax),
                        NULL); // NULL description
+  (*env)->DeleteGlobalRef(env, atk_value);
+  return ret;
 }
 
 static gdouble
@@ -215,11 +228,16 @@ jaw_value_get_increment (AtkValue *obj)
 {
   JawObject *jaw_obj = JAW_OBJECT(obj);
   ValueData *data = jaw_object_get_interface_data(jaw_obj, INTERFACE_VALUE);
-  jobject atk_value = data->atk_value;
   JNIEnv *env = jaw_util_get_jni_env();
+  jobject atk_value = (*env)->NewGlobalRef(env, data->atk_value);
+  if (!atk_value) {
+    return 0.;
+  }
   jclass classAtkValue = (*env)->FindClass(env, "org/GNOME/Accessibility/AtkValue");
   jmethodID jmid = (*env)->GetMethodID(env, classAtkValue, "getIncrement", "()D");
-  return (*env)->CallDoubleMethod(env, atk_value, jmid);
+  gdouble ret = (*env)->CallDoubleMethod(env, atk_value, jmid);
+  (*env)->DeleteGlobalRef(env, atk_value);
+  return ret;
 }
 
 #ifdef __cplusplus
diff --git a/wrapper/module-info.java b/wrapper/module-info.java
index 9e2d1e1..9249b08 100644
--- a/wrapper/module-info.java
+++ b/wrapper/module-info.java
@@ -1,6 +1,7 @@
 module atk.wrapper {
     exports org.GNOME.Accessibility;
     requires java.desktop;
+    requires java.management;
     provides javax.accessibility.AccessibilityProvider
         with org.GNOME.Accessibility.AtkProvider;
 }
diff --git a/wrapper/org/GNOME/Accessibility/AtkWrapper.java.in 
b/wrapper/org/GNOME/Accessibility/AtkWrapper.java.in
index 9977446..be02e4a 100644
--- a/wrapper/org/GNOME/Accessibility/AtkWrapper.java.in
+++ b/wrapper/org/GNOME/Accessibility/AtkWrapper.java.in
@@ -26,6 +26,9 @@ import java.beans.*;
 import java.io.*;
 import javax.accessibility.*;
 import java.awt.Toolkit;
+import javax.management.*;
+import java.util.*;
+import java.lang.management.*;
 
 public class AtkWrapper {
   static boolean accessibilityEnabled = false;
@@ -42,6 +45,17 @@ public class AtkWrapper {
           break;
         }
       }
+
+      java.util.List<GarbageCollectorMXBean> gcbeans = ManagementFactory.getGarbageCollectorMXBeans();
+      for (GarbageCollectorMXBean gcbean : gcbeans) {
+       NotificationEmitter emitter = (NotificationEmitter) gcbean;
+       NotificationListener listener = new NotificationListener() {
+         public void handleNotification(Notification notif, Object handback) {
+           AtkWrapper.GC();
+         }
+       };
+       emitter.addNotificationListener(listener, null, null);
+      }
     } catch (Exception e) {
       e.printStackTrace();
       e.getCause();
@@ -634,6 +648,7 @@ public class AtkWrapper {
 
   public native static boolean initNativeLibrary();
   public native static void loadAtkBridge();
+  public native static void GC();
 
   public native static void focusNotify(javax.accessibility.AccessibleContext ac);
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]