JNI/Win32 Patch #3: Change _Jv_LookupJNIMethod( ) for "stdcall" export variations on Win32

Ranjit Mathew rmathew@hotmail.com
Sun Dec 8 08:57:00 GMT 2002


Hi,

     This patch proposes to change _Jv_LookupJNIMethod( ) in jni.cc
to accommodate the vagaries of exported symbols for JNI functions
that use the "stdcall" calling convention on Win32.

Please note that this would break the compiler generated stubs
for making a JNI call, for which I'll soon submit a separate
patch.

I've had to increase the size of the "buf" buffer in this
method to accommodate the '_', '@' and arguments size (1 + 1 + 10)
used by Win32 compilers to decorate "stdcall" functions. (For
example, "_fooBar@12" for MSVC.)

I store the leading '_' in buf[0] and consequently every offset
used in the previous incarnation of this function had to be
increased by one, even for non-Win32 platforms.

Finally, sorry Tom, but I didn't change it all the way to the
thread-safe form suggested by you (taking an "out" parameter,
rather than returning a value) - I wasn't too sure of how to
do it and it is too close to the GCC 3.3 branch. :-(


ChangeLog:

2002-12-08  Ranjit Mathew  <rmathew@hotmail.com>

	* jni.cc (_Jv_LookupJNIMethod): Modified to accept the
	size of the arguments for a JNI function. For Win32,
	modified to search for all forms of possible exported
	names of an "stdcall" JNI function.

	(_Jv_JNIMethod::call): Modified to calculate the size
	of the arguments passed to a JNI function and pass it
	to _Jv_LookupJNIMethod( ).

-------------------------------- 8< --------------------------------
--- jni.cc	2002-11-08 08:28:50.000000000 +0530
+++ jni.cc	2002-12-08 20:26:04.000000000 +0530
@@ -11,4 +11,5 @@
  #include <config.h>

+#include <stdio.h>
  #include <stddef.h>
  #include <string.h>
@@ -2023,7 +2025,7 @@
  extern "C" void *
  _Jv_LookupJNIMethod (jclass klass, _Jv_Utf8Const *name,
-		     _Jv_Utf8Const *signature)
+		     _Jv_Utf8Const *signature, int args_size)
  {
-  char buf[10 + 6 * (name->length + signature->length)];
+  char buf[10 + 6 * (name->length + signature->length) + 12];
    int long_start;
    void *function;
@@ -2045,17 +2047,75 @@

    // If there was no override, then look in the symbol table.
-  mangled_name (klass, name, signature, buf, &long_start);
-  char c = buf[long_start];
-  buf[long_start] = '\0';
-  function = _Jv_FindSymbolInExecutable (buf);
+  buf[0] = '_';
+  mangled_name (klass, name, signature, buf + 1, &long_start);
+  char c = buf[long_start + 1];
+  buf[long_start + 1] = '\0';
+
+  function = _Jv_FindSymbolInExecutable (buf + 1);
+#ifdef WIN32
+  // On Win32, we use the "stdcall" calling convention (see JNICALL
+  // in jni.h).
+  //
+  // For a function named 'fooBar' that takes 'nn' bytes as arguments,
+  // by default, MinGW GCC exports it as 'fooBar@nn', MSVC exports
+  // it as '_fooBar@nn' and BCC exports it as 'fooBar'. We try to
+  // take care of all of these variations.
+
+  char asz_buf[12];      /* '@' + '2147483647' (32-bit INT_MAX) + '\0' */
+  char long_nm_sv[11];   /* Ditto, except for the '\0'. */
+
    if (function == NULL)
      {
-      buf[long_start] = c;
+      // We have tried searching for the 'fooBar' form (BCC).
+      // Now try the others.
+
+      // First, save the part of the long name that will be damaged
+      // by appending '@nn'.
+      memcpy (long_nm_sv, (buf + long_start + 1 + 1), sizeof (long_nm_sv));
+
+      sprintf (asz_buf, "@%d", args_size);
+      strcat (buf, asz_buf);
+
+      // Search for the '_fooBar@xx' form (MSVC).
        function = _Jv_FindSymbolInExecutable (buf);
+
+      if ( function == NULL)
+        {
+          // Search for the 'fooBar@xx' form (MinGW GCC).
+          function = _Jv_FindSymbolInExecutable (buf + 1);
+	}
+    }
+#else /* WIN32 */
+  args_size;   /* Dummy statement to avoid unused parameter warning */
+#endif /* ! WIN32 */
+
+  if (function == NULL)
+    {
+      buf[long_start + 1] = c;
+#ifdef WIN32
+      // Restore the part of the long name that was damaged by
+      // appending the '@nn'.
+      memcpy ((buf + long_start + 1 + 1), long_nm_sv, sizeof (long_nm_sv));
+#endif /* WIN32 */
+      function = _Jv_FindSymbolInExecutable (buf + 1);
        if (function == NULL)
  	{
-	  jstring str = JvNewStringUTF (name->data);
-	  throw new java::lang::UnsatisfiedLinkError (str);
-	}
+#ifdef WIN32
+          strcat (buf, asz_buf);
+
+          function = _Jv_FindSymbolInExecutable (buf);
+
+          if (function == NULL)
+            {
+              function = _Jv_FindSymbolInExecutable (buf + 1);
+            }
+
+	  if (function == NULL)
+#endif /* WIN32 */
+            {
+	      jstring str = JvNewStringUTF (name->data);
+	      throw new java::lang::UnsatisfiedLinkError (str);
+            }
+        }
      }

@@ -2087,7 +2147,15 @@
      JvSynchronize sync (global_ref_table);
      if (_this->function == NULL)
-      _this->function = _Jv_LookupJNIMethod (_this->defining_class,
-					     _this->self->name,
-					     _this->self->signature);
+      {
+        int args_size = sizeof (JNIEnv *) + _this->args_raw_size;
+
+        if (_this->self->accflags & java::lang::reflect::Modifier::STATIC)
+          args_size += sizeof (_this->defining_class);
+
+        _this->function = _Jv_LookupJNIMethod (_this->defining_class,
+					       _this->self->name,
+					       _this->self->signature,
+					       args_size);
+      }
    }
-------------------------------- 8< --------------------------------

Sincerely Yours,
Ranjit.

-- 
Ranjit Mathew        Email: rmathew AT hotmail DOT com
Bangalore,
INDIA.               Web: http://ranjitmathew.tripod.com/





More information about the Java-patches mailing list