* Merged gcj-abi-2-dev-branch to trunk.

(Actual changes too large to list in the commit message;
see ChangeLog.)

From-SVN: r91270
This commit is contained in:
Tom Tromey 2004-11-25 03:47:08 +00:00
parent ec0641f612
commit 367390404d
70 changed files with 11301 additions and 3355 deletions

View file

@ -121,15 +121,15 @@ public class ObjectInputStream extends InputStream
*/
public final Object readObject() throws ClassNotFoundException, IOException
{
if (callersClassLoader == null)
{
callersClassLoader = getCallersClassLoader ();
if (Configuration.DEBUG && dump)
{
dumpElementln ("CallersClassLoader = " + callersClassLoader);
}
}
if (callersClassLoader == null)
{
callersClassLoader = getCallersClassLoader ();
if (Configuration.DEBUG && dump)
{
dumpElementln ("CallersClassLoader = " + callersClassLoader);
}
}
if (this.useSubclassMethod)
return readObjectOverride();
@ -271,7 +271,7 @@ public class ObjectInputStream extends InputStream
readArrayElements(array, componentType);
if(dump)
for (int i = 0, len = Array.getLength(array); i < len; i++)
dumpElementln(" ELEMENT[" + i + "]=" + Array.get(array, i));
dumpElementln(" ELEMENT[" + i + "]=" + Array.get(array, i));
ret_val = processResolution(null, array, handle);
break;
}
@ -398,6 +398,8 @@ public class ObjectInputStream extends InputStream
setBlockDataMode(old_mode);
this.isDeserializing = was_deserializing;
depth -= 2;
depth -= 2;
@ -1806,6 +1808,7 @@ public class ObjectInputStream extends InputStream
* @param sm SecurityManager instance which should be called.
* @return The current class loader in the calling stack.
*/
private static native ClassLoader currentClassLoader (SecurityManager sm);
private native ClassLoader getCallersClassLoader();
@ -1875,7 +1878,7 @@ public class ObjectInputStream extends InputStream
private int depth = 0;
private void dumpElement (String msg)
{
{
System.out.print(msg);
}

View file

@ -347,8 +347,8 @@ public class ObjectOutputStream extends OutputStream
fieldsAlreadyWritten = false;
if (currentObjectStreamClass.hasWriteMethod())
{
if (dump)
dumpElementln ("WRITE METHOD CALLED FOR: " + obj);
if (dump)
dumpElementln ("WRITE METHOD CALLED FOR: " + obj);
setBlockDataMode(true);
callWriteMethod(obj, currentObjectStreamClass);
setBlockDataMode(false);
@ -358,10 +358,10 @@ public class ObjectOutputStream extends OutputStream
}
else
{
if (dump)
dumpElementln ("WRITE FIELDS CALLED FOR: " + obj);
writeFields(obj, currentObjectStreamClass);
}
if (dump)
dumpElementln ("WRITE FIELDS CALLED FOR: " + obj);
writeFields(obj, currentObjectStreamClass);
}
}
this.currentObject = prevObject;

View file

@ -42,13 +42,15 @@ enum
JV_STATE_PRELOADING = 1, // Can do _Jv_FindClass.
JV_STATE_LOADING = 3, // Has super installed.
JV_STATE_COMPILED = 5, // This was a compiled class.
JV_STATE_READ = 4, // Has been completely defined.
JV_STATE_LOADED = 5, // Has Miranda methods defined.
JV_STATE_COMPILED = 6, // This was a compiled class.
JV_STATE_LOADED = 6, // Is complete.
JV_STATE_PREPARED = 7, // Layout & static init done.
JV_STATE_LINKED = 9, // Strings interned.
JV_STATE_IN_PROGRESS = 10, // <Clinit> running.
JV_STATE_IN_PROGRESS = 10, // <clinit> running.
JV_STATE_ERROR = 12,
@ -59,6 +61,9 @@ struct _Jv_Field;
struct _Jv_VTable;
union _Jv_word;
struct _Jv_ArrayVTable;
class _Jv_ExecutionEngine;
class _Jv_CompiledEngine;
class _Jv_InterpreterEngine;
struct _Jv_Constants
{
@ -106,7 +111,7 @@ union _Jv_IDispatchTable
} iface;
};
// Used by _Jv_GetInterfaces ()
// Used by _Jv_Linker::get_interfaces ()
struct _Jv_ifaces
{
jclass *list;
@ -139,6 +144,23 @@ struct _Jv_CatchClass
_Jv_Utf8Const *classname;
};
// Possible values for the assertion_code field in the type assertion table.
enum
{
JV_ASSERT_END_OF_TABLE = 0,
JV_ASSERT_TYPES_COMPATIBLE = 1,
JV_ASSERT_IS_INSTANTIABLE = 2
};
// Entry in the type assertion table, used to validate type constraints
// for binary compatibility.
struct _Jv_TypeAssertion
{
jint assertion_code;
_Jv_Utf8Const *op1;
_Jv_Utf8Const *op2;
};
#define JV_PRIMITIVE_VTABLE ((_Jv_VTable *) -1)
#define JV_CLASS(Obj) ((jclass) (*(_Jv_VTable **) Obj)->clas)
@ -149,11 +171,11 @@ struct _Jv_CatchClass
_Jv_Method *_Jv_GetMethodLocal (jclass klass, _Jv_Utf8Const *name,
_Jv_Utf8Const *signature);
jboolean _Jv_IsAssignableFrom (jclass, jclass);
jboolean _Jv_IsAssignableFromSlow (jclass, jclass);
jboolean _Jv_InterfaceAssignableFrom (jclass, jclass);
void _Jv_InitClass (jclass klass);
_Jv_Method* _Jv_LookupDeclaredMethod (jclass, _Jv_Utf8Const *,
_Jv_Utf8Const*);
_Jv_Utf8Const*, jclass * = NULL);
jfieldID JvGetFirstInstanceField (jclass);
jint JvNumInstanceFields (jclass);
jfieldID JvGetFirstStaticField (jclass);
@ -183,10 +205,6 @@ class java::io::ObjectOutputStream;
class java::io::ObjectInputStream;
class java::io::ObjectStreamClass;
void _Jv_WaitForState (jclass, int);
void _Jv_RegisterClasses (const jclass *classes);
void _Jv_RegisterClasses_Counted (const jclass *classes,
size_t count);
void _Jv_RegisterClassHookDefault (jclass klass);
void _Jv_RegisterInitiatingLoader (jclass,java::lang::ClassLoader*);
void _Jv_UnregisterClass (jclass);
@ -205,19 +223,7 @@ void _Jv_InitNewClassFields (jclass klass);
// Friend functions and classes in prims.cc
void _Jv_InitPrimClass (jclass, char *, char, int);
void _Jv_PrepareCompiledClass (jclass);
void _Jv_PrepareConstantTimeTables (jclass);
jshort _Jv_GetInterfaces (jclass, _Jv_ifaces *);
void _Jv_GenerateITable (jclass, _Jv_ifaces *, jshort *);
jstring _Jv_GetMethodString (jclass, _Jv_Utf8Const *);
jshort _Jv_AppendPartialITable (jclass, jclass, void **, jshort);
jshort _Jv_FindIIndex (jclass *, jshort *, jshort);
void _Jv_LinkSymbolTable (jclass);
void _Jv_LayoutInterfaceMethods (jclass);
void _Jv_LayoutVTableMethods (jclass klass);
void _Jv_SetVTableEntries (jclass, _Jv_VTable *, jboolean *);
void _Jv_MakeVTable (jclass);
void _Jv_linkExceptionClassTable (jclass);
jboolean _Jv_CheckAccess (jclass self_klass, jclass other_klass,
jint flags);
@ -225,25 +231,14 @@ jclass _Jv_GetArrayClass (jclass klass, java::lang::ClassLoader *loader);
#ifdef INTERPRETER
jboolean _Jv_IsInterpretedClass (jclass);
void _Jv_InitField (jobject, jclass, _Jv_Field*);
void _Jv_InitField (jobject, jclass, int);
_Jv_word _Jv_ResolvePoolEntry (jclass, int);
_Jv_Method *_Jv_SearchMethodInClass (jclass cls, jclass klass,
_Jv_Utf8Const *method_name,
_Jv_Utf8Const *method_signature);
void _Jv_PrepareClass (jclass);
void _Jv_PrepareMissingMethods (jclass base, jclass iface_class);
void _Jv_Defer_Resolution (void *cl, _Jv_Method *meth, void **);
class _Jv_ClassReader;
class _Jv_InterpClass;
class _Jv_InterpMethod;
#endif
class _Jv_BytecodeVerifier;
class _Jv_StackTrace;
class gnu::gcj::runtime::StackTrace;
class java::io::VMObjectStreamClass;
@ -316,9 +311,14 @@ public:
void setSigners(JArray<jobject> *);
inline jclass getSuperclass (void)
{
return superclass;
}
{
return superclass;
}
inline jclass getInterface (jint n)
{
return interfaces[n];
}
inline jboolean isArray (void)
{
@ -351,9 +351,16 @@ public:
// FIXME: this probably shouldn't be public.
jint size (void)
{
return size_in_bytes;
}
{
return size_in_bytes;
}
// The index of the first method we declare ourself (as opposed to
// inheriting).
inline jint firstMethodIndex (void)
{
return vtable_method_count - method_count;
}
// finalization
void finalize ();
@ -372,10 +379,17 @@ private:
static jstring getPackagePortion (jstring);
void set_state (jint nstate)
{
state = nstate;
notifyAll ();
}
// Friend functions implemented in natClass.cc.
friend _Jv_Method *::_Jv_GetMethodLocal (jclass klass, _Jv_Utf8Const *name,
_Jv_Utf8Const *signature);
friend jboolean (::_Jv_IsAssignableFrom) (jclass, jclass);
friend jboolean (::_Jv_IsAssignableFromSlow) (jclass, jclass);
friend jboolean (::_Jv_InterfaceAssignableFrom) (jclass, jclass);
friend void *::_Jv_LookupInterfaceMethodIdx (jclass klass, jclass iface,
int method_idx);
@ -383,7 +397,7 @@ private:
friend void ::_Jv_InitClass (jclass klass);
friend _Jv_Method* ::_Jv_LookupDeclaredMethod (jclass, _Jv_Utf8Const *,
_Jv_Utf8Const*);
_Jv_Utf8Const*, jclass *);
friend jfieldID (::JvGetFirstInstanceField) (jclass);
friend jint (::JvNumInstanceFields) (jclass);
friend jfieldID (::JvGetFirstStaticField) (jclass);
@ -413,7 +427,6 @@ private:
friend class java::io::ObjectInputStream;
friend class java::io::ObjectStreamClass;
friend void ::_Jv_WaitForState (jclass, int);
friend void ::_Jv_RegisterClasses (const jclass *classes);
friend void ::_Jv_RegisterClasses_Counted (const jclass *classes,
size_t count);
@ -436,40 +449,22 @@ private:
// in prims.cc
friend void ::_Jv_InitPrimClass (jclass, char *, char, int);
friend void ::_Jv_PrepareCompiledClass (jclass);
friend void ::_Jv_PrepareConstantTimeTables (jclass);
friend jshort (::_Jv_GetInterfaces) (jclass, _Jv_ifaces *);
friend void ::_Jv_GenerateITable (jclass, _Jv_ifaces *, jshort *);
friend jstring (::_Jv_GetMethodString) (jclass, _Jv_Utf8Const *);
friend jshort (::_Jv_AppendPartialITable) (jclass, jclass, void **, jshort);
friend jshort (::_Jv_FindIIndex) (jclass *, jshort *, jshort);
friend void ::_Jv_LinkSymbolTable (jclass);
friend void ::_Jv_LayoutInterfaceMethods (jclass);
friend void ::_Jv_LayoutVTableMethods (jclass klass);
friend void ::_Jv_SetVTableEntries (jclass, _Jv_VTable *, jboolean *);
friend void ::_Jv_MakeVTable (jclass);
friend void ::_Jv_linkExceptionClassTable (jclass);
friend jboolean (::_Jv_CheckAccess) (jclass self_klass, jclass other_klass,
jint flags);
friend bool _Jv_getInterfaceMethod(jclass, jclass&, int&,
const _Jv_Utf8Const*,
const _Jv_Utf8Const*);
friend jclass (::_Jv_GetArrayClass) (jclass klass,
java::lang::ClassLoader *loader);
#ifdef INTERPRETER
friend jboolean (::_Jv_IsInterpretedClass) (jclass);
friend void ::_Jv_InitField (jobject, jclass, _Jv_Field*);
friend void ::_Jv_InitField (jobject, jclass, int);
friend _Jv_word (::_Jv_ResolvePoolEntry) (jclass, int);
friend _Jv_Method *::_Jv_SearchMethodInClass (jclass cls, jclass klass,
_Jv_Utf8Const *method_name,
_Jv_Utf8Const *method_signature);
friend void ::_Jv_PrepareClass (jclass);
friend void ::_Jv_PrepareMissingMethods (jclass base, jclass iface_class);
friend void ::_Jv_Defer_Resolution (void *cl, _Jv_Method *meth, void **);
friend class ::_Jv_ClassReader;
friend class ::_Jv_InterpClass;
friend class ::_Jv_InterpMethod;
@ -480,10 +475,14 @@ private:
#endif
friend class ::_Jv_BytecodeVerifier;
friend class ::_Jv_StackTrace;
friend class gnu::gcj::runtime::StackTrace;
friend class java::io::VMObjectStreamClass;
friend class _Jv_Linker;
friend class _Jv_ExecutionEngine;
friend class _Jv_CompiledEngine;
friend class _Jv_InterpreterEngine;
friend void ::_Jv_sharedlib_register_hook (jclass klass);
// Chain for class pool.
@ -518,8 +517,12 @@ private:
_Jv_OffsetTable *otable;
// Offset table symbols.
_Jv_MethodSymbol *otable_syms;
// Address table
_Jv_AddressTable *atable;
_Jv_MethodSymbol *atable_syms;
// Interface table
_Jv_AddressTable *itable;
_Jv_MethodSymbol *itable_syms;
_Jv_CatchClass *catch_classes;
// Interfaces implemented by this class.
jclass *interfaces;
@ -542,13 +545,17 @@ private:
jclass arrayclass;
// Security Domain to which this class belongs (or null).
java::security::ProtectionDomain *protectionDomain;
// Pointer to the type assertion table for this class.
_Jv_TypeAssertion *assertion_table;
// Signers of this class (or null).
JArray<jobject> *hack_signers;
// Used by Jv_PopClass and _Jv_PushClass to communicate with StackTrace.
jclass chain;
// Additional data, specific to the generator (JIT, native, interpreter) of this
// class.
// Additional data, specific to the generator (JIT, native,
// interpreter) of this class.
void *aux_info;
// Execution engine.
_Jv_ExecutionEngine *engine;
};
// Inline functions that are friends of java::lang::Class

View file

@ -288,6 +288,8 @@ public abstract class ClassLoader
if (c != null)
return c;
ClassNotFoundException ex = null;
// Can the class be loaded by a parent?
try
{
@ -304,9 +306,20 @@ public abstract class ClassLoader
}
catch (ClassNotFoundException e)
{
ex = e;
}
// Still not found, we have to do it ourself.
c = findClass(name);
try
{
c = findClass(name);
}
catch (ClassNotFoundException cause)
{
if (ex != null)
throw new ClassNotFoundException(ex.toString(), cause);
else
throw cause;
}
if (resolve)
resolveClass(c);
return c;
@ -435,8 +448,9 @@ public abstract class ClassLoader
domain = defaultProtectionDomain;
if (! initialized)
throw new SecurityException("attempt to define class from uninitialized class loader");
Class retval = VMClassLoader.defineClass(this, name, data,
offset, len, domain);
offset, len, domain);
loadedClasses.put(retval.getName(), retval);
return retval;
}

View file

@ -1,5 +1,5 @@
/* Compiler.java -- placeholder for Java-to-native runtime compilers
Copyright (C) 1998, 1999, 2001, 2002 Free Software Foundation, Inc.
Copyright (C) 1998, 1999, 2001, 2002, 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@ -76,8 +76,7 @@ public final class Compiler
*/
public static boolean compileClass(Class oneClass)
{
// Never succeed.
return false;
return VMCompiler.compileClass(oneClass);
}
/**
@ -90,8 +89,7 @@ public final class Compiler
*/
public static boolean compileClasses(String classNames)
{
// Note the incredibly lame interface. Always fail.
return false;
return VMCompiler.compileClasses(classNames);
}
/**
@ -105,8 +103,7 @@ public final class Compiler
*/
public static Object command(Object arg)
{
// Our implementation defines this to a no-op.
return null;
return VMCompiler.command(arg);
}
/**
@ -116,6 +113,7 @@ public final class Compiler
*/
public static void enable()
{
VMCompiler.enable();
}
/**
@ -124,5 +122,6 @@ public final class Compiler
*/
public static void disable()
{
VMCompiler.disable();
}
}

View file

@ -324,7 +324,7 @@ public class SecurityManager
public void checkPermission(Permission perm)
{
// XXX Should be: AccessController.checkPermission(perm);
throw new SecurityException("Operation not allowed");
//.throw new SecurityException("Operation not allowed");
}
/**
@ -553,7 +553,7 @@ public class SecurityManager
// throw new SecurityException("Missing context");
// AccessControlContext ac = (AccessControlContext) context;
// ac.checkPermission(new FilePermission(filename, "read"));
throw new SecurityException("Cannot read files via file names.");
// throw new SecurityException("Cannot read files via file names.");
}
/**
@ -677,7 +677,7 @@ public class SecurityManager
// // Use the toString() hack to do the null check.
// ac.checkPermission(new SocketPermission(host.toString + ":" +port,
// "connect"));
throw new SecurityException("Cannot make network connections.");
// throw new SecurityException("Cannot make network connections.");
}
/**

View file

@ -97,44 +97,31 @@ final class VMClassLoader
ProtectionDomain pd)
throws ClassFormatError;
static final native void linkClass0 (Class klass);
static final native void markClassErrorState0 (Class klass);
/**
* Helper to resolve all references to other classes from this class.
*
* @param c the class to resolve
*/
static final void resolveClass(Class clazz)
{
synchronized (clazz)
{
try
{
linkClass0 (clazz);
}
catch (Throwable x)
{
markClassErrorState0 (clazz);
static final native void resolveClass(Class clazz);
LinkageError e;
if (x instanceof LinkageError)
e = (LinkageError) x;
else if (x instanceof ClassNotFoundException)
{
e = new NoClassDefFoundError("while resolving class: "
+ clazz.getName());
e.initCause (x);
}
else
{
e = new LinkageError ("unexpected exception during linking: "
+ clazz.getName());
e.initCause (x);
}
throw e;
}
static final void transformException(Class clazz, Throwable x)
{
LinkageError e;
if (x instanceof LinkageError)
e = (LinkageError) x;
else if (x instanceof ClassNotFoundException)
{
e = new NoClassDefFoundError("while resolving class: "
+ clazz.getName());
e.initCause (x);
}
else
{
e = new LinkageError ("unexpected exception during linking: "
+ clazz.getName());
e.initCause (x);
}
throw e;
}
/**

View file

@ -0,0 +1,332 @@
/* VMClassLoader.java -- Reference implementation of compiler interface
Copyright (C) 2004 Free Software Foundation
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.lang;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.security.MessageDigest;
import java.security.ProtectionDomain;
import java.security.NoSuchAlgorithmException;
import java.util.WeakHashMap;
import java.util.HashSet;
import java.util.Enumeration;
import java.util.StringTokenizer;
import java.util.Vector;
import gnu.gcj.runtime.SharedLibHelper;
import gnu.gcj.runtime.PersistentByteMap;
/**
* This class is just a per-VM reflection of java.lang.Compiler.
* All methods are defined identically.
*/
final class VMCompiler
{
// True if we want to use gcj-jit.
public static boolean useCompiler = true;
// True if we're able to use gcj-jit.
public static final boolean canUseCompiler;
// Compiler to use.
public static String gcjJitCompiler;
// Compiler options.
public static String gcjJitCompilerOptions;
// Temporary directory to use.
public static String gcjJitTmpdir;
// This maps a ClassLoader to a set of SharedLibHelper objects that
// it has used. We do things this way to ensure that a
// SharedLibHelper is collected if and only if the ClassLoader is.
private static WeakHashMap sharedHelperMap = new WeakHashMap();
private static Vector precompiledMapFiles;
static
{
gcjJitCompiler = System.getProperty("gnu.gcj.jit.compiler");
if (gcjJitCompiler == null)
canUseCompiler = false;
else
{
gcjJitCompilerOptions = System.getProperty("gnu.gcj.jit.options",
"-g");
gcjJitTmpdir = System.getProperty("gnu.gcj.jit.cachedir");
// Note that we *don't* choose java.io.tmpdir as a default --
// that would allow easy attacks against the VM.
if (gcjJitTmpdir == null)
canUseCompiler = false;
else
canUseCompiler = true;
}
String prop = System.getProperty ("gnu.gcj.precompiled.db.path");
if (prop != null)
{
precompiledMapFiles = new Vector();
// Add the
StringTokenizer st
= new StringTokenizer (prop,
System.getProperty ("path.separator", ":"));
{
while (st.hasMoreElements ())
{
String e = st.nextToken ();
try
{
PersistentByteMap map
= new PersistentByteMap
(e, PersistentByteMap.AccessMode.READ_ONLY);
precompiledMapFiles.add(map);
}
catch (IllegalArgumentException _)
{
// Not a map file
}
catch (java.io.IOException _)
{
}
}
}
}
}
/**
* Don't allow new `Compiler's to be made.
*/
private VMCompiler()
{
}
private static Class loadSharedLibrary(ClassLoader loader,
String fileName,
ProtectionDomain domain,
String className)
{
Class c = null;
SharedLibHelper helper
= SharedLibHelper.findHelper (loader, fileName, domain.getCodeSource());
c = helper.findClass (className);
if (c != null)
{
HashSet hs = (HashSet) sharedHelperMap.get(loader);
if (hs == null)
{
hs = new HashSet();
sharedHelperMap.put(loader, hs);
}
hs.add(helper);
}
return c;
}
/**
* Compile a class given the bytes for it. Returns the Class, or
* null if compilation failed or otherwise could not be done.
*/
public static Class compileClass(ClassLoader loader,
String name, byte[] data,
int offset, int len,
ProtectionDomain domain)
{
if (precompiledMapFiles == null
&& (! useCompiler || ! canUseCompiler))
return null;
byte digest[];
try
{
MessageDigest md = MessageDigest.getInstance("MD5");
digest = md.digest(data);
}
catch (NoSuchAlgorithmException _)
{
return null;
}
// We use lookaside cache files to determine whether these bytes
// correspond to a class file that is part of a precompiled DSO.
if (precompiledMapFiles != null)
{
try
{
Enumeration elements = precompiledMapFiles.elements();
while (elements.hasMoreElements())
{
PersistentByteMap map = (PersistentByteMap)elements.nextElement();
byte[] soName = map.get(digest);
if (soName != null)
return loadSharedLibrary(loader,
new String(soName),
domain, name);
}
}
catch (Exception _)
{
}
}
if (! useCompiler || ! canUseCompiler)
return null;
try
{
// FIXME: Make sure that the class represented by the
// bytes in DATA really is the class named in NAME. Make
// sure it's not "java.*".
StringBuffer hexBytes = new StringBuffer(gcjJitTmpdir);
hexBytes.append(File.separatorChar);
int digestLength = digest.length;
for (int i = 0; i < digestLength; ++i)
hexBytes.append(Integer.toHexString(digest[i] & 0xff));
// FIXME: use System.mapLibraryName?
// I'm thinking we should use that, plus a class specified
// via a property that determines lookup policy.
File soFile = new File(hexBytes + ".so");
if (soFile.isFile())
return loadSharedLibrary (loader, soFile.toString(), domain,
name);
File classFile = new File(hexBytes + ".class");
classFile.delete();
if (classFile.createNewFile() != true)
return null;
FileOutputStream f = new FileOutputStream (classFile);
// FIXME: race condition if bytes change... ?
f.write(data, offset, len);
// Invoke the compiler.
StringBuffer command = new StringBuffer(gcjJitCompiler);
command.append(" ");
command.append(classFile);
command.append(" ");
command.append(gcjJitCompilerOptions);
// These options are required.
command.append(" -findirect-dispatch -fjni -shared -fPIC -o ");
command.append(soFile);
Process p = Runtime.getRuntime().exec(command.toString());
// Read the process' stderr into a string.
StringBuffer err = new StringBuffer();
InputStreamReader stderr = new InputStreamReader (p.getErrorStream());
char[] inBuf = new char[500];
int bytesRead;
while ((bytesRead = stderr.read (inBuf)) != -1)
err.append(inBuf, 0, bytesRead);
if (p.waitFor() != 0)
{
// FIXME: we could log err.toString() somewhere...
return null;
}
return loadSharedLibrary(loader, soFile.toString(), domain, name);
}
catch (Exception _)
{
return null;
}
}
/**
* Compile the class named by <code>oneClass</code>.
*
* @param oneClass the class to compile
* @return <code>false</code> if no compiler is available or
* compilation failed, <code>true</code> if compilation succeeded
* @throws NullPointerException if oneClass is null
*/
public static boolean compileClass(Class oneClass)
{
// Never succeed.
return false;
}
/**
* Compile the classes whose name matches <code>classNames</code>.
*
* @param classNames the name of classes to compile
* @return <code>false</code> if no compiler is available or
* compilation failed, <code>true</code> if compilation succeeded
* @throws NullPointerException if classNames is null
*/
public static boolean compileClasses(String classNames)
{
// Note the incredibly lame interface. Always fail.
return false;
}
/**
* This method examines the argument and performs an operation
* according to the compilers documentation. No specific operation
* is required.
*
* @param arg a compiler-specific argument
* @return a compiler-specific value, including null
* @throws NullPointerException if the compiler doesn't like a null arg
*/
public static Object command(Object arg)
{
// Our implementation defines this to a no-op.
return null;
}
/**
* Calling <code>Compiler.enable()</code> will cause the compiler
* to resume operation if it was previously disabled; provided that a
* compiler even exists.
*/
public static void enable()
{
useCompiler = true;
}
/**
* Calling <code>Compiler.disable()</code> will cause the compiler
* to be suspended; provided that a compiler even exists.
*/
public static void disable()
{
useCompiler = false;
}
}

View file

@ -54,11 +54,12 @@ class VMSecurityManager
// The docs above are wrong. See the online docs.
// FIXME this implementation is a bit wrong too -- the docs say we
// must also consider ancestors of the system class loader.
ClassLoader systemClassLoader = VMClassLoader.getSystemClassLoader();
Class[] classStack = getClassContext ();
for (int i = 0; i < classStack.length; i++)
{
ClassLoader loader = classStack[i].getClassLoader();
if (loader != null)
if (loader != null && loader != systemClassLoader)
return loader;
}

File diff suppressed because it is too large Load diff

View file

@ -18,6 +18,7 @@ details. */
#include <gcj/cni.h>
#include <jvm.h>
#include <execution.h>
#include <java-threads.h>
#include <java-interp.h>
@ -33,6 +34,7 @@ details. */
#include <java/lang/ClassNotFoundException.h>
#include <java/lang/ClassCircularityError.h>
#include <java/lang/IncompatibleClassChangeError.h>
#include <java/lang/ClassFormatError.h>
#include <java/lang/VirtualMachineError.h>
#include <java/lang/VMClassLoader.h>
#include <java/lang/reflect/Modifier.h>
@ -41,156 +43,6 @@ details. */
#include <java/io/Serializable.h>
#include <java/lang/Cloneable.h>
void
_Jv_WaitForState (jclass klass, int state)
{
if (klass->state >= state)
return;
_Jv_MonitorEnter (klass) ;
if (klass->state == JV_STATE_COMPILED)
{
klass->state = JV_STATE_LOADED;
if (gcj::verbose_class_flag)
fprintf (stderr, "[Loaded (pre-compiled) %s]\n", klass->name->chars());
}
if (state == JV_STATE_LINKED)
{
// Must call _Jv_PrepareCompiledClass while holding the class
// mutex.
#ifdef INTERPRETER
if (_Jv_IsInterpretedClass (klass))
_Jv_PrepareClass (klass);
#endif
_Jv_PrepareCompiledClass (klass);
_Jv_MonitorExit (klass);
return;
}
java::lang::Thread *self = java::lang::Thread::currentThread();
// this is similar to the strategy for class initialization.
// if we already hold the lock, just leave.
while (klass->state <= state
&& klass->thread
&& klass->thread != self)
klass->wait ();
_Jv_MonitorExit (klass);
if (klass->state == JV_STATE_ERROR)
throw new java::lang::LinkageError;
}
typedef unsigned int uaddr __attribute__ ((mode (pointer)));
/** This function does class-preparation for compiled classes.
NOTE: It contains replicated functionality from
_Jv_ResolvePoolEntry, and this is intentional, since that function
lives in resolve.cc which is entirely conditionally compiled.
*/
void
_Jv_PrepareCompiledClass (jclass klass)
{
jint state = klass->state;
if (state >= JV_STATE_LINKED)
return;
// Short-circuit, so that mutually dependent classes are ok.
klass->state = JV_STATE_LINKED;
_Jv_Constants *pool = &klass->constants;
// Resolve class constants first, since other constant pool
// entries may rely on these.
for (int index = 1; index < pool->size; ++index)
{
if (pool->tags[index] == JV_CONSTANT_Class)
{
_Jv_Utf8Const *name = pool->data[index].utf8;
jclass found;
if (name->first() == '[')
found = _Jv_FindClassFromSignature (name->chars(),
klass->loader);
else
found = _Jv_FindClass (name, klass->loader);
if (! found)
{
jstring str = name->toString();
throw new java::lang::NoClassDefFoundError (str);
}
pool->data[index].clazz = found;
pool->tags[index] |= JV_CONSTANT_ResolvedFlag;
}
}
// If superclass looks like a constant pool entry,
// resolve it now.
if ((uaddr) klass->superclass < pool->size)
klass->superclass = pool->data[(uaddr) klass->superclass].clazz;
// Likewise for interfaces.
for (int i = 0; i < klass->interface_count; i++)
if ((uaddr) klass->interfaces[i] < pool->size)
klass->interfaces[i] = pool->data[(uaddr) klass->interfaces[i]].clazz;
// Resolve the remaining constant pool entries.
for (int index = 1; index < pool->size; ++index)
{
if (pool->tags[index] == JV_CONSTANT_String)
{
jstring str;
str = _Jv_NewStringUtf8Const (pool->data[index].utf8);
pool->data[index].o = str;
pool->tags[index] |= JV_CONSTANT_ResolvedFlag;
}
}
#ifdef INTERPRETER
// FIXME: although the comment up top says that this function is
// only called for compiled classes, it is actually called for every
// class.
if (! _Jv_IsInterpretedClass (klass))
{
#endif /* INTERPRETER */
jfieldID f = JvGetFirstStaticField (klass);
for (int n = JvNumStaticFields (klass); n > 0; --n)
{
int mod = f->getModifiers ();
// If we have a static String field with a non-null initial
// value, we know it points to a Utf8Const.
_Jv_ResolveField(f, klass->loader);
if (f->getClass () == &java::lang::String::class$
&& java::lang::reflect::Modifier::isStatic (mod))
{
jstring *strp = (jstring *) f->u.addr;
if (*strp)
*strp = _Jv_NewStringUtf8Const ((_Jv_Utf8Const *) *strp);
}
f = f->getNextField ();
}
#ifdef INTERPRETER
}
#endif /* INTERPRETER */
if (klass->isInterface ())
_Jv_LayoutInterfaceMethods (klass);
if (state == JV_STATE_COMPILED && gcj::verbose_class_flag)
fprintf (stderr, "[Loaded (pre-compiled) %s]\n",
klass->name->chars());
klass->notifyAll ();
_Jv_PushClass (klass);
}
//
// A single class can have many "initiating" class loaders,
// and a single "defining" class loader. The Defining
@ -221,6 +73,8 @@ static _Jv_LoaderInfo *initiated_classes[HASH_LEN];
static jclass loaded_classes[HASH_LEN];
// This is the root of a linked list of classes
static jclass stack_head;
@ -323,11 +177,6 @@ _Jv_RegisterClasses (const jclass *classes)
jclass klass = *classes;
(*_Jv_RegisterClassHook) (klass);
// registering a compiled class causes
// it to be immediately "prepared".
if (klass->state == JV_STATE_NOTHING)
klass->state = JV_STATE_COMPILED;
}
}
@ -341,11 +190,6 @@ _Jv_RegisterClasses_Counted (const jclass * classes, size_t count)
jclass klass = classes[i];
(*_Jv_RegisterClassHook) (klass);
// registering a compiled class causes
// it to be immediately "prepared".
if (klass->state == JV_STATE_NOTHING)
klass->state = JV_STATE_COMPILED;
}
}
@ -354,8 +198,10 @@ _Jv_RegisterClassHookDefault (jclass klass)
{
jint hash = HASH_UTF (klass->name);
jclass check_class = loaded_classes[hash];
// The BC ABI makes this check unnecessary: we always resolve all
// data references via the appropriate class loader, so the kludge
// that required this check has gone.
#if 0
// If the class is already registered, don't re-register it.
while (check_class != NULL)
{
@ -381,7 +227,11 @@ _Jv_RegisterClassHookDefault (jclass klass)
check_class = check_class->next;
}
#endif
// FIXME: this is really bogus!
if (! klass->engine)
klass->engine = &_Jv_soleCompiledEngine;
klass->next = loaded_classes[hash];
loaded_classes[hash] = klass;
}
@ -442,7 +292,7 @@ _Jv_FindClass (_Jv_Utf8Const *name, java::lang::ClassLoader *loader)
{
// we need classes to be in the hash while
// we're loading, so that they can refer to themselves.
_Jv_WaitForState (klass, JV_STATE_LOADED);
_Jv_Linker::wait_for_state (klass, JV_STATE_LOADED);
}
return klass;
@ -555,7 +405,7 @@ _Jv_NewArrayClass (jclass element, java::lang::ClassLoader *loader,
// cache one and reuse it. It is not necessary to synchronize this.
if (!array_idt)
{
_Jv_PrepareConstantTimeTables (array_class);
_Jv_Linker::wait_for_state(array_class, JV_STATE_PREPARED);
array_idt = array_class->idt;
array_depth = array_class->depth;
array_ancestors = array_class->ancestors;
@ -569,19 +419,19 @@ _Jv_NewArrayClass (jclass element, java::lang::ClassLoader *loader,
using namespace java::lang::reflect;
{
// Array classes are "abstract final"...
_Jv_ushort accflags = Modifier::FINAL | Modifier::ABSTRACT;
// ... and inherit accessibility from element type, per vmspec 5.3.3.2
accflags |= (element->accflags & Modifier::PUBLIC);
accflags |= (element->accflags & Modifier::PROTECTED);
accflags |= (element->accflags & Modifier::PRIVATE);
// Array classes are "abstract final" and inherit accessibility
// from element type, per vmspec 5.3.3.2
_Jv_ushort accflags = (Modifier::FINAL | Modifier::ABSTRACT
| (element->accflags
& (Modifier::PUBLIC | Modifier::PROTECTED
| Modifier::PRIVATE)));
array_class->accflags = accflags;
}
// An array class has no visible instance fields. "length" is invisible to
// reflection.
// say this class is initialized and ready to go!
// Say this class is initialized and ready to go!
array_class->state = JV_STATE_DONE;
// vmspec, section 5.3.3 describes this
@ -591,8 +441,6 @@ _Jv_NewArrayClass (jclass element, java::lang::ClassLoader *loader,
element->arrayclass = array_class;
}
static jclass stack_head;
// These two functions form a stack of classes. When a class is loaded
// it is pushed onto the stack by the class loader; this is so that
// StackTrace can quickly determine which classes have been loaded.

View file

@ -1,6 +1,6 @@
// natRuntime.cc - Implementation of native side of Runtime class.
/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation
/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation
This file is part of libgcj.
@ -388,8 +388,11 @@ java::lang::Runtime::insertSystemProperties (java::util::Properties *newprops)
newprops->put(JvNewStringLatin1 (Prop), JvNewStringLatin1 (Val))
// A mixture of the Java Product Versioning Specification
// (introduced in 1.2), and earlier versioning properties.
SET ("java.version", GCJVERSION);
// (introduced in 1.2), and earlier versioning properties. Some
// programs rely on seeing values that they expect, so we claim to
// be a 1.4-ish VM for their sake.
SET ("java.version", "1.4.2");
SET ("java.runtime.version", "1.4.2");
SET ("java.vendor", "Free Software Foundation, Inc.");
SET ("java.vendor.url", "http://gcc.gnu.org/java/");
SET ("java.class.version", "46.0");
@ -399,7 +402,7 @@ java::lang::Runtime::insertSystemProperties (java::util::Properties *newprops)
SET ("java.vm.version", __VERSION__);
SET ("java.vm.vendor", "Free Software Foundation, Inc.");
SET ("java.vm.name", "GNU libgcj");
SET ("java.specification.version", "1.3");
SET ("java.specification.version", "1.4");
SET ("java.specification.name", "Java(tm) Platform API Specification");
SET ("java.specification.vendor", "Sun Microsystems Inc.");

View file

@ -1,7 +1,6 @@
// natString.cc - Implementation of java.lang.String native methods.
/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004
Free Software Foundation
/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation
This file is part of libgcj.
@ -57,7 +56,7 @@ static int strhash_size = 0; /* Number of slots available in strhash.
jstring*
_Jv_StringFindSlot (jchar* data, jint len, jint hash)
{
JvSynchronize sync (&StringClass);
JvSynchronize sync (&java::lang::String::class$);
int start_index = hash & (strhash_size - 1);
int deleted_index = -1;
@ -120,7 +119,7 @@ _Jv_StringGetSlot (jstring str)
static void
rehash ()
{
JvSynchronize sync (&StringClass);
JvSynchronize sync (&java::lang::String::class$);
if (strhash == NULL)
{
@ -167,7 +166,7 @@ rehash ()
jstring
java::lang::String::intern()
{
JvSynchronize sync (&StringClass);
JvSynchronize sync (&java::lang::String::class$);
if (3 * strhash_count >= 2 * strhash_size)
rehash();
jstring* ptr = _Jv_StringGetSlot(this);
@ -194,7 +193,7 @@ java::lang::String::intern()
void
_Jv_FinalizeString (jobject obj)
{
JvSynchronize sync (&StringClass);
JvSynchronize sync (&java::lang::String::class$);
// We might not actually have intern()d any strings at all, if
// we're being called from Reference.
@ -286,9 +285,9 @@ _Jv_NewStringUtf8Const (Utf8Const* str)
}
chrs -= length;
JvSynchronize sync (&StringClass);
JvSynchronize sync (&java::lang::String::class$);
if (3 * strhash_count >= 2 * strhash_size)
rehash ();
rehash();
jstring* ptr = _Jv_StringFindSlot (chrs, length, hash);
if (*ptr != NULL && *ptr != DELETED_STRING)
return (jstring) UNMASK_PTR (*ptr);
@ -527,7 +526,7 @@ java::lang::String::equals(jobject anObject)
return false;
if (anObject == this)
return true;
if (anObject->getClass() != &StringClass)
if (anObject->getClass() != &java::lang::String::class$)
return false;
jstring other = (jstring) anObject;
if (count != other->count)

View file

@ -22,6 +22,7 @@ details. */
#include <java-interp.h>
#include <java/lang/VMClassLoader.h>
#include <java/lang/VMCompiler.h>
#include <gnu/gcj/runtime/VMClassLoader.h>
#include <java/lang/ClassLoader.h>
#include <java/lang/Class.h>
@ -29,6 +30,21 @@ details. */
#include <java/security/ProtectionDomain.h>
#include <java/lang/ClassFormatError.h>
void
java::lang::VMClassLoader::resolveClass (jclass klass)
{
JvSynchronize sync (klass);
try
{
_Jv_Linker::wait_for_state (klass, JV_STATE_LINKED);
}
catch (java::lang::Throwable *x)
{
klass->set_state(JV_STATE_ERROR);
transformException(klass, x);
}
}
java::lang::Class *
java::lang::VMClassLoader::defineClass (java::lang::ClassLoader *loader,
jstring name,
@ -37,72 +53,61 @@ java::lang::VMClassLoader::defineClass (java::lang::ClassLoader *loader,
jint length,
java::security::ProtectionDomain *pd)
{
jclass klass = VMCompiler::compileClass(loader, name, data,
offset, length, pd);
if (klass != NULL)
{
JvSynchronize sync (&java::lang::Class::class$);
_Jv_RegisterClass (klass);
}
#ifdef INTERPRETER
jclass klass;
klass = new java::lang::Class ();
klass->aux_info = (void *) _Jv_AllocBytes (sizeof (_Jv_InterpClass));
// Synchronize on the class, so that it is not attempted initialized
// until we're done loading.
JvSynchronize sync (klass);
// Record the defining loader. For the system class loader, we
// record NULL.
if (loader != java::lang::ClassLoader::getSystemClassLoader())
klass->loader = loader;
if (name != 0)
else
{
_Jv_Utf8Const *name2 = _Jv_makeUtf8Const (name);
klass = new java::lang::Class ();
if (! _Jv_VerifyClassName (name2))
throw new java::lang::ClassFormatError
(JvNewStringLatin1 ("erroneous class name"));
// Synchronize on the class, so that it is not attempted initialized
// until we're done loading.
JvSynchronize sync (klass);
klass->name = name2;
// Record the defining loader. For the system class loader, we
// record NULL.
if (loader != java::lang::ClassLoader::getSystemClassLoader())
klass->loader = loader;
if (name != 0)
{
_Jv_Utf8Const *name2 = _Jv_makeUtf8Const (name);
if (! _Jv_VerifyClassName (name2))
throw new java::lang::ClassFormatError
(JvNewStringLatin1 ("erroneous class name"));
klass->name = name2;
}
try
{
_Jv_DefineClass (klass, data, offset, length, pd);
}
catch (java::lang::Throwable *ex)
{
klass->state = JV_STATE_ERROR;
klass->notifyAll ();
_Jv_UnregisterClass (klass);
// If EX is not a ClassNotFoundException, that's ok, because we
// account for the possibility in defineClass().
throw ex;
}
// if everything proceeded sucessfully, we're loaded.
JvAssert (klass->state == JV_STATE_LOADED);
}
try
{
_Jv_DefineClass (klass, data, offset, length);
}
catch (java::lang::Throwable *ex)
{
klass->state = JV_STATE_ERROR;
klass->notifyAll ();
_Jv_UnregisterClass (klass);
// If EX is not a ClassNotFoundException, that's ok, because we
// account for the possibility in defineClass().
throw ex;
}
klass->protectionDomain = pd;
// if everything proceeded sucessfully, we're loaded.
JvAssert (klass->state == JV_STATE_LOADED);
#endif // INTERPRETER
return klass;
#else // INTERPRETER
return 0;
#endif
}
// Finish linking a class. Only called from ClassLoader::resolveClass.
void
java::lang::VMClassLoader::linkClass0 (java::lang::Class *klass)
{
_Jv_WaitForState (klass, JV_STATE_LINKED);
}
void
java::lang::VMClassLoader::markClassErrorState0 (java::lang::Class *klass)
{
klass->state = JV_STATE_ERROR;
klass->notifyAll ();
}
java::lang::ClassLoader *
@ -125,9 +130,16 @@ jclass
java::lang::VMClassLoader::loadClass(jstring name, jboolean resolve)
{
_Jv_Utf8Const *utf = _Jv_makeUtf8Const (name);
// FIXME: we culd make _Jv_FindClassFromSignature a template.
jclass klass = _Jv_FindClassInCache (utf, NULL);
if (klass && resolve)
_Jv_InitClass (klass);
if (klass)
{
// We never want to return a class without its supers linked.
// It isn't clear from the spec, but this is what other
// implementations do in practice.
if (resolve)
_Jv_InitClass (klass);
else
_Jv_Linker::wait_for_state (klass, JV_STATE_LOADING);
}
return klass;
}

View file

@ -1,6 +1,6 @@
// natField.cc - Implementation of java.lang.reflect.Field native methods.
/* Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation
/* Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004 Free Software Foundation
This file is part of libgcj.
@ -47,7 +47,7 @@ java::lang::reflect::Field::getType ()
{
jfieldID fld = _Jv_FromReflectedField (this);
JvSynchronize sync (declaringClass);
_Jv_ResolveField (fld, declaringClass->getClassLoaderInternal ());
_Jv_Linker::resolve_field (fld, declaringClass->getClassLoaderInternal ());
return fld->type;
}

View file

@ -1,6 +1,6 @@
// natMethod.cc - Native code for Method class.
/* Copyright (C) 1998, 1999, 2000, 2001 , 2002, 2003 Free Software Foundation
/* Copyright (C) 1998, 1999, 2000, 2001 , 2002, 2003, 2004 Free Software Foundation
This file is part of libgcj.
@ -149,7 +149,6 @@ java::lang::reflect::Method::invoke (jobject obj, jobjectArray args)
getType ();
jmethodID meth = _Jv_FromReflectedMethod (this);
jclass objClass;
if (Modifier::isStatic(meth->accflags))
{
@ -157,12 +156,10 @@ java::lang::reflect::Method::invoke (jobject obj, jobjectArray args)
// here and not in _Jv_CallAnyMethodA because JNI initializes a
// class whenever a method lookup is done.
_Jv_InitClass (declaringClass);
objClass = declaringClass;
}
else
{
objClass = JV_CLASS (obj);
jclass objClass = JV_CLASS (obj);
if (! _Jv_IsAssignableFrom (declaringClass, objClass))
throw new java::lang::IllegalArgumentException;
}
@ -184,7 +181,7 @@ java::lang::reflect::Method::invoke (jobject obj, jobjectArray args)
{
}
if (! _Jv_CheckAccess(caller, objClass, meth->accflags))
if (! _Jv_CheckAccess(caller, declaringClass, meth->accflags))
throw new IllegalAccessException;
}

View file

@ -54,6 +54,8 @@ import java.security.SecureClassLoader;
import java.security.cert.Certificate;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.StringTokenizer;
import java.util.Vector;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
@ -144,9 +146,10 @@ public class URLClassLoader extends SecureClassLoader
private final Vector urls = new Vector();
/**
* Store pre-parsed information for each url into this vector
* each element is a URL loader, corresponding to the URL of
* the same index in "urls"
* Store pre-parsed information for each url into this vector: each
* element is a URL loader. A jar file has its own class-path
* attribute which adds to the URLs that will be searched, but this
* does not add to the list of urls.
*/
private final Vector urlinfos = new Vector();
@ -188,10 +191,15 @@ public class URLClassLoader extends SecureClassLoader
final CodeSource noCertCodeSource;
URLLoader(URLClassLoader classloader, URL baseURL)
{
this(classloader, baseURL, baseURL);
}
URLLoader(URLClassLoader classloader, URL baseURL, URL overrideURL)
{
this.classloader = classloader;
this.baseURL = baseURL;
this.noCertCodeSource = new CodeSource(baseURL, null);
this.noCertCodeSource = new CodeSource(overrideURL, null);
}
/**
@ -221,6 +229,11 @@ public class URLClassLoader extends SecureClassLoader
{
return null;
}
Vector getClassPath()
{
return null;
}
}
/**
@ -290,6 +303,10 @@ public class URLClassLoader extends SecureClassLoader
final JarFile jarfile; // The jar file for this url
final URL baseJarURL; // Base jar: url for all resources loaded from jar
Vector classPath; // The "Class-Path" attribute of this Jar's manifest
SoURLLoader soURLLoader;
public JarURLLoader(URLClassLoader classloader, URL baseURL)
{
super(classloader, baseURL);
@ -302,25 +319,87 @@ public class URLClassLoader extends SecureClassLoader
sb.append("!/");
String jarURL = sb.toString();
this.soURLLoader = null;
this.classPath = null;
URL baseJarURL = null;
JarFile jarfile = null;
try
{
baseJarURL =
new URL(null, jarURL, classloader.getURLStreamHandler("jar"));
{
baseJarURL
= new URL(null, jarURL, classloader.getURLStreamHandler("jar"));
jarfile
= ((JarURLConnection) baseJarURL.openConnection()).getJarFile();
jarfile =
((JarURLConnection) baseJarURL.openConnection()).getJarFile();
}
if (jarfile != null)
{
String fileName = baseURL.getFile();
if (fileName != null)
{
File f = new File(fileName);
String libDirName = f.getCanonicalFile().getParent()
+ File.separator + "GCJLIBS";
File libDir = new File(libDirName);
if (libDir != null && (libDir.isDirectory()))
{
File soFile = new File (libDirName
+ File.separator + f.getName()
+ ".so");
if (soFile != null && soFile.isFile())
this.soURLLoader
= new SoURLLoader (classloader, soFile.toURL(),
baseURL);
}
}
Manifest manifest;
Attributes attributes;
String classPathString;
if ((manifest = jarfile.getManifest()) != null
&& (attributes = manifest.getMainAttributes()) != null
&& ((classPathString
= attributes.getValue(Attributes.Name.CLASS_PATH))
!= null))
{
this.classPath = new Vector();
StringTokenizer st
= new StringTokenizer
(classPathString,
System.getProperty ("path.separator", ":"));
while (st.hasMoreElements ())
{
String e = st.nextToken ();
try
{
URL url = new URL(baseURL, e);
this.classPath.add(url);
}
catch (java.net.MalformedURLException xx)
{
// Give up
}
}
}
}
}
catch (IOException ioe)
{
/* ignored */
/* ignored */
}
this.baseJarURL = baseJarURL;
this.jarfile = jarfile;
}
Class getClass(String className)
{
if (soURLLoader != null)
return soURLLoader.getClass(className);
return null;
}
/** get resource with the name "name" in the jar url */
Resource getResource(String name)
{
@ -337,6 +416,11 @@ public class URLClassLoader extends SecureClassLoader
return null;
}
public String toString ()
{
return "jarfile " + jarfile.getName();
}
Manifest getManifest()
{
try
@ -348,6 +432,11 @@ public class URLClassLoader extends SecureClassLoader
return null;
}
}
Vector getClassPath()
{
return classPath;
}
}
static final class JarURLResource extends Resource
@ -486,7 +575,12 @@ public class URLClassLoader extends SecureClassLoader
SoURLLoader(URLClassLoader classloader, URL url)
{
super(classloader, url);
this(classloader, url, url);
}
SoURLLoader(URLClassLoader classloader, URL url, URL overrideURL)
{
super(classloader, url, overrideURL);
helper = SharedLibHelper.findHelper(classloader, url.getFile(),
noCertCodeSource);
}
@ -577,6 +671,11 @@ public class URLClassLoader extends SecureClassLoader
return (int) file.length();
}
public String toString ()
{
return "file " +file.getAbsolutePath();
}
public URL getURL()
{
try
@ -729,6 +828,7 @@ public class URLClassLoader extends SecureClassLoader
*/
protected void addURL(URL newUrl)
{
urls.add(newUrl);
addURLImpl(newUrl);
}
@ -761,8 +861,21 @@ public class URLClassLoader extends SecureClassLoader
urlloaders.put(newUrl, loader);
}
urls.add(newUrl);
urlinfos.add(loader);
urlinfos.add(loader);
Vector extraUrls = loader.getClassPath();
if (extraUrls != null)
{
Iterator it = extraUrls.iterator();
while (it.hasNext())
{
URL url = (URL)it.next();
URLLoader extraLoader = (URLLoader) urlloaders.get(url);
if (! urlinfos.contains (extraLoader))
addURLImpl(url);
}
}
}
}
@ -773,7 +886,7 @@ public class URLClassLoader extends SecureClassLoader
private void addURLs(URL[] newUrls)
{
for (int i = 0; i < newUrls.length; i++)
addURLImpl(newUrls[i]);
addURL(newUrls[i]);
}
/**
@ -830,7 +943,7 @@ public class URLClassLoader extends SecureClassLoader
{
// Just try to find the resource by the (almost) same name
String resourceName = className.replace('.', '/') + ".class";
int max = urls.size();
int max = urlinfos.size();
Resource resource = null;
for (int i = 0; i < max && resource == null; i++)
{
@ -939,7 +1052,7 @@ public class URLClassLoader extends SecureClassLoader
*/
private Resource findURLResource(String resourceName)
{
int max = urls.size();
int max = urlinfos.size();
for (int i = 0; i < max; i++)
{
URLLoader loader = (URLLoader) urlinfos.elementAt(i);
@ -1010,7 +1123,7 @@ public class URLClassLoader extends SecureClassLoader
throws IOException
{
Vector resources = new Vector();
int max = urls.size();
int max = urlinfos.size();
for (int i = 0; i < max; i++)
{
URLLoader loader = (URLLoader) urlinfos.elementAt(i);