SharedLibLoader patch

Per Bothner per@bothner.com
Tue Sep 4 02:52:00 GMT 2001


This is a preliminary patch for SharedLibLoader, which is a
ClassLoader backed by a shared library.  I.e. you can use gcj
to compile a set of classes (or a .jar file) into a shared
library, and then load the library into a running executable
as a *private* set of classes.  The classes exported by the
shared library are not entered in the global class table or
the "core" path.  Instead the classes are only visible when
loaded from the SharedLibLoader, just like classes loaded
from a UrlClassLoader are only visible via that loader.

There is no supported for resources as Anthony has implemented.

This patch is not ready as is, as there it least one glaring problem:
It calls dlopen/dlsym unconditionally.  The obvious "correct" fix
is to conditionalize on USE_LTDL.  The problem is that lt_dlopen
(if I read the code correctly) calls dlopen with the RTLD_GLOBAL
always set.  I don't think we want this for SharedLibLoader,
where the whole point is that each SharedLibLoader manages a
*separate local* set of classes, with local class names,
and hence we don't want to share symbols, since they might
clash.  (I can imagine having two different revisons of a shared
library loaded at the same time, each managed by its own
SharedLibLoader instance.)

I see two solution:
(1) Extend libltld to optionally not set RTLD_GLOBAL.
(2) Have an autoconf tets for dlopen, and conditionally
compile code in natSharedLibLoader depending on HAVE_DLOPEN
(rather than USE_LTDL).

The latter seems safer and easier. I can add a backup to use
lt_dlopen if dlopen id ! defined(HAVE_DLOPEN) && defined(USE_LTDL).

I've put this clsss in gnu.gcj.runtime, but that may not be best.
It is actually a gnu "extension" class, meant to be used by
applications, rather than an "implementation" class.  One might
argue for gnu.gcj.SharedLibLoader.

Index: SharedLibLoader.java
===================================================================
RCS file: SharedLibLoader.java
diff -N SharedLibLoader.java
--- /dev/null	Tue May  5 13:32:27 1998
+++ SharedLibLoader.java	Tue Sep  4 02:31:04 2001
@@ -0,0 +1,75 @@
+/* Copyright (C) 2001  Free Software Foundation
+
+   This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
+details.  */
+
+package gnu.gcj.runtime;
+import java.util.Hashtable;
+
+/**
+ * A ClassLoader backed by a gcj-compiled shared library.
+ * @author Per Bothner <per@bothner.com>, Brainfood Inc.
+ */
+
+public class SharedLibLoader extends ClassLoader
+{
+  public native void finalize ();
+
+  /** Called during dlopen's processing of the init section. */
+  void registerClass(String name, Class cls)
+  {
+    classMap.put(name, cls);
+  }
+
+  /** Load a shared library, and asociate a ClassLoader with it.
+   * @param libname named of shared library (passed to dlopen)
+   * @param parent the parent ClassLoader
+   * @parem flags passed to dlopen
+   */
+  public SharedLibLoader(String libname, ClassLoader parent, int flags)
+  {
+    super(parent);
+    init(libname, flags);
+  }
+
+
+  /** Load a shared library, and asociate a ClassLoader with it.
+   * @param libname named of shared library (passed to dlopen)
+   */
+  public SharedLibLoader(String libname)
+  {
+    super(getSystemClassLoader());
+    init(libname, 0);
+  }
+
+  void init(String libname, int flags)
+  {
+    init(libname.getBytes(), flags);
+  }
+
+  native void init(byte[] libname, int flags);
+
+  public Class loadClass(String name)
+    throws ClassNotFoundException
+  {
+    return super.loadClass(name);
+  }
+
+  public Class findClass(String name)
+    throws ClassNotFoundException
+  {
+    Object cls = classMap.get(name);
+    if (cls == null)
+      throw new ClassNotFoundException(name);
+    return (Class) cls;
+  }
+
+  /** The handle returned by dlopen. */
+  gnu.gcj.RawData handler;
+
+  /** Map classnames to Classes. */
+  Hashtable classMap = new Hashtable(20);
+}
Index: natSharedLibLoader.cc
===================================================================
RCS file: natSharedLibLoader.cc
diff -N natSharedLibLoader.cc
--- /dev/null	Tue May  5 13:32:27 1998
+++ natSharedLibLoader.cc	Tue Sep  4 02:31:04 2001
@@ -0,0 +1,63 @@
+// natSharedLibLoader.cc - Implementation of FirstThread native methods.
+
+/* Copyright (C) 2001  Free Software Foundation
+
+   This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
+details.  */
+
+#include <config.h>
+
+#include <gcj/cni.h>
+#include <gnu/gcj/runtime/SharedLibLoader.h>
+#include <dlfcn.h>
+#include <java/io/IOException.h>
+
+/* Only used during dlopen, while having a lock on ClassLoader.clsss. */
+static gnu::gcj::runtime::SharedLibLoader* curLoader;
+
+typedef void (*ClassHookFunc) (jclass);
+
+void ::register_hook(jclass cls)
+{
+  curLoader->registerClass(cls->getName(), cls);
+}
+
+struct SharedLibDummy
+{
+  ClassHookFunc saved;
+  SharedLibDummy()
+  {
+    saved = _Jv_RegisterClassHook;
+  }
+  ~SharedLibDummy()
+  {
+    _Jv_RegisterClassHook = saved;
+    curLoader = NULL;
+  }
+};
+
+void gnu::gcj::runtime::SharedLibLoader::init(jbyteArray libname, jint flags)
+{
+  char *lname = (char*) elements(libname);
+  if (flags==0)
+    flags = RTLD_LAZY;
+  JvSynchronize dummy1(&java::lang::Class::class$);
+  SharedLibDummy dummy2;
+  curLoader = this;
+  _Jv_RegisterClassHook = ::register_hook;
+  void *h = dlopen(lname, flags);
+  if (h == NULL)
+    {
+      const char *msg = dlerror();
+      throw new java::io::IOException(JvNewStringLatin1(msg));
+    }
+  handler = (gnu::gcj::RawData*) h;
+}
+
+void gnu::gcj::runtime::SharedLibLoader::finalize()
+{
+  dlclose (handler);
+}



More information about the Java-patches mailing list