This is the mail archive of the
java-patches@sources.redhat.com
mailing list for the Java project.
Revised patch: ClassLoader changes and more
- To: java-patches at sources dot redhat dot com
- Subject: Revised patch: ClassLoader changes and more
- From: Anthony Green <green at cygnus dot com>
- Date: Sat, 25 Nov 2000 19:56:45 -0800
- Reply-to: green at cygnus dot com
Thanks for pointing out the gotcha Bryce.
I was able to test this patch. It includes a reversion of Tom's
previous patch. I'm going to check it in on the theory that things
are pretty broken right now, and this makes it no worse than before.
URLClassLoader needed one more change to take into account the new
Vector implementation (our old one was broken in a way that we took
advantage of).
With these changes, the following program works as expected...
import java.util.*;
public class c
{
public static void main (String[] args) throws Exception
{
ClassLoader cl = Thread.currentThread().getContextClassLoader();
Enumeration e = cl.getResources (args[0]);
while (e.hasMoreElements())
System.out.println (e.nextElement ());
}
}
$ ./c java/lang/String.class
jar:file:///horton/green/net/i/share/libgcj.zip!/java/lang/String.class
2000-11-25 Anthony Green <green@redhat.com>
* prims.cc (_Jv_NewObjectArray): Undo placement change.
(_Jv_NewPrimArray): Likewise.
* gcj/array.h (__JArray): Undo const change. Removed constructor.
(class JArray): Removed constructor.
* 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. Use addElement instead of
insertElementAt.
(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: prims.cc
===================================================================
RCS file: /cvs/java/libgcj/libjava/prims.cc,v
retrieving revision 1.40
diff -u -p -2 -c -p -r1.40 prims.cc
*** prims.cc 2000/11/24 21:02:36 1.40
--- prims.cc 2000/11/26 03:41:52
*************** details. */
*** 68,74 ****
#endif
- // We use placement new.
- #include <new>
-
// We allocate a single OutOfMemoryError exception which we keep
// around for use if we run out of memory.
--- 68,71 ----
*************** _Jv_NewObjectArray (jsize count, jclass
*** 415,421 ****
if (__builtin_expect (! obj, false))
JvThrow (no_memory);
! // Use placement new to initialize length field.
! new (obj) __JArray (count);
! jobject *ptr = elements(obj);
// We know the allocator returns zeroed memory. So don't bother
// zeroing it again.
--- 412,417 ----
if (__builtin_expect (! obj, false))
JvThrow (no_memory);
! obj->length = count;
! jobject *ptr = elements (obj);
// We know the allocator returns zeroed memory. So don't bother
// zeroing it again.
*************** _Jv_NewPrimArray (jclass eltype, jint co
*** 451,456 ****
if (__builtin_expect (! arr, false))
JvThrow (no_memory);
! // Use placement new to initialize length field.
! new (arr) __JArray (count);
// Note that we assume we are given zeroed memory by the allocator.
--- 447,451 ----
if (__builtin_expect (! arr, false))
JvThrow (no_memory);
! arr->length = count;
// Note that we assume we are given zeroed memory by the allocator.
Index: gcj/array.h
===================================================================
RCS file: /cvs/java/libgcj/libjava/gcj/array.h,v
retrieving revision 1.9
diff -u -p -2 -c -p -r1.9 array.h
*** array.h 2000/11/24 21:02:36 1.9
--- array.h 2000/11/26 03:41:52
*************** extern "Java" {
*** 18,36 ****
class __JArray : public java::lang::Object
{
- protected:
- // FIXME: this is a hack to work around a bug in the g++ Java
- // support. If we add a constructor with a jsize argument to
- // JArray<T>, then g++ complains.
- __JArray () : length (0)
- {
- }
public:
! const jsize length;
friend jsize JvGetArrayLength (__JArray*);
-
- // This probably shouldn't be public.
- __JArray (jsize l) : length (l)
- {
- }
};
--- 18,24 ----
class __JArray : public java::lang::Object
{
public:
! jsize length;
friend jsize JvGetArrayLength (__JArray*);
};
Index: java/lang/Class.h
===================================================================
RCS file: /cvs/java/libgcj/libjava/java/lang/Class.h,v
retrieving revision 1.26
diff -u -p -2 -c -p -r1.26 Class.h
*** Class.h 2000/10/06 01:49:31 1.26
--- Class.h 2000/11/26 03:41:52
*************** class java::lang::Class : public java::l
*** 104,107 ****
--- 104,108 ----
{
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 -2 -c -p -r1.9 Class.java
*** Class.java 2000/03/07 19:55:26 1.9
--- Class.java 2000/11/26 03:41:52
*************** public final class Class implements Seri
*** 31,34 ****
--- 31,36 ----
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 ();
Index: java/lang/ClassLoader.java
===================================================================
RCS file: /cvs/java/libgcj/libjava/java/lang/ClassLoader.java,v
retrieving revision 1.9
diff -u -p -2 -c -p -r1.9 ClassLoader.java
*** ClassLoader.java 2000/03/07 19:55:26 1.9
--- ClassLoader.java 2000/11/26 03:41:52
*************** package java.lang;
*** 12,17 ****
--- 12,19 ----
import java.io.InputStream;
+ import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
+ import java.util.Enumeration;
import java.util.Stack;
*************** public abstract class ClassLoader {
*** 133,137 ****
throws ClassNotFoundException
{
! throw new ClassNotFoundException ();
}
--- 135,139 ----
throws ClassNotFoundException
{
! throw new ClassNotFoundException (name);
}
*************** public abstract class ClassLoader {
*** 155,159 ****
* @see ClassLoader#defineClass(String,byte[],int,int) */
protected final Class defineClass(byte[] data, int off, int len)
! throws java.lang.ClassNotFoundException, java.lang.LinkageError
{
return defineClass (null, data, off, len);
--- 157,161 ----
* @see ClassLoader#defineClass(String,byte[],int,int) */
protected final Class defineClass(byte[] data, int off, int len)
! throws ClassFormatError
{
return defineClass (null, data, off, len);
*************** public abstract class ClassLoader {
*** 189,193 ****
int off,
int len)
! throws java.lang.ClassNotFoundException, java.lang.LinkageError
{
if (data==null || data.length < off+len || off<0 || len<0)
--- 191,195 ----
int off,
int len)
! throws ClassFormatError
{
if (data==null || data.length < off+len || off<0 || len<0)
*************** public abstract class ClassLoader {
*** 208,217 ****
return defineClass0 (name, data, off, len);
! } catch (java.lang.LinkageError x) {
throw x; // rethrow
- } catch (java.lang.ClassNotFoundException x) {
- throw x; // rethrow
-
} catch (java.lang.VirtualMachineError x) {
throw x; // rethrow
--- 210,216 ----
return defineClass0 (name, data, off, len);
! } catch (ClassFormatError x) {
throw x; // rethrow
} catch (java.lang.VirtualMachineError x) {
throw x; // rethrow
*************** public abstract class ClassLoader {
*** 224,228 ****
+ name + ": "
+ x.toString ());
! }
}
--- 223,227 ----
+ name + ": "
+ x.toString ());
! }
}
*************** public abstract class ClassLoader {
*** 232,236 ****
int off,
int len)
! throws java.lang.ClassNotFoundException, java.lang.LinkageError;
--- 231,235 ----
int off,
int len)
! throws ClassFormatError;
*************** public abstract class ClassLoader {
*** 357,362 ****
return res.openStream ();
} catch (java.io.IOException x) {
! return null;
! }
}
--- 356,361 ----
return res.openStream ();
} catch (java.io.IOException x) {
! return null;
! }
}
*************** public abstract class ClassLoader {
*** 370,377 ****
* @see java.io.URL
*/
! public URL getResource(String name) {
return null;
}
}
--- 369,429 ----
* @see java.io.URL
*/
! 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 -2 -c -p -r1.13 Thread.java
*** Thread.java 2000/09/07 12:09:41 1.13
--- Thread.java 2000/11/26 03:41:52
*************** public class Thread implements Runnable
*** 146,159 ****
}
! // TODO12:
! // public ClassLoader getContextClassLoader()
! // {
! // }
!
! // TODO12:
! // public void setContextClassLoader(ClassLoader cl)
! // {
! // }
public final void setName (String n)
{
--- 146,167 ----
}
! public ClassLoader getContextClassLoader()
! {
! if (context_class_loader == null)
! {
! context_class_loader = ClassLoader.getSystemClassLoader ();
! return context_class_loader;
! }
!
! // 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)
{
*************** public class Thread implements Runnable
*** 228,232 ****
alive_flag = false;
startable_flag = true;
!
if (current != null)
{
--- 236,240 ----
alive_flag = false;
startable_flag = true;
!
if (current != null)
{
*************** public class Thread implements Runnable
*** 235,238 ****
--- 243,247 ----
int pri = current.getPriority();
priority = (gmax < pri ? gmax : pri);
+ context_class_loader = current.context_class_loader;
}
else
*************** public class Thread implements Runnable
*** 278,282 ****
{
return "Thread[" + name + "," + priority + "," +
! (group == null ? "" : group.getName()) + "]";
}
--- 287,291 ----
{
return "Thread[" + name + "," + priority + "," +
! (group == null ? "" : group.getName()) + "]";
}
*************** public class Thread implements Runnable
*** 292,295 ****
--- 301,305 ----
private boolean alive_flag;
private boolean startable_flag;
+ private ClassLoader context_class_loader;
// Our native data.
Index: java/lang/natClass.cc
===================================================================
RCS file: /cvs/java/libgcj/libjava/java/lang/natClass.cc,v
retrieving revision 1.29
diff -u -p -2 -c -p -r1.29 natClass.cc
*** natClass.cc 2000/10/06 01:49:31 1.29
--- natClass.cc 2000/11/26 03:41:53
*************** static _Jv_Utf8Const *finit_leg_name = _
*** 73,77 ****
jclass
! java::lang::Class::forName (jstring className)
{
if (! className)
--- 73,77 ----
jclass
! java::lang::Class::forName (jstring className, java::lang::ClassLoader *loader)
{
if (! className)
*************** java::lang::Class::forName (jstring clas
*** 86,93 ****
_Jv_Utf8Const *name = _Jv_makeUtf8Const (buffer, length);
! // FIXME: should use class loader from calling method.
jclass klass = (buffer[0] == '['
! ? _Jv_FindClassFromSignature (name->data, NULL)
! : _Jv_FindClass (name, NULL));
if (klass)
--- 86,93 ----
_Jv_Utf8Const *name = _Jv_makeUtf8Const (buffer, length);
! // FIXME: should use bootstrap class loader if loader is null.
jclass klass = (buffer[0] == '['
! ? _Jv_FindClassFromSignature (name->data, loader)
! : _Jv_FindClass (name, loader));
if (klass)
*************** java::lang::Class::forName (jstring clas
*** 99,102 ****
--- 99,109 ----
}
+ jclass
+ java::lang::Class::forName (jstring className)
+ {
+ // FIXME: should use class loader from calling method.
+ return forName (className, NULL);
+ }
+
java::lang::reflect::Constructor *
java::lang::Class::getConstructor (JArray<jclass> *param_types)
Index: java/net/URLClassLoader.java
===================================================================
RCS file: /cvs/java/libgcj/libjava/java/net/URLClassLoader.java,v
retrieving revision 1.4
diff -u -p -2 -c -p -r1.4 URLClassLoader.java
*** URLClassLoader.java 2000/08/20 17:49:11 1.4
--- URLClassLoader.java 2000/11/26 03:41:53
*************** package java.net;
*** 11,14 ****
--- 11,15 ----
import java.io.*;
import java.util.jar.*;
+ import java.util.Enumeration;
import java.util.Vector;
*************** public class URLClassLoader extends Clas
*** 43,46 ****
--- 44,97 ----
}
+ // 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)
*************** public class URLClassLoader extends Clas
*** 62,90 ****
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 ();
!
! // 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"))
--- 113,120 ----
for (int i = 0; i < urls.length; i++)
{
! // Convert a Jar File URL into a Jar URL is possible.
! URL u = jarFileize(urls[i]);
! path.addElement (u);
if (u.getProtocol ().equals ("jar"))
*************** public class URLClassLoader extends Clas
*** 99,137 ****
/* ignore */
}
! info.insertElementAt (conn, i);
}
else
{
! info.insertElementAt (null, i);
}
}
}
! public URL getResource (String name)
{
for (int i = 0; i < path.size(); 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()));
}
else
{
URL p = new URL (u, name, getHandler0 (u.getProtocol()));
!
InputStream is = p.openStream();
if (is != null)
{
is.close();
! return p;
}
}
!
// if we get an exception ... try the next path element
} catch (IOException x) {
--- 129,176 ----
/* ignore */
}
! info.addElement (conn);
}
else
{
! info.addElement (null);
}
}
}
+
+ public URL[] getURLs ()
+ {
+ URL[] urls = new URL[path.size()];
+ path.copyInto (urls);
+ return urls;
+ }
! public Enumeration findResources (String name)
{
+ Vector results = new Vector ();
+
for (int i = 0; i < path.size(); i++)
{
! URL u = (URL)path.elementAt (i);
!
try {
JarURLConnection conn = (JarURLConnection) info.elementAt (i);
!
if (conn != null)
{
if (conn.getJarFile().getJarEntry (name) != null)
! 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();
! results.addElement (p);
}
}
!
// if we get an exception ... try the next path element
} catch (IOException x) {
*************** public class URLClassLoader extends Clas
*** 139,171 ****
}
}
!
! return null;
}
! /** IN jdk 1.2 this method is not overridden, but we gain performance
! by doing so.
! */
!
! public InputStream getResourceAsStream (String name)
{
for (int i = 0; i < path.size(); 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);
}
else
{
! InputStream is = new URL(u, name, getHandler0 (u.getProtocol())).openStream();
if (is != null)
! return is;
}
--- 178,209 ----
}
}
!
! return results.elements ();
}
! public URL findResource (String name)
{
for (int i = 0; i < path.size(); 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()));
}
else
{
! URL p = new URL (u, name, getHandler0 (u.getProtocol()));
!
! InputStream is = p.openStream();
if (is != null)
! {
! is.close();
! return p;
! }
}