Greetings,

Currently SVNBase class uses a member variable jthis to hold a copy of
jobject
reference. This variable lives as long as SVNClient object lives, however,
the
reference itself is only valid during a single JNI call.  To address this
mismatch
the attached patch passes the jobject reference as a parameter instead.
This
eliminates the risk of the jobject reference being misused outside the
scope
where it is valid.  This mismatch becomes more evident on JavaHL
RA editor API is implemented where objects like directories live across
method
calls.

[[[
JavaHL: Explicitly pass jobject jthis when processing dispose() call rather
 than stashing a reference in the SVNBase class where it can be misused
later

[ in subversion/bindings/javahl/native ]

* SVNBase.cpp,
  SVNBase.h
  (dispose, jthis): Accept jobject jthis as explicit parameter to dispose()
and
                    delete the member variable jthis

* SVNClient.cpp,
  SVNClient.h,
  SVNRepos.cpp,
  SVNRepos.h
  (dispose): Accept object jthis as explicit parameter and pass it to
             SVNBase::dispose

* org_apache_subversion_javahl_SVNClient.cpp,
  org_apache_subversion_javahl_SVNRepos.cpp
  (Java_org_apache_subversion_javahl_SVNClient_dispose,
   Java_org_apache_subversion_javahl_SVNRepos_dispose):
   Pass object jthis as explicit parameter and pass it to the C++ wrapper
class
]]]

Thank you,

Vladimir
Index: subversion/bindings/javahl/native/SVNRepos.cpp
===================================================================
--- subversion/bindings/javahl/native/SVNRepos.cpp      (revision 1328758)
+++ subversion/bindings/javahl/native/SVNRepos.cpp      (working copy)
@@ -54,10 +54,10 @@ SVNRepos *SVNRepos::getCppObject(jobject jthis)
   return (cppAddr == 0 ? NULL : reinterpret_cast<SVNRepos *>(cppAddr));
 }
 
-void SVNRepos::dispose()
+void SVNRepos::dispose(jobject jthis)
 {
   static jfieldID fid = 0;
-  SVNBase::dispose(&fid, JAVA_PACKAGE"/SVNRepos");
+  SVNBase::dispose(jthis, &fid, JAVA_PACKAGE"/SVNRepos");
 }
 
 void SVNRepos::cancelOperation()
Index: subversion/bindings/javahl/native/SVNClient.h
===================================================================
--- subversion/bindings/javahl/native/SVNClient.h       (revision 1328758)
+++ subversion/bindings/javahl/native/SVNClient.h       (working copy)
@@ -196,7 +196,7 @@ class SVNClient :public SVNBase
   ClientContext &getClientContext();
 
   const char *getLastPath();
-  void dispose();
+  void dispose(jobject jthis);
   static SVNClient *getCppObject(jobject jthis);
   SVNClient(jobject jthis_in);
   virtual ~SVNClient();
Index: 
subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNRepos.cpp
===================================================================
--- subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNRepos.cpp 
(revision 1328758)
+++ subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNRepos.cpp 
(working copy)
@@ -60,7 +60,7 @@ Java_org_apache_subversion_javahl_SVNRepos_dispose
       JNIUtil::throwError(_("bad C++ this"));
       return;
     }
-  cl->dispose();
+  cl->dispose(jthis);
 }
 
 JNIEXPORT void JNICALL
Index: subversion/bindings/javahl/native/SVNBase.cpp
===================================================================
--- subversion/bindings/javahl/native/SVNBase.cpp       (revision 1328758)
+++ subversion/bindings/javahl/native/SVNBase.cpp       (working copy)
@@ -30,7 +30,6 @@
 SVNBase::SVNBase()
     : pool(JNIUtil::getPool())
 {
-  jthis = NULL;
 }
 
 SVNBase::~SVNBase()
@@ -58,17 +57,6 @@ jlong SVNBase::findCppAddrForJObject(jobject jthis
       if (JNIUtil::isJavaExceptionThrown())
         return 0;
 
-      if (cppAddr)
-        {
-          /* jthis is not guaranteed to be the same between JNI invocations, so
-             we do a little dance here and store the updated version in our
-             object for this invocation.
-
-             findCppAddrForJObject() is, by necessity, called before any other
-             methods on the C++ object, so by doing this we can guarantee a
-             valid jthis pointer for subsequent uses. */
-          (reinterpret_cast<SVNBase *> (cppAddr))->jthis = jthis;
-        }
       return cppAddr;
     }
 }
@@ -82,17 +70,15 @@ void SVNBase::finalize()
   JNIUtil::enqueueForDeletion(this);
 }
 
-void SVNBase::dispose(jfieldID *fid, const char *className)
+void SVNBase::dispose(jobject jthis, jfieldID *fid, const char *className)
 {
-  jobject my_jthis = this->jthis;
-
   delete this;
   JNIEnv *env = JNIUtil::getEnv();
   SVNBase::findCppAddrFieldID(fid, className, env);
   if (*fid == 0)
     return;
 
-  env->SetLongField(my_jthis, *fid, 0);
+  env->SetLongField(jthis, *fid, 0);
   if (JNIUtil::isJavaExceptionThrown())
     return;
 }
Index: 
subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNClient.cpp
===================================================================
--- 
subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNClient.cpp    
    (revision 1328758)
+++ 
subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNClient.cpp    
    (working copy)
@@ -75,7 +75,7 @@ Java_org_apache_subversion_javahl_SVNClient_dispos
       JNIUtil::throwError(_("bad C++ this"));
       return;
     }
-  cl->dispose();
+  cl->dispose(jthis);
 }
 
 JNIEXPORT void JNICALL
Index: subversion/bindings/javahl/native/SVNBase.h
===================================================================
--- subversion/bindings/javahl/native/SVNBase.h (revision 1328758)
+++ subversion/bindings/javahl/native/SVNBase.h (working copy)
@@ -49,7 +49,7 @@ class SVNBase
    *
    * @since 1.4.0
    */
-  virtual void dispose() = 0;
+  virtual void dispose(jobject jthis) = 0;
 
   /**
    * This method should never be called, as @c dispose() should be
@@ -80,14 +80,8 @@ class SVNBase
    *
    * @since 1.4.0
    */
-  void dispose(jfieldID *fid, const char *className);
+  void dispose(jobject jthis, jfieldID *fid, const char *className);
 
-  /**
-   * A pointer to the parent java object.  This is not valid across JNI
-   * method invocations, and so should be set in each one.
-   */
-  jobject jthis;
-
  private:
   /**
    * If the value pointed to by @a fid is zero, find the @c jfieldID
Index: subversion/bindings/javahl/native/SVNClient.cpp
===================================================================
--- subversion/bindings/javahl/native/SVNClient.cpp     (revision 1328758)
+++ subversion/bindings/javahl/native/SVNClient.cpp     (working copy)
@@ -86,10 +86,10 @@ SVNClient *SVNClient::getCppObject(jobject jthis)
     return (cppAddr == 0 ? NULL : reinterpret_cast<SVNClient *>(cppAddr));
 }
 
-void SVNClient::dispose()
+void SVNClient::dispose(jobject jthis)
 {
     static jfieldID fid = 0;
-    SVNBase::dispose(&fid, JAVA_PACKAGE"/SVNClient");
+    SVNBase::dispose(jthis, &fid, JAVA_PACKAGE"/SVNClient");
 }
 
 jstring SVNClient::getAdminDirectoryName()
Index: subversion/bindings/javahl/native/SVNRepos.h
===================================================================
--- subversion/bindings/javahl/native/SVNRepos.h        (revision 1328758)
+++ subversion/bindings/javahl/native/SVNRepos.h        (working copy)
@@ -69,7 +69,7 @@ class SVNRepos : public SVNBase
   void pack(File &path, ReposNotifyCallback *callback);
   SVNRepos();
   virtual ~SVNRepos();
-  void dispose();
+  void dispose(jobject jthis);
   static SVNRepos *getCppObject(jobject jthis);
 
   static svn_error_t *checkCancel(void *cancelBaton);

Reply via email to