Patch: dynamic loading

Tom Tromey tromey@cygnus.com
Mon Jan 17 11:15:00 GMT 2000


I'm committing the appended patch.
It adds dynamic loading capabilities to libgcj.

With this patch, on native platforms, Runtime.loadLibrary will now
work correctly.

In addition, Class.forName() will try to load a series of shared
objects in order to find the requested class.  If a class
`gnu.quux.whatever' is requested, libgcj will first look for
`gnu-quux-whatever.so', then `gnu-quux.so', and finally `gnu.so'
(actually it will also look for `.la' and `.dll' files -- it uses ltdl
to do the searching).


2000-01-17  Tom Tromey  <tromey@cygnus.com>

	* java/lang/Runtime.java (loadLibraryInternal): Declare.
	* java/lang/natClassLoader.cc (_Jv_FindClass): Removed dead copy.
	(_Jv_FindClassInCache): Likewise.
	(_Jv_FindClass): Don't conditionalize body on INTERPRETER.
	(findSystemClass): Try to load class from compiled module.
	Include Runtime.h.
	* java/lang/natRuntime.cc (load): Use UTF-8 copy of filename.
	(loadLibrary): Likewise.
	(lt_preloaded_symbols): Define.
	(loadLibraryInternal): New method.
	* include/config.h.in: Rebuilt.
	* acconfig.h (USE_LTDL): Added.
	* Makefile.am (SUBDIRS): Added $(DIRLTDL).
	(INCLUDES): Added $(INCLTDL).b
	(libgcj_la_DEPENDENCIES): Added $(LIBLTDL).
	(libgcj_la_LIBADD): Likewise.
	* aclocal.m4, configure: Rebuilt.
	* configure.in: Added libltdl support.

Tom

Index: acconfig.h
===================================================================
RCS file: /cvs/java/libgcj/libjava/acconfig.h,v
retrieving revision 1.14
diff -u -r1.14 acconfig.h
--- acconfig.h	2000/01/17 15:43:32	1.14
+++ acconfig.h	2000/01/17 19:11:02
@@ -125,3 +125,6 @@
  
 /* Define if getuid() and friends are missing.  */
 #undef NO_GETUID
+
+/* Define if libltdl is in use.  */
+#undef USE_LTDL
Index: configure.in
===================================================================
RCS file: /cvs/java/libgcj/libjava/configure.in,v
retrieving revision 1.46
diff -u -r1.46 configure.in
--- configure.in	2000/01/17 15:43:32	1.46
+++ configure.in	2000/01/17 19:11:08
@@ -17,7 +17,20 @@
 
 AM_CONFIG_HEADER(include/config.h)
 
+# Only use libltdl for native builds.
+if test -z "${with_cross_host}"; then
+   AC_LIBLTDL_CONVENIENCE
+   AC_LIBTOOL_DLOPEN
+   DIRLTDL=libltdl
+   AC_DEFINE(USE_LTDL)
+   # Sigh.  Libtool's macro doesn't do the right thing.
+   INCLTDL="-I\$(top_srcdir)/libltdl $INCLTDL"
+fi
+AC_SUBST(INCLTDL)
+AC_SUBST(LIBLTDL)
+AC_SUBST(DIRLTDL)
 AM_PROG_LIBTOOL
+AC_CONFIG_SUBDIRS($DIRLDL)
 
 if test -z "$with_target_subdir" || test "$with_target_subdir" = "."; then
    COMPPATH=.
Index: java/lang/Runtime.java
===================================================================
RCS file: /cvs/java/libgcj/libjava/java/lang/Runtime.java,v
retrieving revision 1.4
diff -u -r1.4 Runtime.java
--- Runtime.java	1999/06/09 17:42:23	1.4
+++ Runtime.java	2000/01/17 19:11:13
@@ -1,6 +1,6 @@
 // Runtime.java - Runtime class.
 
-/* Copyright (C) 1998, 1999  Cygnus Solutions
+/* Copyright (C) 1998, 1999, 2000  Cygnus Solutions
 
    This file is part of libgcj.
 
@@ -96,6 +96,12 @@
 
   public native void load (String pathname);
   public native void loadLibrary (String libname);
+
+  // This is a helper function for the ClassLoader which can load
+  // compiled libraries.  Returns true if library (which is just the
+  // base name -- path searching is done by this function) was loaded,
+  // false otherwise.
+  native boolean loadLibraryInternal (String libname);
 
   public native void runFinalization ();
 
Index: java/lang/natClassLoader.cc
===================================================================
RCS file: /cvs/java/libgcj/libjava/java/lang/natClassLoader.cc,v
retrieving revision 1.13
diff -u -r1.13 natClassLoader.cc
--- natClassLoader.cc	2000/01/13 18:13:31	1.13
+++ natClassLoader.cc	2000/01/17 19:11:16
@@ -34,6 +34,7 @@
 #include <java/lang/ClassCircularityError.h>
 #include <java/lang/IncompatibleClassChangeError.h>
 #include <java/lang/reflect/Modifier.h>
+#include <java/lang/Runtime.h>
 
 #define CloneableClass _CL_Q34java4lang9Cloneable
 extern java::lang::Class CloneableClass;
@@ -193,7 +194,35 @@
 jclass
 gnu::gcj::runtime::VMClassLoader::findSystemClass (jstring name)
 {
-  return _Jv_FindClassInCache (_Jv_makeUtf8Const (name), 0);
+  _Jv_Utf8Const *name_u = _Jv_makeUtf8Const (name);
+  jclass klass = _Jv_FindClassInCache (name_u, 0);
+
+  if (! klass)
+    {
+      // Turn `gnu.pkg.quux' into `gnu-pkg-quux'.  Then search for a
+      // module named (eg, on Linux) `gnu-pkg-quux.so', followed by
+      // `gnu-pkg.so' and `gnu.so'.  If loading one of these causes
+      // the class to appear in the cache, then use it.
+      jstring so_base_name = name->replace ('.', '-');
+
+      while (! klass && so_base_name && so_base_name->length() > 0)
+	{
+	  using namespace ::java::lang;
+	  Runtime *rt = Runtime::getRuntime();
+	  jboolean loaded = rt->loadLibraryInternal (so_base_name);
+
+	  jint nd = so_base_name->lastIndexOf ('-');
+	  if (nd == -1)
+	    so_base_name = NULL;
+	  else
+	    so_base_name = so_base_name->substring (0, nd);
+
+	  if (loaded)
+	    klass = _Jv_FindClassInCache (name_u, 0);
+	}
+    }
+
+  return klass;
 }
 
 jclass
@@ -403,31 +432,11 @@
   _Jv_RegisterClasses (classes);
 }
 
-#if 0
-// NOTE: this one is out of date with the new loader stuff...
 jclass
-_Jv_FindClassInCache (jstring name, java::lang::ClassLoader *loader)
-{
-  JvSynchronize sync (&ClassClass);
-  jint hash = name->hashCode();
-  jclass klass = loaded_classes[(_Jv_ushort) hash % HASH_LEN];
-  for ( ; klass; klass = klass->next)
-    {
-      if (loader == klass->loader
-	  && _Jv_equal (klass->name, name, hash))
-	break;
-    }
-  _Jv_MonitorExit (&ClassClass);
-  return klass;
-}
-#endif
-
-jclass _Jv_FindClass (_Jv_Utf8Const *name,
-		      java::lang::ClassLoader *loader)
+_Jv_FindClass (_Jv_Utf8Const *name, java::lang::ClassLoader *loader)
 {
   jclass klass = _Jv_FindClassInCache (name, loader);
 
-#ifdef INTERPRETER
   if (! klass)
     {
       jstring sname = _Jv_NewStringUTF (name->data);
@@ -466,43 +475,9 @@
       // we're loading, so that they can refer to themselves. 
       _Jv_WaitForState (klass, JV_STATE_LOADED);
     }
-#endif
 
   return klass;
 }
-
-#if 0
-// NOTE: this one is out of date with the new class loader stuff...
-jclass
-_Jv_FindClass (jstring name, java::lang::ClassLoader *loader)
-{
-  jclass klass = _Jv_FindClassInCache (name, loader);
-  if (! klass)
-    {
-      if (loader)
-	{
-	  klass = loader->loadClass(name);
-	}
-      else
-	{
-	  // jmspec 5.3.1.2
-	  
-	  // delegate to the system loader
-	  klass = java::lang::ClassLoader::system.loadClass (sname);
-	  
-	  // register that we're an initiating loader
-	  if (klass)
-	    _Jv_RegisterInitiatingLoader (klass, 0);
-	}
-    }
-  else
-    {
-      _Jv_WaitForState (klass, JV_STATE_LOADED);
-    }
-  
-  return klass;
-}
-#endif
 
 jclass
 _Jv_NewClass (_Jv_Utf8Const *name, jclass superclass,
Index: java/lang/natRuntime.cc
===================================================================
RCS file: /cvs/java/libgcj/libjava/java/lang/natRuntime.cc,v
retrieving revision 1.3
diff -u -r1.3 natRuntime.cc
--- natRuntime.cc	1999/09/10 22:03:08	1.3
+++ natRuntime.cc	2000/01/17 19:11:16
@@ -1,6 +1,6 @@
 // natRuntime.cc - Implementation of native side of Runtime class.
 
-/* Copyright (C) 1998, 1999  Cygnus Solutions
+/* Copyright (C) 1998, 1999, 2000  Cygnus Solutions
 
    This file is part of libgcj.
 
@@ -20,6 +20,10 @@
 
 #ifdef USE_LTDL
 #include <ltdl.h>
+
+/* FIXME: we don't always need this.  The next libtool will let us use
+   AC_LTDL_PREOPEN to see if we do.  */
+const lt_dlsymlist lt_preloaded_symbols[1] = { { 0, 0 } };
 #endif
 
 void
@@ -56,8 +60,12 @@
   checkLink (path);
   using namespace java::lang;
 #ifdef USE_LTDL
+  jint len = _Jv_GetStringUTFLength (path);
+  char buf[len + 1];
+  jsize total = JvGetStringUTFRegion (path, 0, path->length(), buf);
+  buf[total] = '\0';
   // FIXME: make sure path is absolute.
-  lt_dlhandle h = lt_dlopen (FIXME);
+  lt_dlhandle h = lt_dlopen (buf);
   if (h == NULL)
     {
       const char *msg = lt_dlerror ();
@@ -76,8 +84,12 @@
   checkLink (lib);
   using namespace java::lang;
 #ifdef USE_LTDL
+  jint len = _Jv_GetStringUTFLength (lib);
+  char buf[len + 1];
+  jsize total = JvGetStringUTFRegion (lib, 0, lib->length(), buf);
+  buf[total] = '\0';
   // FIXME: make sure path is absolute.
-  lt_dlhandle h = lt_dlopenext (FIXME);
+  lt_dlhandle h = lt_dlopenext (buf);
   if (h == NULL)
     {
       const char *msg = lt_dlerror ();
@@ -86,6 +98,24 @@
 #else
   _Jv_Throw (new UnknownError
 	     (JvNewStringLatin1 ("Runtime.loadLibrary not implemented")));
+#endif /* USE_LTDL */
+}
+
+jboolean
+java::lang::Runtime::loadLibraryInternal (jstring lib)
+{
+  JvSynchronize sync (this);
+  using namespace java::lang;
+#ifdef USE_LTDL
+  jint len = _Jv_GetStringUTFLength (lib);
+  char buf[len + 1];
+  jsize total = JvGetStringUTFRegion (lib, 0, lib->length(), buf);
+  buf[total] = '\0';
+  // FIXME: make sure path is absolute.
+  lt_dlhandle h = lt_dlopenext (buf);
+  return h != NULL;
+#else
+  return false;
 #endif /* USE_LTDL */
 }
 


More information about the Java-patches mailing list