You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by br...@apache.org on 2014/01/14 04:48:37 UTC

svn commit: r1557925 - in /subversion/trunk/subversion/bindings/javahl: native/JNIUtil.cpp native/JNIUtil.h native/jniwrapper/jni_base.cpp native/org_apache_subversion_javahl_NativeResources.cpp src/org/apache/subversion/javahl/NativeResources.java

Author: brane
Date: Tue Jan 14 03:48:36 2014
New Revision: 1557925

URL: http://svn.apache.org/r1557925
Log:
Move the JavaHL native library initialization into a context that
is guaranteed to be single-threaded.

[in subversion/bindings/javahl]
* src/org/apache/subversion/javahl/NativeResources.java
  (NativeResources.initNativeLibrary): Remove native method.
  (NativeResources.init): Remove call to initNativeLibrary.

* native/JNIUtil.h (JNIUtil::JNIGlobalInit): Make method private.
  (initialize_jni_util): Declare as friend.
  (JNIUtil::g_inInit, JNIUtil::g_initEnv): Remove.
* javahl/native/JNIUtil.cpp
  (JNIUtil::g_inInit, JNIUtil::g_initEnv): Remove.
  (GlobalInitGuard): Remove.
  (JNIUtil::JNIGlobalInit): Remove obsolete references to the above.
  (initialize_jni_util): Implement as a wrapper for JNIUtil::JNIGlobalInit.

* native/jniwrapper/jni_base.cpp
  (initialize_jni_util): Declare prototype here.
  (JNI_OnLoad): Call initialize_jni_util and handle the failure here.

* native/org_apache_subversion_javahl_NativeResources.cpp:
   Removed obsolete native implementation.

Removed:
    subversion/trunk/subversion/bindings/javahl/native/org_apache_subversion_javahl_NativeResources.cpp
Modified:
    subversion/trunk/subversion/bindings/javahl/native/JNIUtil.cpp
    subversion/trunk/subversion/bindings/javahl/native/JNIUtil.h
    subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_base.cpp
    subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/NativeResources.java

Modified: subversion/trunk/subversion/bindings/javahl/native/JNIUtil.cpp
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/JNIUtil.cpp?rev=1557925&r1=1557924&r2=1557925&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/JNIUtil.cpp (original)
+++ subversion/trunk/subversion/bindings/javahl/native/JNIUtil.cpp Tue Jan 14 03:48:36 2014
@@ -73,8 +73,6 @@ JNIMutex *JNIUtil::g_finalizedObjectsMut
 JNIMutex *JNIUtil::g_logMutex = NULL;
 JNIMutex *JNIUtil::g_configMutex = NULL;
 bool JNIUtil::g_initException;
-bool JNIUtil::g_inInit;
-JNIEnv *JNIUtil::g_initEnv;
 int JNIUtil::g_logLevel = JNIUtil::noLog;
 std::ofstream JNIUtil::g_logStream;
 
@@ -113,109 +111,19 @@ bool JNIUtil::JNIInit(JNIEnv *env)
   return true;
 }
 
-namespace
+/* Forwarder for calling JNIGlobalInit from JNI_OnLoad(). */
+bool initialize_jni_util(JNIEnv *env)
 {
-struct GlobalInitGuard
-{
-  enum InitState
-    {
-      state_null,
-      state_init,
-      state_done,
-      state_error
-    };
-
-  GlobalInitGuard()
-    : m_finished(false),
-      m_state(InitState(svn_atomic_cas(&m_global_state,
-                                       state_init, state_null)))
-    {
-      switch (m_state)
-        {
-        case state_null:
-          // This thread won the initialization contest.
-          break;
-
-        case state_done:
-          // The library is already initialized.
-          break;
-
-        case state_init:
-          // Another thread is currently initializing the
-          // library. Spin and wait for it to finish, with exponential
-          // backoff, but no longer than half a second.
-          for (unsigned shift = 0;
-               m_state == state_init && shift < 8;
-               ++shift)
-            {
-              apr_sleep((APR_USEC_PER_SEC / 1000) << shift);
-              m_state = InitState(svn_atomic_cas(&m_global_state,
-                                                 state_null, state_null));
-            }
-          if (m_state == state_init)
-            // The initialization didn't complete in half a second,
-            // which probably implies a thread crash or a deadlock.
-            m_state = state_error;
-          break;
-
-        default:
-          // Error state, or unknown state. In any case, do not continue.
-          m_state = state_error;
-        }
-    }
-
-  ~GlobalInitGuard()
-    {
-      // Signal the end of the library intialization if we're the
-      // initializing thread.
-      if (m_finished && m_state == state_null)
-        {
-          SVN_ERR_ASSERT_NO_RETURN(
-              state_init == svn_atomic_cas(&m_global_state,
-                                           state_done, state_init));
-        }
-    }
-
-  bool done() const
-    {
-      return (m_state == state_done);
-    }
-
-  bool error() const
-    {
-      return (m_state == state_error);
-    }
-
-  void finish()
-    {
-      m_finished = true;
-    }
-
-private:
-  bool m_finished;
-  InitState m_state;
-  static volatile svn_atomic_t m_global_state;
-};
-volatile svn_atomic_t
-GlobalInitGuard::m_global_state = GlobalInitGuard::state_null;
-} // anonymous namespace
+  return JNIUtil::JNIGlobalInit(env);
+}
 
 /**
  * Initialize the environment for all requests.
+ * This method must be called in a single-threaded context.
  * @param env   the JNI environment for this request
  */
 bool JNIUtil::JNIGlobalInit(JNIEnv *env)
 {
-  // This method has to be run only once during the run a program.
-  GlobalInitGuard guard;
-  if (guard.done())
-    return true;
-  else if (guard.error())
-    return false;
-
-  g_inInit = true;
-  g_initEnv = env;
-
   svn_error_t *err;
 
   /* This has to happen before any pools are created. */
@@ -325,10 +233,6 @@ bool JNIUtil::JNIGlobalInit(JNIEnv *env)
   if (isExceptionThrown())
     return false;
 
-  g_initEnv = NULL;
-  g_inInit = false;
-
-  guard.finish();
   return true;
 }
 

Modified: subversion/trunk/subversion/bindings/javahl/native/JNIUtil.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/JNIUtil.h?rev=1557925&r1=1557924&r2=1557925&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/JNIUtil.h (original)
+++ subversion/trunk/subversion/bindings/javahl/native/JNIUtil.h Tue Jan 14 03:48:36 2014
@@ -147,7 +147,6 @@ class JNIUtil
     }
 
   static apr_pool_t *getPool();
-  static bool JNIGlobalInit(JNIEnv *env);
   static bool JNIInit(JNIEnv *env);
   static bool initializeJNIRuntime();
   enum { noLog, errorLog, exceptionLog, entryLog } LogLevel;
@@ -158,6 +157,9 @@ class JNIUtil
   static JNIMutex *g_configMutex;
 
  private:
+  friend bool initialize_jni_util(JNIEnv *env);
+  static bool JNIGlobalInit(JNIEnv *env);
+
   static void wrappedHandleSVNError(svn_error_t *err, jthrowable jcause);
   static void putErrorsInTrace(svn_error_t *err,
                                std::vector<jobject> &stackTrace);
@@ -194,17 +196,6 @@ class JNIUtil
   static bool g_initException;
 
   /**
-   * Flag, that one thread is in the init code.  Cannot use mutex
-   * here since apr is not initialized yet.
-   */
-  static bool g_inInit;
-
-  /**
-   * The JNI environment used during initialization.
-   */
-  static JNIEnv *g_initEnv;
-
-  /**
    * The stream to write log messages to.
    */
   static std::ofstream g_logStream;

Modified: subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_base.cpp
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_base.cpp?rev=1557925&r1=1557924&r2=1557925&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_base.cpp (original)
+++ subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_base.cpp Tue Jan 14 03:48:36 2014
@@ -33,6 +33,7 @@
 #include "jni_stack.hpp"
 
 #include "../JNIUtil.h"
+bool initialize_jni_util(JNIEnv *env);
 
 // Global library initializaiton
 
@@ -45,6 +46,7 @@ JNIEXPORT jint JNICALL
 JNI_OnLoad(JavaVM* jvm, void*)
 {
   ::Java::Env::static_init(jvm);
+  const ::Java::Env env;
 
   const apr_status_t status = apr_initialize();
   if (!status)
@@ -55,9 +57,16 @@ JNI_OnLoad(JavaVM* jvm, void*)
       std::strcpy(buf, "Could not initialize APR: ");
       const std::size_t offset = std::strlen(buf);
       apr_strerror(status, buf + offset, sizeof(buf) - offset - 1);
-      const ::Java::Env env;
       env.ThrowNew(env.FindClass("java/lang/Error"), buf);
     }
+
+  // Initialize the old-style JavaHL infrastructure.
+  if (!initialize_jni_util(env.get()) && !env.ExceptionCheck())
+    {
+      env.ThrowNew(env.FindClass("java/lang/LinkageError"),
+                   "Native library initialization failed");
+    }
+
   return JNI_VERSION_1_2;
 }
 

Modified: subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/NativeResources.java
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/NativeResources.java?rev=1557925&r1=1557924&r2=1557925&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/NativeResources.java (original)
+++ subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/NativeResources.java Tue Jan 14 03:48:36 2014
@@ -141,9 +141,6 @@ public class NativeResources
      */
     private static final void init()
     {
-        if (!initNativeLibrary())
-            throw new LinkageError("Native library initialization failed");
-
         version = new Version();
         if (!version.isAtLeast(1, 9, 0))
         {
@@ -161,9 +158,4 @@ public class NativeResources
                 " but the run-time version is " + runtimeVersion);
         }
     }
-
-    /**
-     * Initialize the native library layer.
-     */
-    private static native boolean initNativeLibrary();
 }