This is the mail archive of the java-patches@sources.redhat.com mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

ClassLoader changes and more



This patch includes a number of ClassLoader related changes which
bring our implementation much closer to 1.3.  This includes new
methods and new semantics (for the getResource methods).

I'm not checking these changes in yet because I have not been able to
test them.  I don't think I've introduced any bugs, but I can't build
any working programs with the latest tools.  Is anyone else seeing
this failure on program startup?

(gdb) where
#0  0x401687c7 in _Jv_CheckArrayStore (arr=0x8084f18, obj=0x8064f60)
    at ../../../libgcj/libgcj/libjava/java/lang/natClass.cc:912
#1  0x401c9b72 in internalPut__Q34java4util9HashtablePQ34java4lang6ObjectT1 (
    this=0x8065cd0, key=0x8067e40, value=0x8066de0)
    at ../../../libgcj/libgcj/libjava/java/util/Hashtable.java:407
#2  0x401c99f1 in put__Q34java4util9HashtablePQ34java4lang6ObjectT1 (
    this=0x8065cd0, key=0x8067e40, value=0x8066de0)
    at ../../../libgcj/libgcj/libjava/java/util/Hashtable.java:366
#3  0x4016e9a3 in java::lang::System::init_properties ()
    at ../../../libgcj/libgcj/libjava/gcj/cni.h:64
#4  0x40183b4f in getProperty__Q34java4lang6SystemPQ34java4lang6String (
    property=0x8067e70)
    at ../../../libgcj/libgcj/libjava/java/lang/System.java:74
#5  0x401a65b0 in _003cclinit_003e__Q34java2io11PrintStreamU ()
    at ../../../libgcj/libgcj/libjava/java/io/PrintStream.java:301
#6  0x40167d4d in java::lang::Class::initializeClass (this=0x402f5340)
    at ../../../libgcj/libgcj/libjava/java/lang/natClass.cc:760
#7  0x4014e856 in _Jv_AllocObject (klass=0x402f5340, size=28)
    at ../../../libgcj/libgcj/libjava/java/lang/Class.h:215
#8  0x4018406f in _003cclinit_003e__Q34java4lang6SystemU ()
    at ../../../libgcj/libgcj/libjava/java/lang/System.java:156
#9  0x40167d4d in java::lang::Class::initializeClass (this=0x804d638)
    at ../../../libgcj/libgcj/libjava/java/lang/natClass.cc:760
#10 0x402751f4 in _Jv_InitClass (klass=0x804d638)
    at ../../../libgcj/libgcj/libjava/java/lang/Class.h:215
#11 0x40183c20 in java.lang.System.getSecurityManager ()
    at ../../../libgcj/libgcj/libjava/java/lang/System.java:87
#12 0x40186787 in java.lang.ThreadGroup.checkAccess (this=0x8066ea0)
    at ../../../libgcj/libgcj/libjava/java/lang/ThreadGroup.java:544
#13 0x4018425b in __Q34java4lang6ThreadPQ34java4lang11ThreadGroupPQ34java4lang8RunnablePQ34java4lang6String (this=0x8067ea0, g=0x0, r=0x0, n=0x8066ee0)
    at ../../../libgcj/libgcj/libjava/java/lang/Thread.java:220
#14 0x401df238 in __Q43gnu3gcj7runtime11FirstThreadPQ34java4lang5ClassPQ34java4lang6Object (this=0x8067ea0, k=0x804ce60, o=0x806ceb8)
    at ../../../libgcj/libgcj/libjava/gnu/gcj/runtime/FirstThread.java:28
#15 0x4014f494 in JvRunMain (klass=0x804ce60, argc=3, argv=0xbffff934)
    at ../../../libgcj/libgcj/libjava/prims.cc:888
#16 0x804bc43 in main (argc=3, argv=0xbffff934)
#17 0x404429cb in __libc_start_main (main=0x804bc20 <main>, argc=3, 
    argv=0xbffff934, init=0x80490b4 <_init>, fini=0x804bcac <_fini>, 
    rtld_fini=0x4000ae60 <_dl_fini>, stack_end=0xbffff92c)
    at ../sysdeps/generic/libc-start.c:92
(gdb) 

2000-11-25  Anthony Green  <green@redhat.com>

	* java/lang/Thread.java (context_class_loader): New private data.
	(getContextClassLoader): New method.
	(setContextClassLoader): New method.
	(Thread): Initialize context_class_loader.

	* java/net/URLClassLoader.java: Import java.util.Enumeration.
	(getResource): Rename to findResource.
	(findResource): New method.  Used to be getResource.
	(getResourceAsStream): Deleted.
	(jarFileize): Extracted logic from URLClassLoader constructor into
	this new private method.
	(addURL): New protected method.
	(URLClassLoader): Call jarFileize.
	(findResources): New method.
	
	* java/lang/ClassLoader.java: Import java.util.Enumeration.
	(getResource): Implement correct logic.
	(findResource): New method.
	(getResources): New method.
	(findClass): Create a ClassNotFoundException with the name of the
	class rather than nothing at all.
	(defineClass) Only throw ClassFormatError.
	
	* java/lang/Class.java (forName): New method.
	* java/lang/Class.h (forName): New method.
	* java/lang/natClass.cc (forName): New method.

Index: java/lang/Class.h
===================================================================
RCS file: /cvs/java/libgcj/libjava/java/lang/Class.h,v
retrieving revision 1.26
diff -u -p -p -r1.26 Class.h
--- Class.h	2000/10/06 01:49:31	1.26
+++ Class.h	2000/11/25 22:29:00
@@ -103,6 +103,7 @@ struct _Jv_ifaces
 class java::lang::Class : public java::lang::Object
 {
 public:
+  static jclass forName (jstring className, java::lang::ClassLoader *loader);
   static jclass forName (jstring className);
   JArray<jclass> *getClasses (void);
 
Index: java/lang/Class.java
===================================================================
RCS file: /cvs/java/libgcj/libjava/java/lang/Class.java,v
retrieving revision 1.9
diff -u -p -p -r1.9 Class.java
--- Class.java	2000/03/07 19:55:26	1.9
+++ Class.java	2000/11/25 22:29:00
@@ -30,6 +30,8 @@ public final class Class implements Seri
 {
   public static native Class forName (String className)
     throws ClassNotFoundException;
+  public static native Class forName (String className, ClassLoader loader)
+    throws ClassNotFoundException;
   public native Class[] getClasses ();
   public native ClassLoader getClassLoader ();
   public native Class getComponentType ();
Index: java/lang/ClassLoader.java
===================================================================
RCS file: /cvs/java/libgcj/libjava/java/lang/ClassLoader.java,v
retrieving revision 1.9
diff -u -p -p -r1.9 ClassLoader.java
--- ClassLoader.java	2000/03/07 19:55:26	1.9
+++ ClassLoader.java	2000/11/25 22:29:00
@@ -11,8 +11,10 @@ details.  */
 package java.lang;
 
 import java.io.InputStream;
+import java.io.IOException;
 import java.net.URL;
 import java.net.URLConnection;
+import java.util.Enumeration;
 import java.util.Stack;
 
 /**
@@ -132,7 +134,7 @@ public abstract class ClassLoader {
   protected Class findClass (String name)
     throws ClassNotFoundException
   {
-    throw new ClassNotFoundException ();
+    throw new ClassNotFoundException (name);
   }
 
   /** 
@@ -154,7 +156,7 @@ public abstract class ClassLoader {
    * @exception java.lang.LinkageError
    * @see ClassLoader#defineClass(String,byte[],int,int) */
   protected final Class defineClass(byte[] data, int off, int len) 
-    throws java.lang.ClassNotFoundException, java.lang.LinkageError
+    throws ClassFormatError
   {
     return defineClass (null, data, off, len);
   }
@@ -188,7 +190,7 @@ public abstract class ClassLoader {
 						 byte[] data,
 						 int off,
 						 int len)
-    throws java.lang.ClassNotFoundException, java.lang.LinkageError
+    throws ClassFormatError
   {
     if (data==null || data.length < off+len || off<0 || len<0)
       throw new ClassFormatError ("arguments to defineClass "
@@ -207,12 +209,9 @@ public abstract class ClassLoader {
 
       return defineClass0 (name, data, off, len);
 
-    } catch (java.lang.LinkageError x) {
+    } catch (ClassFormatError x) {
       throw x;		// rethrow
 
-    } catch (java.lang.ClassNotFoundException x) {
-      throw x;		// rethrow
-
     } catch (java.lang.VirtualMachineError x) {
       throw x;		// rethrow
 
@@ -223,7 +222,7 @@ public abstract class ClassLoader {
 			       + "while defining class "
 			       + name + ": " 
 			       + x.toString ());
-     }
+    }
   }
 
   /** This is the entry point of defineClass into the native code */
@@ -231,7 +230,7 @@ public abstract class ClassLoader {
 				     byte[] data,
 				     int off,
 				     int len)
-    throws java.lang.ClassNotFoundException, java.lang.LinkageError;
+    throws ClassFormatError;
 
 
   /** 
@@ -356,8 +355,8 @@ public abstract class ClassLoader {
       if (res == null) return null;
       return res.openStream ();
     } catch (java.io.IOException x) {
-       return null;
-     }
+      return null;
+    }
   }
  
   /**
@@ -369,9 +368,62 @@ public abstract class ClassLoader {
    * @see     java.lang.ClassLoader#getResourceAsStream(String)
    * @see     java.io.URL
    */
-  public URL getResource(String name) {
+  public URL getResource (String name) 
+  {
+    // The rules say search the parent class if non-null,
+    // otherwise search the built-in class loader (assumed to be
+    // the system ClassLoader).  If not found, call
+    // findResource().
+    URL result = null;
+
+    ClassLoader delegate = parent;
+
+    if (delegate == null)
+      delegate = getSystemClassLoader ();
+	
+    // Protect ourselves from looping.
+    if (this != delegate)
+      result = delegate.getResource (name);
+
+    if (result != null)
+      return result;
+    else
+      return findResource (name);
+  }
+
+  protected URL findResource (String name)
+  {
+    // Default to returning null.  Derived classes implement this.
     return null;
   }
 
+  public Enumeration getResources (String name) throws IOException
+  {
+    // The rules say search the parent class if non-null,
+    // otherwise search the built-in class loader (assumed to be
+    // the system ClassLoader).  If not found, call
+    // findResource().
+    Enumeration result = null;
+
+    ClassLoader delegate = parent;
+
+    if (delegate == null)
+      delegate = getSystemClassLoader ();
+	
+    // Protect ourselves from looping.
+    if (this != delegate)
+      result = delegate.getResources (name);
+
+    if (result != null)
+      return result;
+    else
+      return findResources (name);
+  }
+
+  protected Enumeration findResources (String name) throws IOException
+  {
+    // Default to returning null.  Derived classes implement this.
+    return null;
+  }
 }
 
Index: java/lang/Thread.java
===================================================================
RCS file: /cvs/java/libgcj/libjava/java/lang/Thread.java,v
retrieving revision 1.13
diff -u -p -p -r1.13 Thread.java
--- Thread.java	2000/09/07 12:09:41	1.13
+++ Thread.java	2000/11/25 22:29:00
@@ -145,15 +145,20 @@ public class Thread implements Runnable
     daemon_flag = status;
   }
 
-  // TODO12:
-  // public ClassLoader getContextClassLoader()
-  // {
-  // }
-
-  // TODO12:
-  // public void setContextClassLoader(ClassLoader cl)
-  // {
-  // }
+  public ClassLoader getContextClassLoader()
+  {
+    if (context_class_loader == null)
+      return null;
+
+    // FIXME: Add security manager stuff here.
+    return context_class_loader;
+  }
+
+  public void setContextClassLoader(ClassLoader cl)
+  {
+    // FIXME: Add security manager stuff here.
+    context_class_loader = cl;
+  }
 
   public final void setName (String n)
   {
@@ -234,11 +239,13 @@ public class Thread implements Runnable
         int gmax = group.getMaxPriority();
 	int pri = current.getPriority();
 	priority = (gmax < pri ? gmax : pri);
+	context_class_loader = current.context_class_loader;
       }
     else
       {
 	daemon_flag = false;
 	priority = NORM_PRIORITY;
+	context_class_loader = ClassLoader.getSystemClassLoader ();
       }
 
     initialize_native ();
@@ -277,7 +284,7 @@ public class Thread implements Runnable
   public String toString ()
   {
     return "Thread[" + name + "," + priority + "," + 
-	   (group == null ? "" : group.getName()) + "]";
+      (group == null ? "" : group.getName()) + "]";
   }
 
   public static native void yield ();
@@ -291,6 +298,7 @@ public class Thread implements Runnable
   boolean interrupt_flag;
   private boolean alive_flag;
   private boolean startable_flag;
+  private ClassLoader context_class_loader;
 
   // Our native data.
   private Object data;
Index: java/lang/natClass.cc
===================================================================
RCS file: /cvs/java/libgcj/libjava/java/lang/natClass.cc,v
retrieving revision 1.29
diff -u -p -p -r1.29 natClass.cc
--- natClass.cc	2000/10/06 01:49:31	1.29
+++ natClass.cc	2000/11/25 22:29:00
@@ -72,7 +72,7 @@ static _Jv_Utf8Const *finit_leg_name = _
 
 
 jclass
-java::lang::Class::forName (jstring className)
+java::lang::Class::forName (jstring className, java::lang::ClassLoader *loader)
 {
   if (! className)
     JvThrow (new java::lang::NullPointerException);
@@ -85,10 +85,10 @@ java::lang::Class::forName (jstring clas
   // IllegalArgumentException on failure.
   _Jv_Utf8Const *name = _Jv_makeUtf8Const (buffer, length);
 
-  // FIXME: should use class loader from calling method.
+  // FIXME: should use bootstrap class loader if loader is null.
   jclass klass = (buffer[0] == '[' 
-		  ? _Jv_FindClassFromSignature (name->data, NULL)
-		  : _Jv_FindClass (name, NULL));
+		  ? _Jv_FindClassFromSignature (name->data, loader)
+		  : _Jv_FindClass (name, loader));
 
   if (klass)
     _Jv_InitClass (klass);
@@ -96,6 +96,13 @@ java::lang::Class::forName (jstring clas
     JvThrow (new java::lang::ClassNotFoundException (className));
 
   return klass;
+}
+
+jclass
+java::lang::Class::forName (jstring className)
+{
+  // FIXME: should use class loader from calling method.
+  return forName (className, NULL);
 }
 
 java::lang::reflect::Constructor *
Index: java/net/URLClassLoader.java
===================================================================
RCS file: /cvs/java/libgcj/libjava/java/net/URLClassLoader.java,v
retrieving revision 1.4
diff -u -p -p -r1.4 URLClassLoader.java
--- URLClassLoader.java	2000/08/20 17:49:11	1.4
+++ URLClassLoader.java	2000/11/25 22:29:01
@@ -10,6 +10,7 @@ package java.net;
 
 import java.io.*;
 import java.util.jar.*;
+import java.util.Enumeration;
 import java.util.Vector;
 
 public class URLClassLoader extends ClassLoader 
@@ -42,6 +43,56 @@ public class URLClassLoader extends Clas
     this (urls, parent, null);
   }
 
+  // A File URL may actually be a Jar URL.  Convert if possible.
+  private URL jarFileize (URL url)
+  {
+    if (! url.getProtocol ().equals ("jar"))
+      {
+	String f = url.getFile ();
+
+	// If it ends with '/' we'll take it for a directory,
+	// otherwise it's a jar file.  This is how JDK 1.2 defines
+	// it, so we will not try to be smart here.
+	if (f.charAt (f.length ()-1) != '/')
+	  {
+	    try
+	      {
+		url = new URL ("jar", "", -1, (url.toExternalForm ())+"!/", 
+			       getHandler0 ("jar"));
+	      } 
+	    catch (MalformedURLException x)
+	      {
+		/* ignore */
+	      }
+	  }
+      }
+    return url;
+  }
+
+  protected void addURL (URL url)
+  {
+    JarURLConnection conn = null;
+    
+    // Convert a Jar File URL into Jar URL if possible.
+    url = jarFileize (url);
+
+    path.addElement (url);
+
+    if (url.getProtocol ().equals ("jar"))
+      {
+	try
+	  {
+	    conn = (JarURLConnection) url.openConnection ();
+	  }
+	catch (java.io.IOException x)
+	  {
+	    /* ignore */
+	  }
+      }
+
+    info.addElement (conn);
+  }
+
   public URLClassLoader (URL[] urls, ClassLoader parent,
 			 URLStreamHandlerFactory fac)
   { 
@@ -61,30 +112,9 @@ public class URLClassLoader extends Clas
 
     for (int i = 0; i < urls.length; i++)
       {
-	URL u = urls[i];
-
-	// If it is a jar url, then we'll search it as is.  
-	if (! u.getProtocol ().equals ("jar"))
-	  {
-	    String f = u.getFile ();
+	// Convert a Jar File URL into a Jar URL is possible. 
+	URL u = jarFileize(urls[i]);
 
-	    // If it ends with '/' we'll take it for a directory,
-	    // otherwise it's a jar file.  This is how JDK 1.2 defines
-	    // it, so we will not try to be smart here.
-	    if (f.charAt (f.length ()-1) != '/')
-	      {
-		try
-		  {
-		    u = new URL ("jar", "", -1, (u.toExternalForm ())+"!/", 
-				 getHandler0 ("jar"));
-		  } 
-		catch (MalformedURLException x)
-		  {
-		    /* ignore */
-		  }
-	      }
-	  }
-
 	path.insertElementAt (u, i);
 
 	if (u.getProtocol ().equals ("jar"))
@@ -106,67 +136,75 @@ public class URLClassLoader extends Clas
 	  }
       }
   }
+
+  public URL[] getURLs ()
+  {
+    URL[] urls = new URL[path.size()];
+    path.copyInto (urls);
+    return urls;
+  }
   
-  public URL getResource (String name)
+  public Enumeration findResources (String name)
   {
+    Vector results = new Vector ();
+	
     for (int i = 0; i < path.size(); i++)
       {
-	URL u    = (URL)path.elementAt (i);
-	
+	URL u = (URL)path.elementAt (i);
+		
 	try {
 	  JarURLConnection conn = (JarURLConnection) info.elementAt (i);
- 	  
+		    
 	  if (conn != null)
 	    {
 	      if (conn.getJarFile().getJarEntry (name) != null)
-		return new URL(u, name, getHandler0 (u.getProtocol()));
+		results.addElement (new URL(u, name, getHandler0 (u.getProtocol())));
 	    }
 	  else
 	    {
 	      URL p = new URL (u, name, getHandler0 (u.getProtocol()));
-
+			    
 	      InputStream is = p.openStream();
 	      if (is != null)
 		{
 		  is.close();
-		  return p;
+		  results.addElement (p);
 		}
 	    }
-	
+		    
 	  // if we get an exception ... try the next path element
 	} catch (IOException x) {
 	  continue;
 	}
       }
-
-    return null;
+	
+    return results.elements ();
   }
 
-  /** IN jdk 1.2 this method is not overridden, but we gain performance
-      by doing so.
-   */
-
-  public InputStream getResourceAsStream (String name)
+  public URL findResource (String name)
   {
     for (int i = 0; i < path.size(); i++)
       {
-	URL u    = (URL)path.elementAt (i);
+	URL u = (URL)path.elementAt (i);
 	
 	try {
 	  JarURLConnection conn = (JarURLConnection) info.elementAt (i);
-	  
+ 	  
 	  if (conn != null)
 	    {
-	      JarFile file = conn.getJarFile ();
-	      JarEntry ent = file.getJarEntry (name);
-	      if (ent != null)
-		return file.getInputStream(ent);
+	      if (conn.getJarFile().getJarEntry (name) != null)
+		return new URL(u, name, getHandler0 (u.getProtocol()));
 	    }
 	  else
 	    {
-	      InputStream is = new URL(u, name, getHandler0 (u.getProtocol())).openStream();
+	      URL p = new URL (u, name, getHandler0 (u.getProtocol()));
+
+	      InputStream is = p.openStream();
 	      if (is != null)
-		return is;
+		{
+		  is.close();
+		  return p;
+		}
 	    }
 	
 	  // if we get an exception ... try the next path element

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]