ikvm-fork/runtime/ClassLoaderWrapper.cs

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

2002-12-18 19:00:25 +03:00
/*
2005-02-02 18:11:26 +03:00
Copyright (C) 2002, 2003, 2004, 2005 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.Emit;
using System.Reflection;
using System.IO;
using System.Collections;
using System.Xml;
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
{
2005-07-25 18:34:22 +04:00
class IdentityProvider : IHashCodeProvider, IComparer
{
public int GetHashCode(object obj)
{
return System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode(obj);
}
public int Compare(object x, object y)
{
return x == y ? 0 : 1;
}
}
2005-06-01 13:49:30 +04:00
class ClassLoaderWrapper
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
private static bool arrayConstructionHack;
2005-07-25 18:34:22 +04:00
private static readonly object arrayConstructionLock = new object();
private static readonly IdentityProvider identityProvider = new IdentityProvider();
private static readonly Hashtable javaClassLoaderToClassLoaderWrapper = new Hashtable(identityProvider, identityProvider);
private static readonly Hashtable dynamicTypes = Hashtable.Synchronized(new Hashtable());
private static readonly Hashtable typeToTypeWrapper = Hashtable.Synchronized(new Hashtable(identityProvider, identityProvider));
2005-06-01 13:49:30 +04:00
private static ClassLoaderWrapper bootstrapClassLoader;
private static ClassLoaderWrapper systemClassLoader;
private object javaClassLoader;
private Hashtable types = new Hashtable();
private ArrayList nativeLibraries;
// FXBUG moduleBuilder is static, because multiple dynamic assemblies is broken (TypeResolve doesn't fire)
// so for the time being, we share one dynamic assembly among all classloaders
private static ModuleBuilder moduleBuilder;
private static bool saveDebugImage;
private static Hashtable nameClashHash = new Hashtable();
private static Assembly coreAssembly; // this is the assembly that contains the remapped and core classes
private static Hashtable remappedTypes = new Hashtable();
private static int instanceCounter = 0;
private static ArrayList saveDebugAssemblies;
private int instanceId = System.Threading.Interlocked.Increment(ref instanceCounter);
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()
{
// TODO AppDomain.TypeResolve requires ControlAppDomain permission, but if we don't have that,
// we should handle that by disabling dynamic class loading
AppDomain.CurrentDomain.TypeResolve += new ResolveEventHandler(OnTypeResolve);
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-06-01 13:49:30 +04:00
Debug.Assert(coreAssembly == null);
// if we're compiling the core, impl will be null
object impl = JVM.Library;
2004-12-21 17:59:29 +03:00
2005-06-01 13:49:30 +04:00
if(impl != null)
2004-03-08 18:18:47 +03:00
{
2005-06-01 13:49:30 +04:00
coreAssembly = impl.GetType().Assembly;
object[] remapped = coreAssembly.GetCustomAttributes(typeof(RemappedClassAttribute), false);
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
2005-06-01 13:49:30 +04:00
internal static bool IsCoreAssemblyType(Type type)
{
return type.Assembly == coreAssembly;
}
2004-10-04 23:30:53 +04:00
2005-06-01 13:49:30 +04:00
private static Assembly OnTypeResolve(object sender, ResolveEventArgs args)
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
lock(arrayConstructionLock)
{
Tracer.Info(Tracer.ClassLoading, "OnTypeResolve: {0} (arrayConstructionHack = {1})", args.Name, arrayConstructionHack);
if(arrayConstructionHack)
{
return null;
}
}
TypeWrapper type = (TypeWrapper)dynamicTypes[args.Name];
if(type == null)
2004-08-17 13:05:21 +04:00
{
return null;
}
2005-08-03 16:59:16 +04:00
// During static compilation, a TypeResolve event should never trigger a finish.
if(JVM.IsStaticCompilerPhase1)
{
JVM.CriticalFailure("Finish triggered during phase 1 of compilation.", null);
return null;
}
2005-06-01 13:49:30 +04:00
try
{
type.Finish();
}
catch(RetargetableJavaException x)
{
throw x.ToJava();
}
// NOTE We used to remove the type from the hashtable here, but that creates a race condition if
// another thread also fires the OnTypeResolve event while we're baking the type.
// I really would like to remove the type from the hashtable, but at the moment I don't see
// any way of doing that that wouldn't cause this race condition.
//dynamicTypes.Remove(args.Name);
return type.TypeAsTBD.Assembly;
2004-03-08 18:18:47 +03:00
}
2005-06-01 13:49:30 +04:00
internal ClassLoaderWrapper(object javaClassLoader)
2004-03-08 18:18:47 +03:00
{
2005-06-01 13:49:30 +04:00
SetJavaClassLoader(javaClassLoader);
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
internal void SetJavaClassLoader(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
2005-07-27 19:57:55 +04:00
internal TypeWrapper RegisterInitiatingLoader(TypeWrapper tw)
{
2005-08-25 17:15:42 +04:00
if(tw == null || tw.IsUnloadable || tw.IsPrimitive)
2005-07-27 19:57:55 +04:00
return tw;
lock(types.SyncRoot)
{
object existing = types[tw.Name];
if(existing != tw)
{
if(existing != null)
{
throw new LinkageError("duplicate class definition: " + tw.Name);
}
if(tw.IsArray)
{
TypeWrapper elem = tw;
// TODO there should be a way to get the ultimate element type
// without creating all the intermediate types
while(elem.IsArray)
{
elem = elem.ElementTypeWrapper;
}
RegisterInitiatingLoader(elem);
}
// 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;
}
2005-06-01 13:49:30 +04:00
// FXBUG This mangles type names, to enable different class loaders loading classes with the same names.
// We used to support this by using an assembly per class loader instance, but because
// of the CLR TypeResolve bug, we put all types in a single assembly for now.
internal string MangleTypeName(string name)
2003-06-10 17:28:47 +04:00
{
2005-06-01 13:49:30 +04:00
lock(nameClashHash.SyncRoot)
2003-06-10 17:28:47 +04:00
{
2005-06-01 13:49:30 +04:00
// FXBUG the 1.1 CLR doesn't like type names that end with a period.
if(nameClashHash.ContainsKey(name) || name.EndsWith("."))
2003-06-10 17:28:47 +04:00
{
2005-06-01 13:49:30 +04:00
if(JVM.IsStaticCompiler)
{
Tracer.Warning(Tracer.Compiler, "Class name clash: {0}", name);
}
return name + "/" + instanceId;
}
else
{
nameClashHash.Add(name, name);
return name;
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
{
2005-08-25 11:46:57 +04:00
TypeWrapper type = LoadClassByDottedNameFast(name, true);
2005-06-01 13:49:30 +04:00
if(type != null)
{
return type;
}
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
{
return LoadClassByDottedNameFast(name, false);
}
private TypeWrapper LoadClassByDottedNameFast(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
if(name.Length >= 1024)
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
{
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];
if(type == null && types.ContainsKey(name))
2004-12-03 10:57:15 +03:00
{
2005-06-01 13:49:30 +04:00
// 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);
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
}
2005-06-01 13:49:30 +04:00
if(name.Length > 1 && name[0] == '[')
2004-12-03 10:57:15 +03:00
{
2005-06-01 13:49:30 +04:00
int dims = 1;
while(name[dims] == '[')
2003-08-26 15:24:17 +04:00
{
2005-06-01 13:49:30 +04:00
dims++;
2003-08-26 15:24:17 +04:00
}
2005-06-01 13:49:30 +04:00
if(name[dims] == 'L')
2002-12-29 19:27:00 +03:00
{
2005-06-01 13:49:30 +04:00
if(!name.EndsWith(";") || name.Length <= dims + 2 || name[dims + 1] == '[')
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
// malformed class name
return null;
2003-08-21 14:06:34 +04:00
}
2005-06-01 13:49:30 +04:00
string elemClass = name.Substring(dims + 1, name.Length - dims - 2);
type = LoadClassByDottedNameFast(elemClass);
if(type != null)
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
type = type.GetClassLoader().CreateArrayType(name, type, dims);
2003-08-21 14:06:34 +04:00
}
2005-07-27 19:57:55 +04:00
return RegisterInitiatingLoader(type);
2002-12-29 19:27:00 +03:00
}
2005-06-01 13:49:30 +04:00
if(name.Length != dims + 1)
{
// malformed class name
return null;
}
switch(name[dims])
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
case 'B':
2005-07-27 19:57:55 +04:00
return RegisterInitiatingLoader(GetBootstrapClassLoader().CreateArrayType(name, PrimitiveTypeWrapper.BYTE, dims));
2005-06-01 13:49:30 +04:00
case 'C':
2005-07-27 19:57:55 +04:00
return RegisterInitiatingLoader(GetBootstrapClassLoader().CreateArrayType(name, PrimitiveTypeWrapper.CHAR, dims));
2005-06-01 13:49:30 +04:00
case 'D':
2005-07-27 19:57:55 +04:00
return RegisterInitiatingLoader(GetBootstrapClassLoader().CreateArrayType(name, PrimitiveTypeWrapper.DOUBLE, dims));
2005-06-01 13:49:30 +04:00
case 'F':
2005-07-27 19:57:55 +04:00
return RegisterInitiatingLoader(GetBootstrapClassLoader().CreateArrayType(name, PrimitiveTypeWrapper.FLOAT, dims));
2005-06-01 13:49:30 +04:00
case 'I':
2005-07-27 19:57:55 +04:00
return RegisterInitiatingLoader(GetBootstrapClassLoader().CreateArrayType(name, PrimitiveTypeWrapper.INT, dims));
2005-06-01 13:49:30 +04:00
case 'J':
2005-07-27 19:57:55 +04:00
return RegisterInitiatingLoader(GetBootstrapClassLoader().CreateArrayType(name, PrimitiveTypeWrapper.LONG, dims));
2005-06-01 13:49:30 +04:00
case 'S':
2005-07-27 19:57:55 +04:00
return RegisterInitiatingLoader(GetBootstrapClassLoader().CreateArrayType(name, PrimitiveTypeWrapper.SHORT, dims));
2005-06-01 13:49:30 +04:00
case 'Z':
2005-07-27 19:57:55 +04:00
return RegisterInitiatingLoader(GetBootstrapClassLoader().CreateArrayType(name, PrimitiveTypeWrapper.BOOLEAN, dims));
2005-06-01 13:49:30 +04:00
default:
return null;
2003-08-21 14:06:34 +04:00
}
2005-06-01 13:49:30 +04:00
}
if(this == GetBootstrapClassLoader())
{
// HACK if the name contains a comma, we assume it is an assembly qualified name
if(name.IndexOf(',') != -1)
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
// NOTE even though we search all loaded assemblies below, we still need to do this,
// because this call might actually trigger the load of an assembly.
Type t = Type.GetType(name);
if(t == null)
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
// HACK we explicitly try all loaded assemblies, to support assemblies
// that aren't loaded in the "Load" context.
string typeName = name.Substring(0, name.IndexOf(','));
foreach(Assembly asm in AppDomain.CurrentDomain.GetAssemblies())
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
t = asm.GetType(typeName);
if(t != null && t.AssemblyQualifiedName == name)
{
break;
}
t = null;
}
}
if(t != null)
{
if(t.Module.IsDefined(typeof(JavaModuleAttribute), false))
{
2005-07-27 19:57:55 +04:00
return RegisterInitiatingLoader(GetWrapperFromType(t));
2004-08-17 13:05:21 +04:00
}
else
{
2005-06-01 13:49:30 +04:00
// HACK weird way to load the .NET type wrapper that always works
// (for remapped types as well, because netexp uses this way of
// loading types, we need the remapped types to appear in their
// .NET "warped" form).
2005-08-25 11:46:57 +04:00
return LoadClassByDottedNameFast(DotNetTypeWrapper.GetName(t), throwClassNotFoundException);
2004-08-17 13:05:21 +04:00
}
}
2003-08-21 14:06:34 +04:00
}
2005-06-01 13:49:30 +04:00
// TODO why is this check here and not at the top of the method?
if(name != "")
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
Type t = GetBootstrapTypeRaw(name);
if(t != null)
{
2005-07-27 19:57:55 +04:00
return RegisterInitiatingLoader(GetWrapperFromBootstrapType(t));
2005-06-01 13:49:30 +04:00
}
type = DotNetTypeWrapper.CreateDotNetTypeWrapper(name);
if(type != null)
{
Debug.Assert(type.Name == name, type.Name + " != " + name);
lock(types.SyncRoot)
{
// another thread may have beaten us to it and in that
// case we don't want to overwrite the previous one
TypeWrapper race = (TypeWrapper)types[name];
if(race == null)
{
types[name] = type;
}
else
{
type = race;
}
}
return type;
}
// NOTE it is important that this is done last, because otherwise we will
// load the netexp generated fake types (e.g. delegate inner interface) instead
// of having DotNetTypeWrapper generating it.
type = GetTypeWrapperCompilerHook(name);
if(type != null)
{
return type;
}
}
if(javaClassLoader == null)
{
return null;
2003-08-21 14:06:34 +04:00
}
2002-12-29 19:27:00 +03:00
}
2005-06-01 13:49:30 +04:00
// NOTE just like Java does (I think), we take the classloader lock before calling the loadClass method
lock(javaClassLoader)
2002-12-29 19:27:00 +03:00
{
2005-06-01 13:49:30 +04:00
Profiler.Enter("ClassLoader.loadClass");
try
{
type = (TypeWrapper)JVM.Library.loadClass(javaClassLoader, name);
}
2005-08-24 15:35:00 +04:00
catch(Exception x)
{
2005-08-25 11:46:57 +04:00
if(!throwClassNotFoundException
&& LoadClassCritical("java.lang.ClassNotFoundException").TypeAsBaseType.IsInstanceOfType(x))
{
return null;
}
2005-08-24 15:35:00 +04:00
throw new ClassLoadingException(IKVM.Runtime.Util.MapException(x));
}
2005-06-01 13:49:30 +04:00
finally
{
Profiler.Leave("ClassLoader.loadClass");
}
2005-08-01 14:27:06 +04:00
// NOTE to be safe, we register the initiating loader,
// while we're holding the lock on the class loader object
return RegisterInitiatingLoader(type);
2002-12-29 19:27:00 +03:00
}
2005-06-01 13:49:30 +04:00
}
finally
{
Profiler.Leave("LoadClassByDottedName");
2002-12-18 19:00:25 +03:00
}
}
2005-06-01 13:49:30 +04:00
private 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(GetWrapperFromTypeFast(type) == null, "GetWrapperFromTypeFast(type) == null", type.FullName);
Debug.Assert(!type.IsArray, "!type.IsArray", type.FullName);
Debug.Assert(!(type.Assembly is AssemblyBuilder), "!(type.Assembly is AssemblyBuilder)", type.FullName);
// only the bootstrap classloader can own compiled types
Debug.Assert(this == GetBootstrapClassLoader(), "this == GetBootstrapClassLoader()", type.FullName);
bool javaType = type.Module.IsDefined(typeof(JavaModuleAttribute), false);
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);
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)
{
if(wrapper.TypeAsTBD != type)
{
string msg = String.Format("\nTypename \"{0}\" is imported from multiple assemblies:\n{1}\n{2}\n", type.FullName, wrapper.Assembly.FullName, type.Assembly.FullName);
JVM.CriticalFailure(msg, null);
}
}
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
wrapper = CompiledTypeWrapper.newInstance(name, type);
2004-08-17 13:05:21 +04:00
}
2005-01-03 11:26:21 +03:00
else
{
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)
wrapper = new DotNetTypeWrapper(type);
}
Debug.Assert(wrapper.Name == name, "wrapper.Name == name", type.FullName);
lock(types.SyncRoot)
{
// another thread may have beaten us to it and in that
// case we don't want to overwrite the previous one
TypeWrapper race = (TypeWrapper)types[name];
if(race == null)
{
types.Add(name, wrapper);
typeToTypeWrapper.Add(type, wrapper);
}
else
{
wrapper = race;
}
2005-01-03 11:26:21 +03:00
}
2003-08-13 19:00:41 +04:00
}
2005-06-01 13:49:30 +04:00
return wrapper;
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 only sees pre-compiled Java classes
internal Type GetBootstrapTypeRaw(string name)
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
foreach(Assembly a in AppDomain.CurrentDomain.GetAssemblies())
2003-02-20 17:18:38 +03:00
{
2005-06-01 13:49:30 +04:00
if(!(a is AssemblyBuilder))
2004-01-11 16:14:42 +03:00
{
2005-06-01 13:49:30 +04:00
Type t = GetJavaTypeFromAssembly(a, name);
if(t != null)
{
return t;
}
2004-01-11 16:14:42 +03:00
}
2003-02-20 17:18:38 +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
private static Type GetJavaTypeFromAssembly(Assembly a, string name)
2004-11-16 14:11:53 +03:00
{
2005-06-27 13:06:57 +04:00
try
2005-06-01 13:49:30 +04:00
{
2005-06-27 13:06:57 +04:00
Type t = a.GetType(name);
2005-08-25 13:36:36 +04:00
if(t != null
&& t.Module.IsDefined(typeof(JavaModuleAttribute), false)
&& !AttributeHelper.IsHideFromJava(t))
2005-06-27 13:06:57 +04:00
{
return t;
}
// HACK we might be looking for an inner classes
t = a.GetType(name.Replace('$', '+'));
2005-08-25 13:36:36 +04:00
if(t != null
&& t.Module.IsDefined(typeof(JavaModuleAttribute), false)
&& !AttributeHelper.IsHideFromJava(t))
2005-06-27 13:06:57 +04:00
{
return t;
}
2005-06-01 13:49:30 +04:00
}
2005-06-27 13:06:57 +04:00
catch(ArgumentException x)
2005-06-01 13:49:30 +04:00
{
2005-06-27 13:06:57 +04:00
// 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);
2005-06-01 13:49:30 +04:00
}
return null;
2004-11-16 14:11:53 +03:00
}
2002-12-18 19:00:25 +03:00
2005-06-01 13:49:30 +04:00
internal virtual TypeWrapper GetTypeWrapperCompilerHook(string name)
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
return null;
2005-01-03 11:26:21 +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;
TypeWrapper wrapper;
lock(types.SyncRoot)
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
wrapper = (TypeWrapper)types[name];
2005-01-03 11:26:21 +03:00
}
2005-06-01 13:49:30 +04:00
if(wrapper == null)
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
String netname = elementType.FullName + "[]";
for(int i = 1; i < dims; i++)
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
netname += "[]";
}
// .NET 1.1 has a limit of 1024 characters for type names
if(netname.Length >= 1024)
{
return null;
}
Type array;
if(elementType.Module is ModuleBuilder)
{
// FXBUG ModuleBuilder.GetType() is broken (I think), it fires a TypeResolveEvent when
// you try to construct an array type from an unfinished type. I don't think it should
// do that. We have to work around that by setting a global flag (yuck) to prevent us
// from responding to the TypeResolveEvent.
lock(arrayConstructionLock)
{
arrayConstructionHack = true;
try
{
array = ((ModuleBuilder)elementType.Module).GetType(netname);
}
finally
{
arrayConstructionHack = false;
}
}
}
else
{
array = elementType.Assembly.GetType(netname, true);
}
Modifiers modifiers = Modifiers.Final | Modifiers.Abstract;
Modifiers reflectiveModifiers = modifiers;
modifiers |= elementTypeWrapper.Modifiers & Modifiers.Public;
reflectiveModifiers |= elementTypeWrapper.ReflectiveModifiers & Modifiers.AccessMask;
wrapper = new ArrayTypeWrapper(array, modifiers, reflectiveModifiers, name, this);
lock(types.SyncRoot)
{
// another thread may have beaten us to it and in that
// case we don't want to overwrite the previous one
TypeWrapper race = (TypeWrapper)types[name];
if(race == null)
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
types.Add(name, wrapper);
if(!(elementType is TypeBuilder) && !wrapper.IsGhostArray)
{
Debug.Assert(!typeToTypeWrapper.ContainsKey(array), name);
typeToTypeWrapper.Add(array, wrapper);
}
2005-01-03 11:26:21 +03:00
}
2005-06-01 13:49:30 +04:00
else
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
wrapper = race;
2005-01-03 11:26:21 +03:00
}
2002-12-18 19:00:25 +03:00
}
2005-01-03 11:26:21 +03:00
}
2005-06-01 13:49:30 +04:00
return wrapper;
}
internal TypeWrapper DefineClass(ClassFile f, object protectionDomain)
{
string dotnetAssembly = f.IKVMAssemblyAttribute;
if(dotnetAssembly != null)
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
// HACK only the bootstrap classloader can define .NET types (but for convenience, we do
// allow other class loaders to call DefineClass for them)
// TODO reconsider this, it might be a better idea to only allow netexp generated jars on the bootclasspath
return GetBootstrapClassLoader().DefineNetExpType(f.Name, dotnetAssembly);
2005-01-03 11:26:21 +03:00
}
lock(types.SyncRoot)
{
2005-06-01 13:49:30 +04:00
if(types.ContainsKey(f.Name))
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
throw new LinkageError("duplicate class definition: " + f.Name);
}
// mark the type as "loading in progress", so that we can detect circular dependencies.
types.Add(f.Name, null);
}
try
{
TypeWrapper type = CreateDynamicTypeWrapper(f, this, protectionDomain);
lock(types.SyncRoot)
{
// in very extreme conditions another thread may have beaten us to it
// and loaded a class with the same name, in that case we'll leak
// the defined DynamicTypeWrapper (or rather the Reflection.Emit
// defined type).
TypeWrapper race = (TypeWrapper)types[f.Name];
if(race == null)
{
Debug.Assert(!dynamicTypes.ContainsKey(type.TypeAsTBD.FullName));
dynamicTypes.Add(type.TypeAsTBD.FullName, type);
types[f.Name] = type;
}
else
2004-08-17 13:05:21 +04:00
{
2005-07-27 19:57:55 +04:00
throw new LinkageError("duplicate class definition: " + f.Name);
2004-08-17 13:05:21 +04:00
}
}
2005-06-01 13:49:30 +04:00
return type;
}
catch
{
lock(types.SyncRoot)
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +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);
}
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
throw;
2002-12-18 19:00:25 +03:00
}
}
2005-06-01 13:49:30 +04:00
protected virtual TypeWrapper CreateDynamicTypeWrapper(ClassFile f, ClassLoaderWrapper loader, object protectionDomain)
2003-12-20 01:19:18 +03:00
{
2005-06-01 13:49:30 +04:00
return new DynamicTypeWrapper(f, loader, protectionDomain);
2003-12-20 01:19:18 +03:00
}
2005-06-01 13:49:30 +04:00
private TypeWrapper DefineNetExpType(string name, string assemblyName)
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
Debug.Assert(this == GetBootstrapClassLoader());
TypeWrapper type;
lock(types.SyncRoot)
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
// we need to check if we've already got it, because other classloaders than the bootstrap classloader may
// "define" NetExp types, there is a potential race condition if multiple classloaders try to define the
// same type simultaneously.
type = (TypeWrapper)types[name];
if(type != null)
{
return type;
}
}
// The sole purpose of the netexp 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
{
asm = Assembly.Load(assemblyName);
}
catch(Exception x)
{
throw new NoClassDefFoundError(name + " (" + x.Message + ")");
}
// pre-compiled Java types can also live in a netexp referenced assembly,
// so we have to explicitly check for those
// (DotNetTypeWrapper.CreateDotNetTypeWrapper will refuse to return Java types).
Type t = GetJavaTypeFromAssembly(asm, name);
if(t != null)
{
return GetWrapperFromBootstrapType(t);
}
type = DotNetTypeWrapper.CreateDotNetTypeWrapper(name);
if(type == null)
{
throw new NoClassDefFoundError(name + " not found in " + assemblyName);
2003-08-08 16:37:14 +04:00
}
2005-01-03 11:26:21 +03:00
lock(types.SyncRoot)
2003-08-08 16:37:14 +04:00
{
2005-06-01 13:49:30 +04:00
TypeWrapper race = (TypeWrapper)types[name];
2005-01-03 11:26:21 +03:00
if(race == null)
{
2005-06-01 13:49:30 +04:00
types.Add(name, type);
2005-01-03 11:26:21 +03:00
}
else
{
type = race;
}
2003-08-08 16:37:14 +04:00
}
2005-01-03 11:26:21 +03:00
return type;
}
2005-05-30 19:30:13 +04:00
2005-06-01 13:49:30 +04:00
internal object GetJavaClassLoader()
2003-12-20 01:19:18 +03:00
{
2005-06-01 13:49:30 +04:00
return (this == GetBootstrapClassLoader()) ? null : javaClassLoader;
2005-01-03 11:26:21 +03:00
}
2005-06-01 13:49:30 +04:00
// When -Xbootclasspath is specified, we use a URLClassLoader as an
// additional bootstrap class loader (this is not visible to the Java code).
// We need to access this to be able to load resources.
internal static object GetJavaBootstrapClassLoader()
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
return GetBootstrapClassLoader().javaClassLoader;
2005-01-03 11:26:21 +03:00
}
2005-06-01 13:49:30 +04:00
internal static void PrepareForSaveDebugImage()
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
Debug.Assert(moduleBuilder == null);
saveDebugImage = true;
2005-01-03 11:26:21 +03:00
}
2005-06-01 13:49:30 +04:00
internal static bool IsSaveDebugImage
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
get
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
return saveDebugImage;
2004-08-17 13:05:21 +04:00
}
2003-12-20 01:19:18 +03:00
}
2002-12-18 19:00:25 +03:00
2005-06-01 13:49:30 +04:00
internal static void FinishAll()
2002-12-18 19:00:25 +03:00
{
2005-08-05 12:40:54 +04:00
JVM.FinishingForDebugSave = true;
2005-06-01 13:49:30 +04:00
while(dynamicTypes.Count > 0)
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
ArrayList l = new ArrayList(dynamicTypes.Values);
foreach(TypeWrapper tw in l)
{
2005-06-16 11:38:08 +04:00
string name = tw.TypeAsTBD.FullName;
Tracer.Info(Tracer.Runtime, "Finishing {0}", name);
2005-08-05 12:40:54 +04:00
tw.Finish();
2005-06-16 11:38:08 +04:00
dynamicTypes.Remove(name);
2005-06-01 13:49:30 +04:00
}
2002-12-18 19:00:25 +03:00
}
}
2004-08-17 13:05:21 +04:00
2005-06-01 13:49:30 +04:00
internal static void SaveDebugImage(object mainClass)
2004-09-05 13:37:58 +04:00
{
2005-06-01 13:49:30 +04:00
FinishAll();
// HACK use reflection to get the type from the class
TypeWrapper mainTypeWrapper = IKVM.NativeCode.java.lang.VMClass.getWrapperFromClass(mainClass);
mainTypeWrapper.Finish();
Type mainType = mainTypeWrapper.TypeAsTBD;
MethodInfo main = mainType.GetMethod("main", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[] { typeof(string[]) }, null);
AssemblyBuilder asm = ((AssemblyBuilder)moduleBuilder.Assembly);
asm.SetEntryPoint(main, PEFileKinds.ConsoleApplication);
asm.Save("ikvmdump.exe");
if(saveDebugAssemblies != null)
2004-09-05 13:37:58 +04:00
{
2005-06-01 13:49:30 +04:00
foreach(AssemblyBuilder ab in saveDebugAssemblies)
{
ab.Save(ab.GetName().Name + ".dll");
}
2004-09-05 13:37:58 +04:00
}
}
2005-06-01 13:49:30 +04:00
internal static void RegisterForSaveDebug(AssemblyBuilder ab)
2004-09-05 13:37:58 +04:00
{
2005-06-01 13:49:30 +04:00
if(saveDebugAssemblies == null)
{
saveDebugAssemblies = new ArrayList();
}
saveDebugAssemblies.Add(ab);
2004-09-05 13:37:58 +04:00
}
2002-12-18 19:00:25 +03:00
2005-06-01 13:49:30 +04:00
internal ModuleBuilder ModuleBuilder
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
get
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
lock(this)
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
if(moduleBuilder == null)
{
moduleBuilder = CreateModuleBuilder();
}
return moduleBuilder;
2002-12-18 19:00:25 +03:00
}
}
}
2005-06-01 13:49:30 +04:00
protected virtual ModuleBuilder CreateModuleBuilder()
2004-09-05 13:37:58 +04:00
{
2005-06-01 13:49:30 +04:00
AssemblyName name = new AssemblyName();
if(saveDebugImage)
{
name.Name = "ikvmdump";
}
else
{
name.Name = "ikvm_dynamic_assembly__" + instanceId + "__" + (uint)Environment.TickCount;
}
DateTime now = DateTime.Now;
name.Version = new Version(now.Year, (now.Month * 100) + now.Day, (now.Hour * 100) + now.Minute, (now.Second * 1000) + now.Millisecond);
AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(name, saveDebugImage ? AssemblyBuilderAccess.RunAndSave : AssemblyBuilderAccess.Run, null, null, null, null, null, true);
CustomAttributeBuilder debugAttr = new CustomAttributeBuilder(typeof(DebuggableAttribute).GetConstructor(new Type[] { typeof(bool), typeof(bool) }), new object[] { true, JVM.Debug });
assemblyBuilder.SetCustomAttribute(debugAttr);
2005-06-24 11:00:43 +04:00
return saveDebugImage ? assemblyBuilder.DefineDynamicModule("ikvmdump.exe", "ikvmdump.exe", JVM.Debug) : assemblyBuilder.DefineDynamicModule(name.Name, JVM.Debug);
2004-09-05 13:37:58 +04:00
}
2002-12-18 19:00:25 +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] == ')')
{
return Type.EmptyTypes;
}
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
{
2005-06-01 13:49:30 +04:00
lock(typeof(ClassLoaderWrapper))
{
if(bootstrapClassLoader == null)
{
bootstrapClassLoader = new ClassLoaderWrapper(null);
}
return bootstrapClassLoader;
}
2004-10-04 23:30:53 +04:00
}
2005-06-01 13:49:30 +04:00
internal static ClassLoaderWrapper GetSystemClassLoader()
2004-09-09 15:17:55 +04:00
{
2005-06-01 13:49:30 +04:00
// during static compilation, we don't have a system class loader
if(JVM.IsStaticCompiler)
{
return GetBootstrapClassLoader();
}
if(systemClassLoader == null)
{
systemClassLoader = GetClassLoaderWrapper(JVM.Library.getSystemClassLoader());
}
return systemClassLoader;
2004-09-09 15:17:55 +04:00
}
2002-12-18 19:00:25 +03:00
2005-06-01 13:49:30 +04:00
internal static ClassLoaderWrapper GetClassLoaderWrapper(object javaClassLoader)
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
if(javaClassLoader == null || GetBootstrapClassLoader().javaClassLoader == javaClassLoader)
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
return GetBootstrapClassLoader();
}
lock(javaClassLoaderToClassLoaderWrapper.SyncRoot)
{
ClassLoaderWrapper wrapper = (ClassLoaderWrapper)javaClassLoaderToClassLoaderWrapper[javaClassLoader];
if(wrapper == null)
{
wrapper = new ClassLoaderWrapper(javaClassLoader);
javaClassLoaderToClassLoaderWrapper[javaClassLoader] = wrapper;
}
return wrapper;
2004-08-17 13:05:21 +04:00
}
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
// This only returns the wrapper for a Type if that wrapper has already been created, otherwise
// it returns null
// If the wrapper doesn't exist, that means that the type is either a .NET type or a pre-compiled Java class
internal static TypeWrapper GetWrapperFromTypeFast(Type type)
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
TypeWrapper.AssertFinished(type);
TypeWrapper wrapper = (TypeWrapper)typeToTypeWrapper[type];
if(wrapper == null)
2003-02-15 21:52:32 +03:00
{
2005-06-01 13:49:30 +04:00
string name = (string)remappedTypes[type];
if(name != null)
{
return LoadClassCritical(name);
}
2003-02-15 21:52:32 +03:00
}
2005-06-01 13:49:30 +04:00
return wrapper;
2003-02-15 21:52:32 +03:00
}
2005-06-01 13:49:30 +04:00
internal static TypeWrapper GetWrapperFromType(Type type)
2003-02-15 21:52:32 +03:00
{
2005-06-01 13:49:30 +04:00
//Tracer.Info(Tracer.Runtime, "GetWrapperFromType: {0}", type.AssemblyQualifiedName);
TypeWrapper.AssertFinished(type);
TypeWrapper wrapper = GetWrapperFromTypeFast(type);
if(wrapper == null)
2003-02-17 13:13:16 +03:00
{
2005-06-01 13:49:30 +04:00
Debug.Assert(type != typeof(object) && type != typeof(string));
if(type.IsArray)
2003-02-17 13:13:16 +03:00
{
2005-06-01 13:49:30 +04:00
// it might be an array of a dynamically compiled Java type
int rank = 1;
Type elem = type.GetElementType();
while(elem.IsArray)
{
rank++;
elem = elem.GetElementType();
}
wrapper = GetWrapperFromType(elem);
return wrapper.MakeArrayType(rank);
2003-02-17 13:13:16 +03:00
}
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
// was "loaded" by the bootstrap classloader
// TODO think up a scheme to deal with .NET types that have the same name. Since all .NET types
// appear in the boostrap classloader, we need to devise a scheme to mangle the class name
return GetBootstrapClassLoader().GetWrapperFromBootstrapType(type);
2003-02-17 13:13:16 +03:00
}
2005-06-01 13:49:30 +04:00
return wrapper;
2002-12-18 19:00:25 +03:00
}
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
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
}
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
}
}
2002-12-18 19:00:25 +03:00
}