ikvm-fork/runtime/ClassLoaderWrapper.cs

1216 строки
32 KiB
C#
Исходник Обычный вид История

2002-12-18 19:00:25 +03:00
/*
2006-01-02 11:15:43 +03:00
Copyright (C) 2002, 2003, 2004, 2005, 2006 Jeroen Frijters
2002-12-18 19:00:25 +03:00
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
Jeroen Frijters
jeroen@frijters.net
*/
using System;
using System.Reflection;
2005-12-07 12:06:32 +03:00
#if !COMPACT_FRAMEWORK
using System.Reflection.Emit;
#endif
2002-12-18 19:00:25 +03:00
using System.IO;
using System.Collections;
using System.Diagnostics;
2004-09-09 15:17:55 +04:00
using IKVM.Attributes;
using IKVM.Runtime;
2002-12-18 19:00:25 +03:00
2005-06-01 13:49:30 +04:00
namespace IKVM.Internal
2002-12-18 19:00:25 +03:00
{
2006-07-06 17:53:51 +04:00
abstract class TypeWrapperFactory
{
#if !COMPACT_FRAMEWORK
internal abstract ModuleBuilder ModuleBuilder { get; }
#endif
internal abstract TypeWrapper DefineClassImpl(Hashtable types, ClassFile f, object protectionDomain);
}
class ClassLoaderWrapper
2002-12-18 19:00:25 +03:00
{
2005-12-07 12:06:32 +03:00
private static readonly object wrapperLock = new object();
2005-09-06 12:06:04 +04:00
private static readonly Hashtable typeToTypeWrapper = Hashtable.Synchronized(new Hashtable());
2005-06-01 13:49:30 +04:00
private static ClassLoaderWrapper bootstrapClassLoader;
2006-05-15 13:08:01 +04:00
#if WHIDBEY && !STATIC_COMPILER
private static readonly Hashtable reflectionOnlyClassLoaders = new Hashtable();
2006-04-10 13:09:09 +04:00
#endif
2006-07-26 14:33:52 +04:00
private static ArrayList genericClassLoaders;
2006-06-28 12:07:29 +04:00
private readonly object javaClassLoader;
2006-02-22 17:44:07 +03:00
protected Hashtable types = new Hashtable();
2005-06-01 13:49:30 +04:00
private ArrayList nativeLibraries;
2006-07-06 17:53:51 +04:00
private TypeWrapperFactory factory;
2005-06-01 13:49:30 +04:00
private static Hashtable remappedTypes = new Hashtable();
2002-12-18 19:00:25 +03:00
2005-06-01 13:49:30 +04:00
// HACK this is used by the ahead-of-time compiler to overrule the bootstrap classloader
internal static void SetBootstrapClassLoader(ClassLoaderWrapper bootstrapClassLoader)
{
Debug.Assert(ClassLoaderWrapper.bootstrapClassLoader == null);
2002-12-18 19:00:25 +03:00
2005-06-01 13:49:30 +04:00
ClassLoaderWrapper.bootstrapClassLoader = bootstrapClassLoader;
}
2004-03-08 18:18:47 +03:00
2005-06-01 13:49:30 +04:00
static ClassLoaderWrapper()
{
typeToTypeWrapper[PrimitiveTypeWrapper.BOOLEAN.TypeAsTBD] = PrimitiveTypeWrapper.BOOLEAN;
typeToTypeWrapper[PrimitiveTypeWrapper.BYTE.TypeAsTBD] = PrimitiveTypeWrapper.BYTE;
typeToTypeWrapper[PrimitiveTypeWrapper.CHAR.TypeAsTBD] = PrimitiveTypeWrapper.CHAR;
typeToTypeWrapper[PrimitiveTypeWrapper.DOUBLE.TypeAsTBD] = PrimitiveTypeWrapper.DOUBLE;
typeToTypeWrapper[PrimitiveTypeWrapper.FLOAT.TypeAsTBD] = PrimitiveTypeWrapper.FLOAT;
typeToTypeWrapper[PrimitiveTypeWrapper.INT.TypeAsTBD] = PrimitiveTypeWrapper.INT;
typeToTypeWrapper[PrimitiveTypeWrapper.LONG.TypeAsTBD] = PrimitiveTypeWrapper.LONG;
typeToTypeWrapper[PrimitiveTypeWrapper.SHORT.TypeAsTBD] = PrimitiveTypeWrapper.SHORT;
typeToTypeWrapper[PrimitiveTypeWrapper.VOID.TypeAsTBD] = PrimitiveTypeWrapper.VOID;
LoadRemappedTypes();
}
2004-12-21 17:59:29 +03:00
2005-06-01 13:49:30 +04:00
internal static void LoadRemappedTypes()
2002-12-18 19:00:25 +03:00
{
2005-12-07 12:06:32 +03:00
// if we're compiling the core, coreAssembly will be null
Assembly coreAssembly = JVM.CoreAssembly;
if(coreAssembly != null)
2004-03-08 18:18:47 +03:00
{
2005-12-19 18:12:49 +03:00
Tracer.Info(Tracer.Runtime, "Core assembly: {0}", coreAssembly.Location);
2005-12-07 12:06:32 +03:00
RemappedClassAttribute[] remapped = AttributeHelper.GetRemappedClasses(coreAssembly);
2005-06-01 13:49:30 +04:00
if(remapped.Length > 0)
{
foreach(RemappedClassAttribute r in remapped)
{
Tracer.Info(Tracer.Runtime, "Remapping type {0} to {1}", r.RemappedType, r.Name);
remappedTypes.Add(r.RemappedType, r.Name);
}
}
else
2004-03-08 18:18:47 +03:00
{
2005-06-01 13:49:30 +04:00
JVM.CriticalFailure("Failed to find core classes in core library", null);
2004-03-08 18:18:47 +03:00
}
}
2002-12-18 19:00:25 +03:00
}
2004-03-08 18:18:47 +03:00
2006-06-26 13:04:03 +04:00
internal static int GetLoadedClassCount()
{
return typeToTypeWrapper.Count;
}
2005-06-01 13:49:30 +04:00
internal static bool IsCoreAssemblyType(Type type)
{
2005-12-07 12:06:32 +03:00
return type.Assembly == JVM.CoreAssembly;
2005-06-01 13:49:30 +04:00
}
2004-10-04 23:30:53 +04:00
2005-06-01 13:49:30 +04:00
internal ClassLoaderWrapper(object javaClassLoader)
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
this.javaClassLoader = javaClassLoader;
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
internal static bool IsRemappedType(Type type)
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
return remappedTypes.ContainsKey(type);
2004-08-17 13:05:21 +04:00
}
2002-12-18 19:00:25 +03:00
2005-06-01 13:49:30 +04:00
internal void SetRemappedType(Type type, TypeWrapper tw)
{
Debug.Assert(!types.ContainsKey(tw.Name));
types.Add(tw.Name, tw);
Debug.Assert(!typeToTypeWrapper.ContainsKey(type));
typeToTypeWrapper.Add(type, tw);
remappedTypes.Add(type, type);
}
2002-12-18 19:00:25 +03:00
2005-06-01 13:49:30 +04:00
// HACK return the TypeWrapper if it is already loaded
2005-07-25 18:34:22 +04:00
// (this exists solely for DynamicTypeWrapper.SetupGhosts and VMClassLoader.findLoadedClass)
2005-06-01 13:49:30 +04:00
internal TypeWrapper GetLoadedClass(string name)
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
lock(types.SyncRoot)
{
return (TypeWrapper)types[name];
}
2004-08-17 13:05:21 +04:00
}
2003-12-20 01:19:18 +03:00
2006-07-26 13:03:44 +04:00
internal TypeWrapper RegisterInitiatingLoader(TypeWrapper tw)
2005-07-27 19:57:55 +04:00
{
2006-07-11 15:34:44 +04:00
Debug.Assert(tw != null);
Debug.Assert(!tw.IsUnloadable);
Debug.Assert(!tw.IsPrimitive);
2005-07-27 19:57:55 +04:00
lock(types.SyncRoot)
{
object existing = types[tw.Name];
if(existing != tw)
{
if(existing != null)
{
2006-07-10 18:40:31 +04:00
// another thread beat us to it, discard the new TypeWrapper and
// return the previous one
return (TypeWrapper)existing;
2005-07-27 19:57:55 +04:00
}
// NOTE if types.ContainsKey(tw.Name) is true (i.e. the value is null),
// we currently have a DefineClass in progress on another thread and we've
// beaten that thread to the punch by loading the class from a parent class
// loader instead. This is ok as DefineClass will throw a LinkageError when
// it is done.
types[tw.Name] = tw;
}
}
return tw;
}
2006-07-06 17:53:51 +04:00
internal TypeWrapper DefineClass(ClassFile f, object protectionDomain)
{
string dotnetAssembly = f.IKVMAssemblyAttribute;
if(dotnetAssembly != null)
{
// The sole purpose of the stub class is to let us load the assembly that the class lives in,
// once we've done that, all types in it become visible.
Assembly asm;
try
{
#if WHIDBEY && STATIC_COMPILER
asm = Assembly.ReflectionOnlyLoad(dotnetAssembly);
#else
asm = Assembly.Load(dotnetAssembly);
#endif
}
catch(Exception x)
{
throw new NoClassDefFoundError(f.Name + " (" + x.Message + ")");
}
TypeWrapper tw = ClassLoaderWrapper.GetAssemblyClassLoader(asm).LoadClassByDottedNameFast(f.Name);
if(tw == null)
{
throw new NoClassDefFoundError(f.Name + " (type not found in " + asm.FullName + ")");
}
if(tw.Assembly != asm)
{
throw new NoClassDefFoundError(f.Name + " (assembly mismatch)");
}
return RegisterInitiatingLoader(tw);
}
2006-07-11 15:34:44 +04:00
lock(this)
2006-07-06 17:53:51 +04:00
{
2006-07-11 15:34:44 +04:00
if(factory == null)
2006-07-06 17:53:51 +04:00
{
2006-07-11 15:34:44 +04:00
factory = CreateTypeWrapperFactory();
2006-07-06 17:53:51 +04:00
}
}
2006-07-11 15:34:44 +04:00
lock(factory)
2006-07-06 17:53:51 +04:00
{
2006-07-11 15:34:44 +04:00
lock(types.SyncRoot)
2006-07-06 17:53:51 +04:00
{
2006-07-11 15:34:44 +04:00
if(types.ContainsKey(f.Name))
2006-07-06 17:53:51 +04:00
{
2006-07-11 15:34:44 +04:00
throw new LinkageError("duplicate class definition: " + f.Name);
2006-07-06 17:53:51 +04:00
}
2006-07-11 15:34:44 +04:00
// mark the type as "loading in progress", so that we can detect circular dependencies.
types.Add(f.Name, null);
2006-07-06 17:53:51 +04:00
}
2006-07-11 15:34:44 +04:00
try
{
return factory.DefineClassImpl(types, f, protectionDomain);
}
catch
2006-07-06 17:53:51 +04:00
{
2006-07-11 15:34:44 +04:00
lock(types.SyncRoot)
2006-07-06 17:53:51 +04:00
{
2006-07-11 15:34:44 +04:00
if(types[f.Name] == null)
{
// if loading the class fails, we remove the indicator that we're busy loading the class,
// because otherwise we get a ClassCircularityError if we try to load the class again.
types.Remove(f.Name);
}
2006-07-06 17:53:51 +04:00
}
2006-07-11 15:34:44 +04:00
throw;
2006-07-06 17:53:51 +04:00
}
}
}
2006-03-11 21:35:29 +03:00
2006-07-06 17:53:51 +04:00
protected virtual TypeWrapperFactory CreateTypeWrapperFactory()
2003-06-10 17:28:47 +04:00
{
2006-07-06 17:53:51 +04:00
#if COMPACT_FRAMEWORK
throw new NoClassDefFoundError("Class loading is not supported on the Compact Framework");
#else
return new DynamicClassLoader(this);
#endif
}
#if !COMPACT_FRAMEWORK
internal virtual ModuleBuilder ModuleBuilder
{
get
2006-03-11 21:35:29 +03:00
{
2006-07-06 17:53:51 +04:00
lock(this)
2006-03-11 21:35:29 +03:00
{
2006-07-06 17:53:51 +04:00
if(factory == null)
{
factory = CreateTypeWrapperFactory();
}
2006-03-11 21:35:29 +03:00
}
2006-07-06 17:53:51 +04:00
return factory.ModuleBuilder;
2006-03-11 21:35:29 +03:00
}
2006-02-22 17:44:07 +03:00
}
2005-12-07 12:06:32 +03:00
#endif
2003-06-10 17:28:47 +04:00
2005-06-01 13:49:30 +04:00
internal TypeWrapper LoadClassByDottedName(string name)
2003-03-17 17:02:46 +03:00
{
2006-07-11 15:34:44 +04:00
TypeWrapper type = LoadClassByDottedNameFastImpl(name, true);
2005-06-01 13:49:30 +04:00
if(type != null)
{
2006-07-11 15:34:44 +04:00
return RegisterInitiatingLoader(type);
2005-06-01 13:49:30 +04:00
}
throw new ClassNotFoundException(name);
2003-03-17 17:02:46 +03:00
}
2005-06-01 13:49:30 +04:00
internal TypeWrapper LoadClassByDottedNameFast(string name)
2005-08-25 11:46:57 +04:00
{
2006-07-11 15:34:44 +04:00
TypeWrapper type = LoadClassByDottedNameFastImpl(name, false);
if(type != null)
{
return RegisterInitiatingLoader(type);
}
return null;
2005-08-25 11:46:57 +04:00
}
2006-07-10 18:40:31 +04:00
private TypeWrapper LoadClassByDottedNameFastImpl(string name, bool throwClassNotFoundException)
2003-02-15 12:20:26 +03:00
{
2005-06-01 13:49:30 +04:00
// .NET 1.1 has a limit of 1024 characters for type names
2006-05-15 13:08:01 +04:00
if(name.Length >= 1024 || name.Length == 0)
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
return null;
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
Profiler.Enter("LoadClassByDottedName");
try
2002-12-18 19:00:25 +03:00
{
2006-07-11 15:34:44 +04:00
bool defineInProgress;
2005-06-01 13:49:30 +04:00
TypeWrapper type;
lock(types.SyncRoot)
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
type = (TypeWrapper)types[name];
2006-07-11 15:34:44 +04:00
defineInProgress = (type == null && types.ContainsKey(name));
2004-12-03 10:57:15 +03:00
}
2005-06-01 13:49:30 +04:00
if(type != null)
2004-12-03 10:57:15 +03:00
{
2005-06-01 13:49:30 +04:00
return type;
2004-12-03 10:57:15 +03:00
}
2006-07-11 15:34:44 +04:00
if(defineInProgress && factory != null)
2004-12-03 10:57:15 +03:00
{
2006-07-11 15:34:44 +04:00
// DefineClass synchronizes on factory, so if we can obtain that
// lock it either means that the DefineClass has finished or
// that we're on the same thread. To distinguish between
// the two, we check the types hashtable again and if it still
// contains the null entry we're on the same thread and should throw
// the ClassCircularityError.
lock(factory)
2003-08-26 15:24:17 +04:00
{
2006-07-11 15:34:44 +04:00
lock(types.SyncRoot)
2006-07-10 13:37:06 +04:00
{
2006-07-11 15:34:44 +04:00
if(types[name] == null && types.ContainsKey(name))
{
// NOTE this can also happen if we (incorrectly) trigger a load of this class during
// the loading of the base class, so we print a trace message here.
Tracer.Error(Tracer.ClassLoading, "**** ClassCircularityError: {0} ****", name);
throw new ClassCircularityError(name);
}
2006-07-10 13:37:06 +04:00
}
2003-08-26 15:24:17 +04:00
}
2006-07-11 15:34:44 +04:00
}
if(name.Length > 1 && name[0] == '[')
{
return LoadArrayClass(name);
2005-06-01 13:49:30 +04:00
}
2006-07-26 11:57:18 +04:00
if(name.EndsWith("_$$$$_") && name.IndexOf("_$$$_") > 0)
{
TypeWrapper tw = LoadGenericClass(name);
if(tw != null)
{
return tw;
}
}
2006-07-26 13:03:44 +04:00
// for manufactured types, we load the declaring outer type (the real one) and
// let that generated the manufactured nested classes
TypeWrapper outer = null;
if(name.EndsWith(DotNetTypeWrapper.DelegateInterfaceSuffix))
{
outer = LoadClassByDottedNameFastImpl(name.Substring(0, name.Length - DotNetTypeWrapper.DelegateInterfaceSuffix.Length), false);
}
else if(name.EndsWith(DotNetTypeWrapper.AttributeAnnotationSuffix))
{
outer = LoadClassByDottedNameFastImpl(name.Substring(0, name.Length - DotNetTypeWrapper.AttributeAnnotationSuffix.Length), false);
}
if(outer != null)
{
foreach(TypeWrapper tw in outer.InnerClasses)
{
if(tw.Name == name)
{
return tw;
}
}
}
2006-07-10 18:40:31 +04:00
return LoadClassImpl(name, throwClassNotFoundException);
2006-07-10 13:37:06 +04:00
}
finally
{
Profiler.Leave("LoadClassByDottedName");
}
}
2006-07-11 15:34:44 +04:00
private TypeWrapper LoadArrayClass(string name)
{
int dims = 1;
while(name[dims] == '[')
{
dims++;
if(dims == name.Length)
{
// malformed class name
return null;
}
}
if(name[dims] == 'L')
{
if(!name.EndsWith(";") || name.Length <= dims + 2 || name[dims + 1] == '[')
{
// malformed class name
return null;
}
string elemClass = name.Substring(dims + 1, name.Length - dims - 2);
// NOTE it's important that we're registered as the initiating loader
// for the element type here
TypeWrapper type = LoadClassByDottedNameFast(elemClass);
if(type != null)
{
type = type.GetClassLoader().CreateArrayType(name, type, dims);
}
return type;
}
if(name.Length != dims + 1)
{
// malformed class name
return null;
}
switch(name[dims])
{
case 'B':
return GetBootstrapClassLoader().CreateArrayType(name, PrimitiveTypeWrapper.BYTE, dims);
case 'C':
return GetBootstrapClassLoader().CreateArrayType(name, PrimitiveTypeWrapper.CHAR, dims);
case 'D':
return GetBootstrapClassLoader().CreateArrayType(name, PrimitiveTypeWrapper.DOUBLE, dims);
case 'F':
return GetBootstrapClassLoader().CreateArrayType(name, PrimitiveTypeWrapper.FLOAT, dims);
case 'I':
return GetBootstrapClassLoader().CreateArrayType(name, PrimitiveTypeWrapper.INT, dims);
case 'J':
return GetBootstrapClassLoader().CreateArrayType(name, PrimitiveTypeWrapper.LONG, dims);
case 'S':
return GetBootstrapClassLoader().CreateArrayType(name, PrimitiveTypeWrapper.SHORT, dims);
case 'Z':
return GetBootstrapClassLoader().CreateArrayType(name, PrimitiveTypeWrapper.BOOLEAN, dims);
default:
return null;
}
}
2006-07-21 14:18:13 +04:00
private TypeWrapper LoadGenericClass(string name)
{
// generic class name grammar:
//
2006-07-26 11:57:18 +04:00
// mangled(open_generic_type_name) "_$$$_" M(parameter_class_name) ( "_$$_" M(parameter_class_name) )* "_$$$$_"
//
// mangled() is the normal name mangling algorithm
// M() is a replacement of "__" with "$$005F$$005F" followed by a replace of "." with "__"
//
2006-07-21 14:18:13 +04:00
int pos = name.IndexOf("_$$$_");
if(pos <= 0)
{
return null;
}
Type type = GetBootstrapClassLoader().GetType(DotNetTypeWrapper.DemangleTypeName(name.Substring(0, pos)));
2006-07-26 11:57:18 +04:00
if(type == null || !Whidbey.IsGenericTypeDefinition(type))
2006-07-21 14:18:13 +04:00
{
return null;
}
ArrayList typeParamNames = new ArrayList();
pos += 5;
int start = pos;
int nest = 0;
for(;;)
{
pos = name.IndexOf("_$$", pos);
if(pos == -1)
{
return null;
}
if(name.IndexOf("_$$_", pos, 4) == pos)
{
if(nest == 0)
{
typeParamNames.Add(name.Substring(start, pos - start));
start = pos + 4;
}
pos += 4;
}
else if(name.IndexOf("_$$$_", pos, 5) == pos)
{
nest++;
pos += 5;
}
else if(name.IndexOf("_$$$$_", pos, 6) == pos)
{
if(nest == 0)
{
if(pos + 6 != name.Length)
{
return null;
}
typeParamNames.Add(name.Substring(start, pos - start));
break;
}
nest--;
pos += 6;
}
else
{
pos += 3;
}
}
Type[] typeArguments = new Type[typeParamNames.Count];
for(int i = 0; i < typeArguments.Length; i++)
{
2006-07-26 11:57:18 +04:00
string s = (string)typeParamNames[i];
s = s.Replace("__", ".");
s = s.Replace("$$005F$$005F", "__");
int dims = 0;
while(s.Length > dims && s[dims] == 'A')
{
dims++;
}
if(s.Length == dims)
{
return null;
}
TypeWrapper tw = null;
switch(s[dims])
{
case 'L':
tw = LoadClassByDottedNameFast(s.Substring(dims + 1));
break;
case 'Z':
tw = PrimitiveTypeWrapper.BOOLEAN;
break;
case 'B':
tw = PrimitiveTypeWrapper.BYTE;
break;
case 'S':
tw = PrimitiveTypeWrapper.SHORT;
break;
case 'C':
tw = PrimitiveTypeWrapper.CHAR;
break;
case 'I':
tw = PrimitiveTypeWrapper.INT;
break;
case 'F':
tw = PrimitiveTypeWrapper.FLOAT;
break;
case 'J':
tw = PrimitiveTypeWrapper.LONG;
break;
case 'D':
tw = PrimitiveTypeWrapper.DOUBLE;
break;
}
2006-07-21 14:18:13 +04:00
if(tw == null)
{
return null;
}
2006-07-26 11:57:18 +04:00
if(dims > 0)
{
tw = tw.MakeArrayType(dims);
}
2006-07-21 14:18:13 +04:00
typeArguments[i] = tw.TypeAsSignatureType;
}
// TODO consider catching the ArgumentException that MakeGenericType can throw
2006-07-26 11:57:18 +04:00
return GetWrapperFromType(Whidbey.MakeGenericType(type, typeArguments));
2006-07-21 14:18:13 +04:00
}
2006-07-10 13:37:06 +04:00
protected virtual TypeWrapper LoadClassImpl(string name, bool throwClassNotFoundException)
{
#if !STATIC_COMPILER
// NOTE just like Java does (I think), we take the classloader lock before calling the loadClass method
lock(javaClassLoader)
{
Profiler.Enter("ClassLoader.loadClass");
TypeWrapper type;
try
{
type = (TypeWrapper)JVM.Library.loadClass(javaClassLoader, name);
}
catch(Exception x)
2005-06-01 13:49:30 +04:00
{
2006-07-10 13:37:06 +04:00
if(!throwClassNotFoundException
&& LoadClassCritical("java.lang.ClassNotFoundException").TypeAsBaseType.IsInstanceOfType(x))
2005-06-01 13:49:30 +04:00
{
return null;
2003-08-21 14:06:34 +04:00
}
2006-07-10 13:37:06 +04:00
throw new ClassLoadingException(IKVM.Runtime.Util.MapException(x));
2002-12-29 19:27:00 +03:00
}
2006-07-10 13:37:06 +04:00
finally
2006-03-11 21:35:29 +03:00
{
2006-07-10 13:37:06 +04:00
Profiler.Leave("ClassLoader.loadClass");
2002-12-29 19:27:00 +03:00
}
2006-07-10 18:40:31 +04:00
return type;
2006-07-10 13:37:06 +04:00
}
2006-04-10 13:09:09 +04:00
#else
2006-07-10 13:37:06 +04:00
return null;
2006-04-10 13:09:09 +04:00
#endif
2002-12-18 19:00:25 +03:00
}
2006-07-10 13:37:06 +04:00
internal TypeWrapper GetWrapperFromBootstrapType(Type type)
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
//Tracer.Info(Tracer.Runtime, "GetWrapperFromBootstrapType: {0}", type.FullName);
Debug.Assert(!type.IsArray, "!type.IsArray", type.FullName);
2005-12-07 12:06:32 +03:00
#if !COMPACT_FRAMEWORK
2005-06-01 13:49:30 +04:00
Debug.Assert(!(type.Assembly is AssemblyBuilder), "!(type.Assembly is AssemblyBuilder)", type.FullName);
2005-12-07 12:06:32 +03:00
#endif
2005-06-01 13:49:30 +04:00
// only the bootstrap classloader can own compiled types
Debug.Assert(this == GetBootstrapClassLoader(), "this == GetBootstrapClassLoader()", type.FullName);
2005-12-07 12:06:32 +03:00
bool javaType = AttributeHelper.IsJavaModule(type.Module);
2005-06-01 13:49:30 +04:00
string name;
2005-01-03 11:26:21 +03:00
if(javaType)
{
2005-06-01 13:49:30 +04:00
name = CompiledTypeWrapper.GetName(type);
2005-01-03 11:26:21 +03:00
}
else
{
2005-06-01 13:49:30 +04:00
name = DotNetTypeWrapper.GetName(type);
2006-07-26 11:57:18 +04:00
if(name == null)
{
return null;
}
2005-01-03 11:26:21 +03:00
}
2005-06-01 13:49:30 +04:00
TypeWrapper wrapper;
2004-08-17 13:05:21 +04:00
lock(types.SyncRoot)
2003-08-13 19:00:41 +04:00
{
2005-06-01 13:49:30 +04:00
wrapper = (TypeWrapper)types[name];
}
2005-08-02 12:44:55 +04:00
if(wrapper != null)
{
2006-07-11 11:29:32 +04:00
if(wrapper.TypeAsTBD != type && (!wrapper.IsRemapped || wrapper.TypeAsBaseType != type))
2005-08-02 12:44:55 +04:00
{
2006-05-15 13:08:01 +04:00
string msg = String.Format("\nTypename \"{0}\" is imported from multiple assemblies:\n{1}\n{2}\n", type.FullName, wrapper.TypeAsTBD.Assembly.FullName, type.Assembly.FullName);
2005-08-02 12:44:55 +04:00
JVM.CriticalFailure(msg, null);
}
2006-07-11 11:29:32 +04:00
return wrapper;
2005-08-02 12:44:55 +04:00
}
else
2005-06-01 13:49:30 +04:00
{
if(javaType)
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
// since this type was compiled from Java source, we have to look for our
// attributes
2006-07-11 11:29:32 +04:00
return RegisterInitiatingLoader(CompiledTypeWrapper.newInstance(name, type));
2004-08-17 13:05:21 +04:00
}
2005-01-03 11:26:21 +03:00
else
{
2006-05-15 13:08:01 +04:00
if(!DotNetTypeWrapper.IsAllowedOutside(type))
{
return null;
}
2005-06-01 13:49:30 +04:00
// since this type was not compiled from Java source, we don't need to
// look for our attributes, but we do need to filter unrepresentable
// stuff (and transform some other stuff)
2006-07-11 11:29:32 +04:00
return RegisterInitiatingLoader(new DotNetTypeWrapper(type));
2005-01-03 11:26:21 +03:00
}
2003-08-13 19:00:41 +04:00
}
}
2002-12-18 19:00:25 +03:00
2005-06-01 13:49:30 +04:00
// NOTE this method can actually return null if the resulting array type name would be too long
// for .NET to handle.
private TypeWrapper CreateArrayType(string name, TypeWrapper elementTypeWrapper, int dims)
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
Debug.Assert(new String('[', dims) + elementTypeWrapper.SigName == name);
Debug.Assert(!elementTypeWrapper.IsUnloadable && !elementTypeWrapper.IsVerifierType && !elementTypeWrapper.IsArray);
Debug.Assert(dims >= 1);
Type elementType = elementTypeWrapper.TypeAsArrayType;
2006-07-11 11:29:32 +04:00
// .NET 1.1 has a limit of 1024 characters for type names
if(elementType.FullName.Length >= 1024 - dims * 2)
{
return null;
}
Type array = ArrayTypeWrapper.MakeArrayType(elementType, dims);
Modifiers modifiers = Modifiers.Final | Modifiers.Abstract;
Modifiers reflectiveModifiers = modifiers;
modifiers |= elementTypeWrapper.Modifiers & Modifiers.Public;
reflectiveModifiers |= elementTypeWrapper.ReflectiveModifiers & Modifiers.AccessMask;
return RegisterInitiatingLoader(new ArrayTypeWrapper(array, modifiers, reflectiveModifiers, name, this));
2005-06-01 13:49:30 +04:00
}
internal object GetJavaClassLoader()
2003-12-20 01:19:18 +03:00
{
2006-06-28 12:07:29 +04:00
return javaClassLoader;
2005-01-03 11:26:21 +03:00
}
2005-06-01 13:49:30 +04:00
internal TypeWrapper ExpressionTypeWrapper(string type)
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
Debug.Assert(!type.StartsWith("Lret;"));
Debug.Assert(type != "Lnull");
int index = 0;
return SigDecoderWrapper(ref index, type);
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
// NOTE this exposes potentially unfinished types
internal Type[] ArgTypeListFromSig(string sig)
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
if(sig[1] == ')')
{
2005-12-07 12:06:32 +03:00
#if COMPACT_FRAMEWORK
return new Type[0];
#else
2005-06-01 13:49:30 +04:00
return Type.EmptyTypes;
2005-12-07 12:06:32 +03:00
#endif
2005-06-01 13:49:30 +04:00
}
TypeWrapper[] wrappers = ArgTypeWrapperListFromSig(sig);
Type[] types = new Type[wrappers.Length];
for(int i = 0; i < wrappers.Length; i++)
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
types[i] = wrappers[i].TypeAsSignatureType;
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
return types;
}
// NOTE: this will ignore anything following the sig marker (so that it can be used to decode method signatures)
private TypeWrapper SigDecoderWrapper(ref int index, string sig)
{
switch(sig[index++])
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
case 'B':
return PrimitiveTypeWrapper.BYTE;
case 'C':
return PrimitiveTypeWrapper.CHAR;
case 'D':
return PrimitiveTypeWrapper.DOUBLE;
case 'F':
return PrimitiveTypeWrapper.FLOAT;
case 'I':
return PrimitiveTypeWrapper.INT;
case 'J':
return PrimitiveTypeWrapper.LONG;
case 'L':
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
int pos = index;
index = sig.IndexOf(';', index) + 1;
return LoadClassByDottedName(sig.Substring(pos, index - pos - 1));
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
case 'S':
return PrimitiveTypeWrapper.SHORT;
case 'Z':
return PrimitiveTypeWrapper.BOOLEAN;
case 'V':
return PrimitiveTypeWrapper.VOID;
case '[':
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
// TODO this can be optimized
string array = "[";
while(sig[index] == '[')
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
index++;
array += "[";
}
switch(sig[index])
{
case 'L':
{
int pos = index;
index = sig.IndexOf(';', index) + 1;
return LoadClassByDottedName(array + sig.Substring(pos, index - pos));
}
case 'B':
case 'C':
case 'D':
case 'F':
case 'I':
case 'J':
case 'S':
case 'Z':
return LoadClassByDottedName(array + sig[index++]);
default:
throw new InvalidOperationException(sig.Substring(index));
2002-12-18 19:00:25 +03:00
}
}
2005-06-01 13:49:30 +04:00
default:
throw new InvalidOperationException(sig.Substring(index));
2002-12-18 19:00:25 +03:00
}
}
2004-03-16 20:10:09 +03:00
2005-06-01 13:49:30 +04:00
internal TypeWrapper FieldTypeWrapperFromSig(string sig)
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
int index = 0;
return SigDecoderWrapper(ref index, sig);
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
internal TypeWrapper RetTypeWrapperFromSig(string sig)
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
int index = sig.IndexOf(')') + 1;
return SigDecoderWrapper(ref index, sig);
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
internal TypeWrapper[] ArgTypeWrapperListFromSig(string sig)
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
if(sig[1] == ')')
{
return TypeWrapper.EmptyArray;
}
ArrayList list = new ArrayList();
for(int i = 1; sig[i] != ')';)
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
list.Add(SigDecoderWrapper(ref i, sig));
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
TypeWrapper[] types = new TypeWrapper[list.Count];
list.CopyTo(types);
return types;
2002-12-18 19:00:25 +03:00
}
2004-09-09 15:17:55 +04:00
2005-06-01 13:49:30 +04:00
internal static ClassLoaderWrapper GetBootstrapClassLoader()
2004-10-04 23:30:53 +04:00
{
2006-03-23 14:57:41 +03:00
lock(wrapperLock)
2005-06-01 13:49:30 +04:00
{
if(bootstrapClassLoader == null)
{
2006-02-22 17:44:07 +03:00
bootstrapClassLoader = new BootstrapClassLoader();
2005-06-01 13:49:30 +04:00
}
return bootstrapClassLoader;
}
2004-10-04 23:30:53 +04:00
}
2005-06-01 13:49:30 +04:00
2006-04-10 13:09:09 +04:00
#if !STATIC_COMPILER
2005-06-01 13:49:30 +04:00
internal static ClassLoaderWrapper GetClassLoaderWrapper(object javaClassLoader)
2002-12-18 19:00:25 +03:00
{
2006-06-28 12:07:29 +04:00
if(javaClassLoader == null)
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
return GetBootstrapClassLoader();
}
2005-09-06 12:06:04 +04:00
lock(wrapperLock)
2005-06-01 13:49:30 +04:00
{
2005-09-06 12:06:04 +04:00
ClassLoaderWrapper wrapper = (ClassLoaderWrapper)JVM.Library.getWrapperFromClassLoader(javaClassLoader);
2005-06-01 13:49:30 +04:00
if(wrapper == null)
{
2006-07-06 17:53:51 +04:00
wrapper = new ClassLoaderWrapper(javaClassLoader);
2005-09-06 12:06:04 +04:00
JVM.Library.setWrapperForClassLoader(javaClassLoader, wrapper);
2005-06-01 13:49:30 +04:00
}
return wrapper;
2004-08-17 13:05:21 +04:00
}
2002-12-18 19:00:25 +03:00
}
2006-04-10 13:09:09 +04:00
#endif
2002-12-18 19:00:25 +03:00
2006-07-11 11:29:32 +04:00
internal static TypeWrapper GetWrapperFromType(Type type)
2002-12-18 19:00:25 +03:00
{
2006-07-11 11:29:32 +04:00
//Tracer.Info(Tracer.Runtime, "GetWrapperFromType: {0}", type.AssemblyQualifiedName);
2005-06-01 13:49:30 +04:00
TypeWrapper.AssertFinished(type);
2006-01-23 13:18:44 +03:00
Debug.Assert(!Whidbey.ContainsGenericParameters(type));
2006-07-11 11:29:32 +04:00
Debug.Assert(!type.IsPointer);
Debug.Assert(!type.IsByRef);
2005-06-01 13:49:30 +04:00
TypeWrapper wrapper = (TypeWrapper)typeToTypeWrapper[type];
2006-07-11 11:29:32 +04:00
if(wrapper != null)
2003-02-15 21:52:32 +03:00
{
2006-07-11 11:29:32 +04:00
return wrapper;
2003-02-15 21:52:32 +03:00
}
2006-07-11 11:29:32 +04:00
string remapped = (string)remappedTypes[type];
if(remapped != null)
2003-02-17 13:13:16 +03:00
{
2006-07-11 11:29:32 +04:00
wrapper = LoadClassCritical(remapped);
}
else if(type.IsArray)
{
// it might be an array of a dynamically compiled Java type
int rank = 1;
Type elem = type.GetElementType();
while(elem.IsArray)
2003-02-17 13:13:16 +03:00
{
2006-07-11 11:29:32 +04:00
rank++;
elem = elem.GetElementType();
2003-02-17 13:13:16 +03:00
}
2006-07-11 11:29:32 +04:00
wrapper = GetWrapperFromType(elem).MakeArrayType(rank);
}
else
{
2005-06-01 13:49:30 +04:00
// if the wrapper doesn't already exist, that must mean that the type
// is a .NET type (or a pre-compiled Java class), which means that it
2006-05-15 13:08:01 +04:00
// was "loaded" by an assembly classloader
2006-07-11 11:29:32 +04:00
wrapper = GetAssemblyClassLoader(type.Assembly).GetWrapperFromBootstrapType(type);
2003-02-17 13:13:16 +03:00
}
2006-07-11 11:29:32 +04:00
typeToTypeWrapper[type] = wrapper;
2005-06-01 13:49:30 +04:00
return wrapper;
2002-12-18 19:00:25 +03:00
}
2006-07-21 14:18:13 +04:00
internal virtual Type GetType(string name)
{
return null;
}
2006-07-26 14:33:52 +04:00
internal static ClassLoaderWrapper GetGenericClassLoader(TypeWrapper wrapper)
{
Type type = wrapper.TypeAsTBD;
Debug.Assert(Whidbey.IsGenericType(type));
Debug.Assert(!Whidbey.ContainsGenericParameters(type));
ArrayList list = new ArrayList();
list.Add(GetAssemblyClassLoader(type.Assembly));
foreach(Type arg in Whidbey.GetGenericArguments(type))
{
ClassLoaderWrapper loader = GetWrapperFromType(arg).GetClassLoader();
if(!list.Contains(loader))
{
list.Add(loader);
}
}
ClassLoaderWrapper[] key = (ClassLoaderWrapper[])list.ToArray(typeof(ClassLoaderWrapper));
ClassLoaderWrapper matchingLoader = null;
lock(wrapperLock)
{
if(genericClassLoaders == null)
{
genericClassLoaders = new ArrayList();
}
foreach(GenericClassLoader loader in genericClassLoaders)
{
if(loader.Matches(key))
{
matchingLoader = loader;
break;
}
}
if(matchingLoader == null)
{
matchingLoader = new GenericClassLoader(key);
genericClassLoaders.Add(matchingLoader);
}
}
matchingLoader.RegisterInitiatingLoader(wrapper);
return matchingLoader;
}
2006-05-15 13:08:01 +04:00
// this method only supports .NET or pre-compiled Java assemblies
internal static ClassLoaderWrapper GetAssemblyClassLoader(Assembly assembly)
{
// TODO this assertion fires when compiling the core library (at least on Whidbey)
// I need to find out why...
2006-07-06 17:53:51 +04:00
#if !COMPACT_FRAMEWORK
2006-05-15 13:08:01 +04:00
Debug.Assert(!(assembly is AssemblyBuilder));
2006-07-06 17:53:51 +04:00
#endif // !COMPACT_FRAMEWORK
2006-05-15 13:08:01 +04:00
#if WHIDBEY && !STATIC_COMPILER
if(assembly.ReflectionOnly)
{
2006-07-21 14:18:13 +04:00
lock(wrapperLock)
2006-05-15 13:08:01 +04:00
{
ClassLoaderWrapper loader = (ClassLoaderWrapper)reflectionOnlyClassLoaders[assembly];
if(loader == null)
{
2006-07-21 14:18:13 +04:00
loader = new ReflectionOnlyClassLoader(assembly);
2006-05-15 13:08:01 +04:00
reflectionOnlyClassLoaders[assembly] = loader;
2006-07-21 14:18:13 +04:00
JVM.Library.setWrapperForClassLoader(loader.javaClassLoader, loader);
2006-05-15 13:08:01 +04:00
}
return loader;
}
}
#endif
return GetBootstrapClassLoader();
}
2005-06-01 13:49:30 +04:00
internal static void SetWrapperForType(Type type, TypeWrapper wrapper)
{
TypeWrapper.AssertFinished(type);
Debug.Assert(!typeToTypeWrapper.ContainsKey(type));
typeToTypeWrapper.Add(type, wrapper);
}
2004-11-23 20:46:39 +03:00
2006-04-10 13:09:09 +04:00
#if STATIC_COMPILER
2005-06-01 13:49:30 +04:00
internal static void PublishLibraryImplementationHelperType(Type type)
2003-12-24 14:51:41 +03:00
{
2005-06-01 13:49:30 +04:00
CompiledTypeWrapper typeWrapper = CompiledTypeWrapper.newInstance(type.FullName, type);
SetWrapperForType(type, typeWrapper);
GetBootstrapClassLoader().types[type.FullName] = typeWrapper;
2003-12-24 14:51:41 +03:00
}
2006-04-10 13:09:09 +04:00
#endif // STATIC_COMPILER
2005-06-01 13:49:30 +04:00
internal static TypeWrapper LoadClassCritical(string name)
2003-12-24 14:51:41 +03:00
{
2005-06-01 13:49:30 +04:00
try
{
return GetBootstrapClassLoader().LoadClassByDottedName(name);
}
catch(Exception x)
{
JVM.CriticalFailure("Loading of critical class failed", x);
return null;
}
2003-12-24 14:51:41 +03:00
}
2004-08-30 19:56:23 +04:00
2005-06-01 13:49:30 +04:00
internal void RegisterNativeLibrary(IntPtr p)
2004-08-30 19:56:23 +04:00
{
2005-06-01 13:49:30 +04:00
lock(this)
2004-08-30 19:56:23 +04:00
{
2005-06-01 13:49:30 +04:00
if(nativeLibraries == null)
{
nativeLibraries = new ArrayList();
}
nativeLibraries.Add(p);
2004-08-30 19:56:23 +04:00
}
}
2005-06-01 13:49:30 +04:00
internal IntPtr[] GetNativeLibraries()
2004-08-30 19:56:23 +04:00
{
2005-06-01 13:49:30 +04:00
lock(this)
2004-08-30 19:56:23 +04:00
{
2005-06-01 13:49:30 +04:00
if(nativeLibraries == null)
{
return new IntPtr[0];
}
return (IntPtr[])nativeLibraries.ToArray(typeof(IntPtr));
2004-08-30 19:56:23 +04:00
}
}
2005-02-23 15:56:15 +03:00
2005-06-01 13:49:30 +04:00
public override string ToString()
2005-02-23 15:56:15 +03:00
{
2005-06-01 13:49:30 +04:00
if(javaClassLoader == null)
{
return "null";
}
return String.Format("{0}@{1:X}", GetWrapperFromType(javaClassLoader.GetType()).Name, javaClassLoader.GetHashCode());
2005-02-23 15:56:15 +03:00
}
}
2006-02-22 17:44:07 +03:00
class BootstrapClassLoader : ClassLoaderWrapper
{
internal BootstrapClassLoader()
: base(null)
{
}
2006-07-10 13:37:06 +04:00
protected override TypeWrapper LoadClassImpl(string name, bool throwClassNotFoundException)
{
Type t = GetBootstrapTypeRaw(name);
if(t != null)
{
return GetWrapperFromBootstrapType(t);
}
2006-07-26 11:57:18 +04:00
return DotNetTypeWrapper.CreateDotNetTypeWrapper(this, name);
2006-07-10 13:37:06 +04:00
}
// NOTE this method only sees pre-compiled Java classes
private Type GetBootstrapTypeRaw(string name)
{
#if COMPACT_FRAMEWORK
// TODO figure this out
return GetJavaTypeFromAssembly(JVM.CoreAssembly, name);
#else
Assembly[] assemblies;
#if WHIDBEY
if(JVM.IsStaticCompiler)
{
assemblies = AppDomain.CurrentDomain.ReflectionOnlyGetAssemblies();
}
else
{
assemblies = AppDomain.CurrentDomain.GetAssemblies();
}
#else
assemblies = AppDomain.CurrentDomain.GetAssemblies();
#endif
foreach(Assembly a in assemblies)
{
if(!(a is AssemblyBuilder))
{
Type t = GetJavaTypeFromAssembly(a, name);
if(t != null)
{
return t;
}
}
}
return null;
#endif
}
2006-07-21 14:18:13 +04:00
internal static Type GetJavaTypeFromAssembly(Assembly a, string name)
2006-07-10 13:37:06 +04:00
{
try
{
Type t = a.GetType(name);
if(t != null
&& AttributeHelper.IsJavaModule(t.Module)
&& !AttributeHelper.IsHideFromJava(t)
&& !t.IsArray
&& !t.IsPointer
&& !t.IsByRef)
{
return t;
}
// HACK we might be looking for an inner classes
t = a.GetType(name.Replace('$', '+'));
if(t != null
&& AttributeHelper.IsJavaModule(t.Module)
&& !AttributeHelper.IsHideFromJava(t)
&& !t.IsArray
&& !t.IsPointer
&& !t.IsByRef)
{
return t;
}
}
catch(ArgumentException x)
{
// we can end up here because we replace the $ with a plus sign
// (or client code did a Class.forName() on an invalid name)
Tracer.Info(Tracer.Runtime, x.Message);
}
catch(FileLoadException x)
{
// this can only happen if the assembly was loaded in the ReflectionOnly
// context and the requested type references a type in another assembly
// that cannot be found in the ReflectionOnly context
// TODO figure out what other exceptions Assembly.GetType() can throw
Tracer.Info(Tracer.Runtime, x.Message);
}
return null;
}
2006-07-21 14:18:13 +04:00
internal override Type GetType(string name)
{
Assembly[] assemblies;
#if WHIDBEY && STATIC_COMPILER
2006-07-26 11:57:18 +04:00
// mscorlib cannot be loaded in the ReflectionOnly context,
// so we have to search that separately
Type trycorlib = typeof(object).Assembly.GetType(name);
if(trycorlib != null)
{
return trycorlib;
}
2006-07-21 14:18:13 +04:00
assemblies = AppDomain.CurrentDomain.ReflectionOnlyGetAssemblies();
#else
assemblies = AppDomain.CurrentDomain.GetAssemblies();
#endif
foreach(Assembly a in assemblies)
{
if(!(a is AssemblyBuilder))
{
Type t = a.GetType(name);
if(t != null)
{
return t;
}
}
}
return null;
}
2006-02-22 17:44:07 +03:00
}
2006-05-15 13:08:01 +04:00
2006-07-26 14:33:52 +04:00
class GenericClassLoader : ClassLoaderWrapper
{
private ClassLoaderWrapper[] delegates;
// HACK we use a ReflectionOnlyClassLoader Java peer for the time being
internal GenericClassLoader(ClassLoaderWrapper[] delegates)
: base(JVM.Library.newReflectionOnlyClassLoader())
{
this.delegates = delegates;
}
internal bool Matches(ClassLoaderWrapper[] key)
{
if(key.Length == delegates.Length)
{
for(int i = 0; i < key.Length; i++)
{
if(key[i] != delegates[i])
{
return false;
}
}
return true;
}
return false;
}
internal override Type GetType(string name)
{
foreach(ClassLoaderWrapper loader in delegates)
{
Type t = loader.GetType(name);
if(t != null)
{
return t;
}
}
return null;
}
protected override TypeWrapper LoadClassImpl(string name, bool throwClassNotFoundException)
{
foreach(ClassLoaderWrapper loader in delegates)
{
TypeWrapper tw = loader.LoadClassByDottedNameFast(name);
if(tw != null)
{
return tw;
}
}
return null;
}
}
2006-07-21 14:18:13 +04:00
#if !STATIC_COMPILER
2006-05-15 13:08:01 +04:00
class ReflectionOnlyClassLoader : ClassLoaderWrapper
{
2006-07-21 14:18:13 +04:00
private Assembly assembly;
private bool isCoreAssembly;
internal ReflectionOnlyClassLoader(Assembly assembly)
: base(JVM.Library.newReflectionOnlyClassLoader())
2006-05-15 13:08:01 +04:00
{
2006-07-21 14:18:13 +04:00
this.assembly = assembly;
isCoreAssembly = AttributeHelper.GetRemappedClasses(assembly).Length > 0;
2006-05-15 13:08:01 +04:00
}
2006-07-10 13:37:06 +04:00
2006-07-26 11:57:18 +04:00
internal override Type GetType(string name)
{
return assembly.GetType(name);
}
2006-07-10 13:37:06 +04:00
protected override TypeWrapper LoadClassImpl(string name, bool throwClassNotFoundException)
{
2006-07-21 14:18:13 +04:00
if(isCoreAssembly)
{
Type t = BootstrapClassLoader.GetJavaTypeFromAssembly(assembly, name);
if(t != null)
{
return GetWrapperFromBootstrapType(t);
}
}
2006-07-26 11:57:18 +04:00
TypeWrapper tw = DotNetTypeWrapper.CreateDotNetTypeWrapper(this, name);
if(tw != null)
{
return tw;
}
2006-07-10 18:40:31 +04:00
return GetBootstrapClassLoader().LoadClassByDottedNameFast(name);
2006-07-10 13:37:06 +04:00
}
2006-05-15 13:08:01 +04:00
}
2006-07-21 14:18:13 +04:00
#endif
2002-12-18 19:00:25 +03:00
}