ikvm-fork/runtime/ClassLoaderWrapper.cs

1206 строки
36 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.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-06-01 13:49:30 +04:00
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();
#if !COMPACT_FRAMEWORK
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 Hashtable dynamicTypes = Hashtable.Synchronized(new Hashtable());
2005-12-07 12:06:32 +03:00
// 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 ArrayList saveDebugAssemblies;
#endif
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;
private static ClassLoaderWrapper systemClassLoader;
private object javaClassLoader;
private Hashtable types = new Hashtable();
private ArrayList nativeLibraries;
private static Hashtable remappedTypes = new Hashtable();
private static int instanceCounter = 0;
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()
{
2005-12-07 12:06:32 +03:00
#if !COMPACT_FRAMEWORK
2005-06-01 13:49:30 +04:00
// 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);
2005-12-07 12:06:32 +03:00
#endif
2005-06-01 13:49:30 +04:00
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
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-12-07 12:06:32 +03:00
#if !COMPACT_FRAMEWORK
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-12-07 12:06:32 +03:00
#endif
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-12-07 12:06:32 +03:00
#if !COMPACT_FRAMEWORK
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-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
{
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-12-07 12:06:32 +03:00
#if !COMPACT_FRAMEWORK
2005-11-01 17:01:42 +03:00
// HACK make sure we don't go through a user class loader when creating
// an array for a precompiled or .NET type
if (type is DynamicTypeWrapper)
{
type = type.GetClassLoader().CreateArrayType(name, type, dims);
}
else
2005-12-07 12:06:32 +03:00
#endif
2005-11-01 17:01:42 +03:00
{
type = GetBootstrapClassLoader().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-12-07 12:06:32 +03:00
#if !COMPACT_FRAMEWORK
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;
}
2005-12-07 12:06:32 +03:00
#endif
2005-06-01 13:49:30 +04:00
}
if(t != null)
{
2005-12-07 12:06:32 +03:00
if(AttributeHelper.IsJavaModule(t.Module))
2005-06-01 13:49:30 +04:00
{
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);
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);
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-12-07 12:06:32 +03:00
#if COMPACT_FRAMEWORK
// TODO figure this out
return GetJavaTypeFromAssembly(JVM.CoreAssembly, name);
#else
Assembly[] assemblies;
#if WHIDBEY
2005-12-19 18:12:49 +03:00
if(JVM.IsStaticCompiler || JVM.IsIkvmStub)
2005-12-07 12:06:32 +03:00
{
assemblies = AppDomain.CurrentDomain.ReflectionOnlyGetAssemblies();
}
else
{
assemblies = AppDomain.CurrentDomain.GetAssemblies();
}
#else
assemblies = AppDomain.CurrentDomain.GetAssemblies();
#endif
foreach(Assembly a in assemblies)
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;
2005-12-07 12:06:32 +03:00
#endif
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
2005-12-07 12:06:32 +03:00
&& AttributeHelper.IsJavaModule(t.Module)
2005-08-25 13:36:36 +04:00
&& !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
2005-12-07 12:06:32 +03:00
&& AttributeHelper.IsJavaModule(t.Module)
2005-08-25 13:36:36 +04:00
&& !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;
2005-12-07 12:06:32 +03:00
#if !COMPACT_FRAMEWORK
2005-06-01 13:49:30 +04:00
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
2005-12-07 12:06:32 +03:00
#endif
2005-06-01 13:49:30 +04:00
{
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);
2005-12-07 12:06:32 +03:00
#if COMPACT_FRAMEWORK
if(!wrapper.IsGhostArray)
{
Debug.Assert(!typeToTypeWrapper.ContainsKey(array), name);
typeToTypeWrapper.Add(array, wrapper);
}
#else
2005-06-01 13:49:30 +04:00
if(!(elementType is TypeBuilder) && !wrapper.IsGhostArray)
{
Debug.Assert(!typeToTypeWrapper.ContainsKey(array), name);
typeToTypeWrapper.Add(array, wrapper);
}
2005-12-07 12:06:32 +03:00
#endif
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;
}
2005-12-07 12:06:32 +03:00
#if !COMPACT_FRAMEWORK
2005-06-01 13:49:30 +04:00
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-12-07 12:06:32 +03:00
#endif
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
2005-12-07 12:06:32 +03:00
#if !COMPACT_FRAMEWORK
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);
2005-12-19 18:12:49 +03:00
AssemblyBuilder assemblyBuilder;
#if WHIDBEY
if(JVM.IsIkvmStub)
{
assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.ReflectionOnly, null, null, null, null, null, true);
}
else
#endif
assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(name, saveDebugImage ? AssemblyBuilderAccess.RunAndSave : AssemblyBuilderAccess.Run, null, null, null, null, null, true);
2005-06-01 13:49:30 +04:00
CustomAttributeBuilder debugAttr = new CustomAttributeBuilder(typeof(DebuggableAttribute).GetConstructor(new Type[] { typeof(bool), typeof(bool) }), new object[] { true, JVM.Debug });
assemblyBuilder.SetCustomAttribute(debugAttr);
2006-01-02 11:15:43 +03:00
ModuleBuilder moduleBuilder = saveDebugImage ? assemblyBuilder.DefineDynamicModule("ikvmdump.exe", "ikvmdump.exe", JVM.Debug) : assemblyBuilder.DefineDynamicModule(name.Name, JVM.Debug);
if(!JVM.NoStackTraceInfo)
{
AttributeHelper.SetSourceFile(moduleBuilder, null);
}
return moduleBuilder;
2004-09-05 13:37:58 +04:00
}
2005-12-07 12:06:32 +03:00
#endif
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] == ')')
{
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
{
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();
}
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)
{
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
}
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
}