2002-12-18 19:00:25 +03:00
|
|
|
/*
|
2008-08-15 16:01:06 +04:00
|
|
|
Copyright (C) 2002-2008 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;
|
2008-11-14 11:42:07 +03:00
|
|
|
#if IKVM_REF_EMIT
|
|
|
|
using IKVM.Reflection.Emit;
|
|
|
|
#elif !COMPACT_FRAMEWORK
|
2005-12-07 12:06:32 +03:00
|
|
|
using System.Reflection.Emit;
|
|
|
|
#endif
|
2002-12-18 19:00:25 +03:00
|
|
|
using System.IO;
|
2008-08-15 16:01:06 +04:00
|
|
|
using System.Collections.Generic;
|
2002-12-18 19:00:25 +03:00
|
|
|
using System.Diagnostics;
|
2006-10-10 20:24:48 +04:00
|
|
|
using System.Threading;
|
2004-09-09 15:17:55 +04:00
|
|
|
using IKVM.Attributes;
|
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
|
2008-08-15 16:01:06 +04:00
|
|
|
internal abstract TypeWrapper DefineClassImpl(Dictionary<string, TypeWrapper> types, ClassFile f, ClassLoaderWrapper classLoader, object protectionDomain);
|
2007-06-12 13:46:53 +04:00
|
|
|
internal abstract bool ReserveName(string name);
|
2008-03-04 10:25:36 +03:00
|
|
|
internal abstract Type DefineUnloadable(string name);
|
2006-07-06 17:53:51 +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();
|
2008-08-15 16:01:06 +04:00
|
|
|
private static readonly Dictionary<Type, TypeWrapper> typeToTypeWrapper = new Dictionary<Type, TypeWrapper>();
|
2006-08-14 11:57:03 +04:00
|
|
|
#if STATIC_COMPILER
|
2005-06-01 13:49:30 +04:00
|
|
|
private static ClassLoaderWrapper bootstrapClassLoader;
|
2006-09-12 13:57:36 +04:00
|
|
|
private TypeWrapperFactory factory;
|
2009-03-07 11:33:33 +03:00
|
|
|
private TypeWrapper circularDependencyHack;
|
2006-08-14 11:57:03 +04:00
|
|
|
#else
|
|
|
|
private static AssemblyClassLoader bootstrapClassLoader;
|
2006-04-10 13:09:09 +04:00
|
|
|
#endif
|
2008-08-15 16:01:06 +04:00
|
|
|
private static readonly Dictionary<Assembly, AssemblyClassLoader> assemblyClassLoaders = new Dictionary<Assembly, AssemblyClassLoader>();
|
|
|
|
private static List<GenericClassLoader> genericClassLoaders;
|
2007-04-23 12:24:33 +04:00
|
|
|
#if !STATIC_COMPILER && !FIRST_PASS
|
|
|
|
private readonly java.lang.ClassLoader javaClassLoader;
|
2007-10-21 11:14:53 +04:00
|
|
|
private static bool customClassLoaderRedirectsLoaded;
|
2008-08-15 16:01:06 +04:00
|
|
|
private static Dictionary<string, string> customClassLoaderRedirects;
|
2007-04-23 12:24:33 +04:00
|
|
|
#endif
|
2008-08-15 16:01:06 +04:00
|
|
|
private Dictionary<string, TypeWrapper> types = new Dictionary<string, TypeWrapper>();
|
|
|
|
private readonly Dictionary<string, Thread> defineClassInProgress = new Dictionary<string, Thread>();
|
|
|
|
private List<IntPtr> nativeLibraries;
|
2006-09-01 11:53:36 +04:00
|
|
|
private CodeGenOptions codegenoptions;
|
2008-08-15 16:01:06 +04:00
|
|
|
private static Dictionary<Type, string> remappedTypes = new Dictionary<Type, string>();
|
2002-12-18 19:00:25 +03:00
|
|
|
|
2006-08-14 11:57:03 +04:00
|
|
|
#if STATIC_COMPILER
|
2005-06-01 13:49:30 +04:00
|
|
|
// HACK this is used by the ahead-of-time compiler to overrule the bootstrap classloader
|
2009-02-19 11:12:05 +03:00
|
|
|
// when we're compiling the core class libraries
|
2005-06-01 13:49:30 +04:00
|
|
|
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;
|
|
|
|
}
|
2006-08-14 11:57:03 +04:00
|
|
|
#endif
|
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
|
|
|
{
|
2007-12-27 18:16:49 +03:00
|
|
|
try
|
|
|
|
{
|
|
|
|
Tracer.Info(Tracer.Runtime, "Core assembly: {0}", coreAssembly.Location);
|
|
|
|
}
|
|
|
|
catch(System.Security.SecurityException)
|
|
|
|
{
|
|
|
|
}
|
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()
|
|
|
|
{
|
2008-08-15 16:01:06 +04:00
|
|
|
lock(typeToTypeWrapper)
|
|
|
|
{
|
|
|
|
return typeToTypeWrapper.Count;
|
|
|
|
}
|
2006-06-26 13:04:03 +04:00
|
|
|
}
|
|
|
|
|
2006-09-01 11:53:36 +04:00
|
|
|
internal ClassLoaderWrapper(CodeGenOptions codegenoptions, object javaClassLoader)
|
2004-08-17 13:05:21 +04:00
|
|
|
{
|
2006-09-01 11:53:36 +04:00
|
|
|
this.codegenoptions = codegenoptions;
|
2007-04-23 12:24:33 +04:00
|
|
|
#if !STATIC_COMPILER && !FIRST_PASS
|
|
|
|
this.javaClassLoader = (java.lang.ClassLoader)javaClassLoader;
|
|
|
|
#endif
|
2004-08-17 13:05:21 +04:00
|
|
|
}
|
2005-06-01 13:49:30 +04:00
|
|
|
|
2007-10-22 13:25:10 +04:00
|
|
|
internal static bool IsDynamicType(Type type)
|
|
|
|
{
|
2008-08-15 16:01:06 +04:00
|
|
|
lock(typeToTypeWrapper)
|
|
|
|
{
|
|
|
|
TypeWrapper tw;
|
|
|
|
typeToTypeWrapper.TryGetValue(type, out tw);
|
|
|
|
return tw is DynamicTypeWrapper;
|
|
|
|
}
|
2007-10-22 13:25:10 +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)
|
|
|
|
{
|
2008-08-15 16:01:06 +04:00
|
|
|
lock(types)
|
|
|
|
{
|
|
|
|
types.Add(tw.Name, tw);
|
|
|
|
}
|
|
|
|
lock(typeToTypeWrapper)
|
|
|
|
{
|
|
|
|
typeToTypeWrapper.Add(type, tw);
|
|
|
|
}
|
|
|
|
remappedTypes.Add(type, tw.Name);
|
2005-06-01 13:49:30 +04:00
|
|
|
}
|
2002-12-18 19:00:25 +03:00
|
|
|
|
2007-10-26 11:11:17 +04:00
|
|
|
// return the TypeWrapper if it is already loaded, this exists for DynamicTypeWrapper.SetupGhosts
|
|
|
|
// and ClassLoader.findLoadedClass()
|
|
|
|
internal virtual TypeWrapper GetLoadedClass(string name)
|
2004-08-17 13:05:21 +04:00
|
|
|
{
|
2008-08-15 16:01:06 +04:00
|
|
|
lock(types)
|
2005-06-01 13:49:30 +04:00
|
|
|
{
|
2008-08-15 16:01:06 +04:00
|
|
|
TypeWrapper tw;
|
|
|
|
types.TryGetValue(name, out tw);
|
|
|
|
return tw;
|
2005-06-01 13:49:30 +04:00
|
|
|
}
|
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
|
|
|
|
2008-08-15 16:01:06 +04:00
|
|
|
lock(types)
|
2005-07-27 19:57:55 +04:00
|
|
|
{
|
2008-08-15 16:01:06 +04:00
|
|
|
TypeWrapper existing;
|
|
|
|
types.TryGetValue(tw.Name, out existing);
|
2005-07-27 19:57:55 +04:00
|
|
|
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
|
2008-08-15 16:01:06 +04:00
|
|
|
return 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-08-29 10:28:34 +04:00
|
|
|
internal bool EmitDebugInfo
|
|
|
|
{
|
|
|
|
get
|
|
|
|
{
|
2006-09-01 11:53:36 +04:00
|
|
|
return (codegenoptions & CodeGenOptions.Debug) != 0;
|
2006-08-29 10:28:34 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal bool EmitStackTraceInfo
|
|
|
|
{
|
|
|
|
get
|
|
|
|
{
|
2006-09-01 11:53:36 +04:00
|
|
|
// NOTE we're negating the flag here!
|
|
|
|
return (codegenoptions & CodeGenOptions.NoStackTraceInfo) == 0;
|
2006-08-29 10:28:34 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal bool StrictFinalFieldSemantics
|
|
|
|
{
|
|
|
|
get
|
|
|
|
{
|
2006-09-01 11:53:36 +04:00
|
|
|
return (codegenoptions & CodeGenOptions.StrictFinalFieldSemantics) != 0;
|
2006-08-29 10:28:34 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal bool NoJNI
|
|
|
|
{
|
|
|
|
get
|
|
|
|
{
|
2006-09-01 11:53:36 +04:00
|
|
|
return (codegenoptions & CodeGenOptions.NoJNI) != 0;
|
2006-08-29 10:28:34 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-02-27 12:04:19 +03:00
|
|
|
internal bool RemoveAsserts
|
|
|
|
{
|
|
|
|
get
|
|
|
|
{
|
|
|
|
return (codegenoptions & CodeGenOptions.RemoveAsserts) != 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-08-29 10:28:34 +04:00
|
|
|
internal virtual string SourcePath
|
|
|
|
{
|
|
|
|
get
|
|
|
|
{
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-03-07 11:33:33 +03:00
|
|
|
#if STATIC_COMPILER
|
|
|
|
internal TypeWrapper LoadCircularDependencyHack(TypeWrapper tw, string name)
|
|
|
|
{
|
|
|
|
if (circularDependencyHack == null)
|
|
|
|
{
|
|
|
|
circularDependencyHack = tw;
|
|
|
|
try
|
|
|
|
{
|
|
|
|
return LoadClassByDottedNameFast(name);
|
|
|
|
}
|
|
|
|
finally
|
|
|
|
{
|
|
|
|
circularDependencyHack = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (circularDependencyHack.Name == name)
|
|
|
|
{
|
|
|
|
return circularDependencyHack;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return LoadClassByDottedNameFast(name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2007-10-22 09:20:42 +04:00
|
|
|
protected virtual void CheckDefineClassAllowed(string className)
|
|
|
|
{
|
|
|
|
// this hook exists so that AssemblyClassLoader can prevent DefineClass when the name is already present in the assembly
|
|
|
|
}
|
|
|
|
|
2006-07-06 17:53:51 +04:00
|
|
|
internal TypeWrapper DefineClass(ClassFile f, object protectionDomain)
|
|
|
|
{
|
|
|
|
string dotnetAssembly = f.IKVMAssemblyAttribute;
|
|
|
|
if(dotnetAssembly != null)
|
|
|
|
{
|
2007-03-29 13:17:19 +04:00
|
|
|
// It's a stub class generated by ikvmstub (or generated by the runtime when getResource was
|
|
|
|
// called on a statically compiled class).
|
|
|
|
ClassLoaderWrapper loader;
|
2006-07-06 17:53:51 +04:00
|
|
|
try
|
|
|
|
{
|
2007-03-29 13:17:19 +04:00
|
|
|
loader = ClassLoaderWrapper.GetAssemblyClassLoaderByName(dotnetAssembly);
|
2006-07-06 17:53:51 +04:00
|
|
|
}
|
|
|
|
catch(Exception x)
|
|
|
|
{
|
2007-03-29 13:17:19 +04:00
|
|
|
// TODO don't catch all exceptions here
|
2006-07-06 17:53:51 +04:00
|
|
|
throw new NoClassDefFoundError(f.Name + " (" + x.Message + ")");
|
|
|
|
}
|
2007-03-29 13:17:19 +04:00
|
|
|
TypeWrapper tw = loader.LoadClassByDottedNameFast(f.Name);
|
2006-07-06 17:53:51 +04:00
|
|
|
if(tw == null)
|
|
|
|
{
|
2007-03-29 13:17:19 +04:00
|
|
|
throw new NoClassDefFoundError(f.Name + " (type not found in " + dotnetAssembly + ")");
|
2006-07-06 17:53:51 +04:00
|
|
|
}
|
|
|
|
return RegisterInitiatingLoader(tw);
|
|
|
|
}
|
2007-10-22 09:20:42 +04:00
|
|
|
CheckDefineClassAllowed(f.Name);
|
2008-08-15 16:01:06 +04:00
|
|
|
lock(types)
|
2006-07-06 17:53:51 +04:00
|
|
|
{
|
2006-10-10 20:24:48 +04:00
|
|
|
if(types.ContainsKey(f.Name))
|
2006-07-11 15:34:44 +04:00
|
|
|
{
|
2006-10-10 20:24:48 +04:00
|
|
|
throw new LinkageError("duplicate class definition: " + f.Name);
|
2006-07-11 15:34:44 +04:00
|
|
|
}
|
2006-10-10 20:24:48 +04:00
|
|
|
// mark the type as "loading in progress", so that we can detect circular dependencies.
|
|
|
|
types.Add(f.Name, null);
|
|
|
|
defineClassInProgress.Add(f.Name, Thread.CurrentThread);
|
|
|
|
}
|
|
|
|
try
|
|
|
|
{
|
|
|
|
return GetTypeWrapperFactory().DefineClassImpl(types, f, this, protectionDomain);
|
|
|
|
}
|
|
|
|
finally
|
|
|
|
{
|
2008-08-15 16:01:06 +04:00
|
|
|
lock(types)
|
2006-07-06 17:53:51 +04:00
|
|
|
{
|
2006-10-10 20:24:48 +04:00
|
|
|
if(types[f.Name] == null)
|
2006-07-06 17:53:51 +04:00
|
|
|
{
|
2006-10-10 20:24:48 +04:00
|
|
|
// 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-10-10 20:24:48 +04:00
|
|
|
defineClassInProgress.Remove(f.Name);
|
2008-08-15 16:01:06 +04:00
|
|
|
Monitor.PulseAll(types);
|
2006-07-06 17:53:51 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2006-03-11 21:35:29 +03:00
|
|
|
|
2006-07-26 18:16:52 +04:00
|
|
|
internal TypeWrapperFactory GetTypeWrapperFactory()
|
|
|
|
{
|
2006-07-06 17:53:51 +04:00
|
|
|
#if COMPACT_FRAMEWORK
|
|
|
|
throw new NoClassDefFoundError("Class loading is not supported on the Compact Framework");
|
2006-09-01 11:53:36 +04:00
|
|
|
#elif STATIC_COMPILER
|
2006-09-12 13:57:36 +04:00
|
|
|
if(factory == null)
|
|
|
|
{
|
|
|
|
factory = new DynamicClassLoader(((CompilerClassLoader)this).CreateModuleBuilder());
|
|
|
|
}
|
|
|
|
return factory;
|
2006-07-06 17:53:51 +04:00
|
|
|
#else
|
2006-09-01 11:53:36 +04:00
|
|
|
return DynamicClassLoader.Instance;
|
2006-07-06 17:53:51 +04:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
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
|
|
|
{
|
2005-06-01 13:49:30 +04:00
|
|
|
TypeWrapper type;
|
2008-08-15 16:01:06 +04:00
|
|
|
lock(types)
|
2002-12-18 19:00:25 +03:00
|
|
|
{
|
2009-03-07 11:11:28 +03:00
|
|
|
if(types.TryGetValue(name, out type) && type == null)
|
2003-08-26 15:24:17 +04:00
|
|
|
{
|
2008-08-15 16:01:06 +04:00
|
|
|
Thread defineThread;
|
|
|
|
if(defineClassInProgress.TryGetValue(name, out defineThread))
|
2006-07-10 13:37:06 +04:00
|
|
|
{
|
2006-10-10 20:24:48 +04:00
|
|
|
if(Thread.CurrentThread == defineThread)
|
2006-07-11 15:34:44 +04:00
|
|
|
{
|
|
|
|
throw new ClassCircularityError(name);
|
|
|
|
}
|
2006-10-10 20:24:48 +04:00
|
|
|
// the requested class is currently being defined by another thread,
|
|
|
|
// so we have to wait on that
|
|
|
|
while(defineClassInProgress.ContainsKey(name))
|
|
|
|
{
|
2008-08-15 16:01:06 +04:00
|
|
|
Monitor.Wait(types);
|
2006-10-10 20:24:48 +04:00
|
|
|
}
|
2008-08-15 16:01:06 +04:00
|
|
|
// the defineClass may have failed, so we need to use TryGetValue
|
|
|
|
types.TryGetValue(name, out type);
|
2006-07-10 13:37:06 +04:00
|
|
|
}
|
2003-08-26 15:24:17 +04:00
|
|
|
}
|
2006-07-11 15:34:44 +04:00
|
|
|
}
|
2006-10-10 20:24:48 +04:00
|
|
|
if(type != null)
|
|
|
|
{
|
|
|
|
return type;
|
|
|
|
}
|
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-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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-10-18 17:54:11 +04:00
|
|
|
internal TypeWrapper LoadGenericClass(string name)
|
2006-07-21 14:18:13 +04:00
|
|
|
{
|
|
|
|
// 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("_$$$_");
|
2007-10-26 11:11:17 +04:00
|
|
|
if(pos <= 0 || !name.EndsWith("_$$$$_"))
|
2006-07-21 14:18:13 +04:00
|
|
|
{
|
|
|
|
return null;
|
|
|
|
}
|
2009-02-04 10:10:59 +03:00
|
|
|
Type type = GetGenericTypeDefinition(DotNetTypeWrapper.DemangleTypeName(name.Substring(0, pos)));
|
|
|
|
if(type == null)
|
2006-07-21 14:18:13 +04:00
|
|
|
{
|
|
|
|
return null;
|
|
|
|
}
|
2008-08-15 16:01:06 +04:00
|
|
|
List<string> typeParamNames = new List<string>();
|
2006-07-21 14:18:13 +04:00
|
|
|
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];
|
2007-03-29 13:17:19 +04:00
|
|
|
// only do the unmangling for non-generic types (because we don't want to convert
|
|
|
|
// the double underscores in two adjacent _$$$_ or _$$$$_ markers)
|
|
|
|
if(s.IndexOf("_$$$_") == -1)
|
|
|
|
{
|
|
|
|
s = s.Replace("__", ".");
|
|
|
|
s = s.Replace("$$005F$$005F", "__");
|
|
|
|
}
|
2006-07-26 11:57:18 +04:00
|
|
|
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));
|
2007-10-22 13:25:10 +04:00
|
|
|
tw.Finish();
|
2006-07-26 11:57:18 +04:00
|
|
|
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;
|
|
|
|
}
|
2006-07-27 18:44:51 +04:00
|
|
|
try
|
|
|
|
{
|
2007-11-26 12:01:35 +03:00
|
|
|
type = type.MakeGenericType(typeArguments);
|
2006-07-27 18:44:51 +04:00
|
|
|
}
|
|
|
|
catch(ArgumentException)
|
|
|
|
{
|
|
|
|
// one of the typeArguments failed to meet the constraints
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
TypeWrapper wrapper = GetWrapperFromType(type);
|
|
|
|
if(wrapper != null && wrapper.Name != name)
|
|
|
|
{
|
|
|
|
// the name specified was not in canonical form
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
return wrapper;
|
2006-07-21 14:18:13 +04:00
|
|
|
}
|
|
|
|
|
2006-07-10 13:37:06 +04:00
|
|
|
protected virtual TypeWrapper LoadClassImpl(string name, bool throwClassNotFoundException)
|
|
|
|
{
|
2007-10-26 11:11:17 +04:00
|
|
|
TypeWrapper tw = LoadGenericClass(name);
|
|
|
|
if(tw != null)
|
|
|
|
{
|
|
|
|
return tw;
|
|
|
|
}
|
2007-04-23 12:24:33 +04:00
|
|
|
#if !STATIC_COMPILER && !FIRST_PASS
|
2006-08-06 13:27:20 +04:00
|
|
|
Profiler.Enter("ClassLoader.loadClass");
|
|
|
|
try
|
2006-07-10 13:37:06 +04:00
|
|
|
{
|
2008-11-18 08:25:06 +03:00
|
|
|
java.lang.Class c = javaClassLoader.loadClassInternal(name);
|
2007-04-23 12:24:33 +04:00
|
|
|
if(c == null)
|
|
|
|
{
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
TypeWrapper type = TypeWrapper.FromClass(c);
|
|
|
|
if(type.Name != name)
|
2006-08-21 09:15:51 +04:00
|
|
|
{
|
|
|
|
// the class loader is trying to trick us
|
|
|
|
return null;
|
|
|
|
}
|
2007-04-23 12:24:33 +04:00
|
|
|
return type;
|
2006-08-06 13:27:20 +04:00
|
|
|
}
|
2007-04-23 12:24:33 +04:00
|
|
|
catch(java.lang.ClassNotFoundException x)
|
2006-08-06 13:27:20 +04:00
|
|
|
{
|
2007-04-23 12:24:33 +04:00
|
|
|
if(throwClassNotFoundException)
|
2006-03-11 21:35:29 +03:00
|
|
|
{
|
2007-04-23 12:24:33 +04:00
|
|
|
throw new ClassLoadingException(ikvm.runtime.Util.mapException(x));
|
2002-12-29 19:27:00 +03:00
|
|
|
}
|
2007-04-23 12:24:33 +04:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
catch(Exception x)
|
|
|
|
{
|
|
|
|
throw new ClassLoadingException(ikvm.runtime.Util.mapException(x));
|
2006-08-06 13:27:20 +04:00
|
|
|
}
|
|
|
|
finally
|
|
|
|
{
|
|
|
|
Profiler.Leave("ClassLoader.loadClass");
|
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
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
}
|
2006-07-27 18:44:51 +04:00
|
|
|
return RegisterInitiatingLoader(new ArrayTypeWrapper(elementTypeWrapper, name));
|
2005-06-01 13:49:30 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
internal object GetJavaClassLoader()
|
2003-12-20 01:19:18 +03:00
|
|
|
{
|
2007-04-23 12:24:33 +04:00
|
|
|
#if FIRST_PASS || STATIC_COMPILER
|
|
|
|
return null;
|
|
|
|
#else
|
2006-06-28 12:07:29 +04:00
|
|
|
return javaClassLoader;
|
2007-04-23 12:24:33 +04:00
|
|
|
#endif
|
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;
|
|
|
|
}
|
2008-08-15 16:01:06 +04:00
|
|
|
List<TypeWrapper> list = new List<TypeWrapper>();
|
2005-06-01 13:49:30 +04:00
|
|
|
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
|
|
|
}
|
2008-08-15 16:01:06 +04:00
|
|
|
return list.ToArray();
|
2002-12-18 19:00:25 +03:00
|
|
|
}
|
2004-09-09 15:17:55 +04:00
|
|
|
|
2006-08-14 11:57:03 +04:00
|
|
|
#if STATIC_COMPILER
|
2005-06-01 13:49:30 +04:00
|
|
|
internal static ClassLoaderWrapper GetBootstrapClassLoader()
|
2006-08-14 11:57:03 +04:00
|
|
|
#else
|
|
|
|
internal static AssemblyClassLoader GetBootstrapClassLoader()
|
|
|
|
#endif
|
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)
|
|
|
|
{
|
2007-10-18 17:54:11 +04: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
|
|
|
{
|
2007-12-19 14:28:09 +03:00
|
|
|
#if FIRST_PASS
|
|
|
|
ClassLoaderWrapper wrapper = null;
|
2008-08-06 16:22:06 +04:00
|
|
|
#else
|
2009-03-02 09:30:13 +03:00
|
|
|
ClassLoaderWrapper wrapper =
|
|
|
|
#if __MonoCS__
|
|
|
|
// MONOBUG the redundant cast to ClassLoaderWrapper is to workaround an mcs bug
|
|
|
|
(ClassLoaderWrapper)(object)
|
|
|
|
#endif
|
|
|
|
((java.lang.ClassLoader)javaClassLoader).wrapper;
|
2007-12-19 14:28:09 +03:00
|
|
|
#endif
|
2005-06-01 13:49:30 +04:00
|
|
|
if(wrapper == null)
|
|
|
|
{
|
2006-09-01 11:53:36 +04:00
|
|
|
CodeGenOptions opt = CodeGenOptions.None;
|
|
|
|
if(System.Diagnostics.Debugger.IsAttached)
|
|
|
|
{
|
|
|
|
opt |= CodeGenOptions.Debug;
|
|
|
|
}
|
|
|
|
wrapper = new ClassLoaderWrapper(opt, javaClassLoader);
|
2007-12-19 14:28:09 +03:00
|
|
|
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);
|
2007-11-26 12:01:35 +03:00
|
|
|
Debug.Assert(!type.ContainsGenericParameters);
|
2006-07-11 11:29:32 +04:00
|
|
|
Debug.Assert(!type.IsPointer);
|
|
|
|
Debug.Assert(!type.IsByRef);
|
2008-08-15 16:01:06 +04:00
|
|
|
TypeWrapper wrapper;
|
|
|
|
lock(typeToTypeWrapper)
|
|
|
|
{
|
|
|
|
typeToTypeWrapper.TryGetValue(type, out wrapper);
|
|
|
|
}
|
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
|
|
|
}
|
2008-08-15 16:01:06 +04:00
|
|
|
string remapped;
|
|
|
|
if(remappedTypes.TryGetValue(type, out remapped))
|
2003-02-17 13:13:16 +03:00
|
|
|
{
|
2006-07-11 11:29:32 +04:00
|
|
|
wrapper = LoadClassCritical(remapped);
|
|
|
|
}
|
2007-01-16 13:14:47 +03:00
|
|
|
else if(IsVector(type))
|
2006-07-11 11:29:32 +04:00
|
|
|
{
|
|
|
|
// it might be an array of a dynamically compiled Java type
|
|
|
|
int rank = 1;
|
|
|
|
Type elem = type.GetElementType();
|
2007-01-16 13:14:47 +03:00
|
|
|
while(IsVector(elem))
|
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-08-14 11:57:03 +04:00
|
|
|
wrapper = GetAssemblyClassLoader(type.Assembly).GetWrapperFromAssemblyType(type);
|
2003-02-17 13:13:16 +03:00
|
|
|
}
|
2008-08-15 16:01:06 +04:00
|
|
|
lock(typeToTypeWrapper)
|
|
|
|
{
|
|
|
|
typeToTypeWrapper[type] = wrapper;
|
|
|
|
}
|
2005-06-01 13:49:30 +04:00
|
|
|
return wrapper;
|
2002-12-18 19:00:25 +03:00
|
|
|
}
|
|
|
|
|
2007-05-27 12:16:58 +04:00
|
|
|
internal static bool IsVector(Type type)
|
2007-01-16 13:14:47 +03:00
|
|
|
{
|
|
|
|
// NOTE it looks like there's no API to distinguish an array of rank 1 from a vector,
|
|
|
|
// so we check if the type name ends in [], which indicates it's a vector
|
|
|
|
// (non-vectors will have [*] or [,]).
|
|
|
|
return type.IsArray && type.Name.EndsWith("[]");
|
|
|
|
}
|
|
|
|
|
2009-02-04 10:10:59 +03:00
|
|
|
internal virtual Type GetGenericTypeDefinition(string name)
|
2006-07-21 14:18:13 +04:00
|
|
|
{
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2006-07-26 14:33:52 +04:00
|
|
|
internal static ClassLoaderWrapper GetGenericClassLoader(TypeWrapper wrapper)
|
|
|
|
{
|
|
|
|
Type type = wrapper.TypeAsTBD;
|
2007-11-26 12:01:35 +03:00
|
|
|
Debug.Assert(type.IsGenericType);
|
|
|
|
Debug.Assert(!type.ContainsGenericParameters);
|
2006-07-26 14:33:52 +04:00
|
|
|
|
2008-08-15 16:01:06 +04:00
|
|
|
List<ClassLoaderWrapper> list = new List<ClassLoaderWrapper>();
|
2006-07-26 14:33:52 +04:00
|
|
|
list.Add(GetAssemblyClassLoader(type.Assembly));
|
2007-11-26 12:01:35 +03:00
|
|
|
foreach(Type arg in type.GetGenericArguments())
|
2006-07-26 14:33:52 +04:00
|
|
|
{
|
|
|
|
ClassLoaderWrapper loader = GetWrapperFromType(arg).GetClassLoader();
|
|
|
|
if(!list.Contains(loader))
|
|
|
|
{
|
|
|
|
list.Add(loader);
|
|
|
|
}
|
|
|
|
}
|
2008-08-15 16:01:06 +04:00
|
|
|
ClassLoaderWrapper[] key = list.ToArray();
|
2007-03-29 13:17:19 +04:00
|
|
|
ClassLoaderWrapper matchingLoader = GetGenericClassLoaderByKey(key);
|
|
|
|
matchingLoader.RegisterInitiatingLoader(wrapper);
|
|
|
|
return matchingLoader;
|
|
|
|
}
|
|
|
|
|
2009-02-27 09:05:22 +03:00
|
|
|
#if !STATIC_COMPILER && !FIRST_PASS
|
|
|
|
internal static object DoPrivileged(java.security.PrivilegedAction action)
|
|
|
|
{
|
|
|
|
return java.security.AccessController.doPrivileged(action, ikvm.@internal.CallerID.create(typeof(java.lang.ClassLoader).TypeHandle));
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2007-03-29 13:17:19 +04:00
|
|
|
private static ClassLoaderWrapper GetGenericClassLoaderByKey(ClassLoaderWrapper[] key)
|
|
|
|
{
|
2006-07-26 14:33:52 +04:00
|
|
|
lock(wrapperLock)
|
|
|
|
{
|
|
|
|
if(genericClassLoaders == null)
|
|
|
|
{
|
2008-08-15 16:01:06 +04:00
|
|
|
genericClassLoaders = new List<GenericClassLoader>();
|
2006-07-26 14:33:52 +04:00
|
|
|
}
|
|
|
|
foreach(GenericClassLoader loader in genericClassLoaders)
|
|
|
|
{
|
|
|
|
if(loader.Matches(key))
|
|
|
|
{
|
2007-03-29 13:17:19 +04:00
|
|
|
return loader;
|
2006-07-26 14:33:52 +04:00
|
|
|
}
|
|
|
|
}
|
2007-03-29 13:17:19 +04:00
|
|
|
object javaClassLoader = null;
|
2007-12-19 14:28:09 +03:00
|
|
|
#if !STATIC_COMPILER && !FIRST_PASS
|
2009-02-27 09:05:22 +03:00
|
|
|
javaClassLoader = DoPrivileged(new CreateAssemblyClassLoader(null));
|
2006-08-14 11:57:03 +04:00
|
|
|
#endif
|
2007-03-29 13:17:19 +04:00
|
|
|
GenericClassLoader newLoader = new GenericClassLoader(key, javaClassLoader);
|
2007-12-19 14:28:09 +03:00
|
|
|
SetWrapperForClassLoader(javaClassLoader, newLoader);
|
2007-03-29 13:17:19 +04:00
|
|
|
genericClassLoaders.Add(newLoader);
|
|
|
|
return newLoader;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-03-02 09:30:13 +03:00
|
|
|
#if !STATIC_COMPILER && __MonoCS__
|
2008-05-20 11:36:50 +04:00
|
|
|
// MONOBUG this weird hack is to work around an mcs bug
|
|
|
|
private static void SetClassLoadWrapperHack<T>(ref T field, ClassLoaderWrapper wrapper)
|
|
|
|
{
|
|
|
|
field = (T)(object)wrapper;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2007-12-19 14:28:09 +03:00
|
|
|
private static void SetWrapperForClassLoader(object javaClassLoader, ClassLoaderWrapper wrapper)
|
|
|
|
{
|
2008-08-06 16:22:06 +04:00
|
|
|
#if !STATIC_COMPILER && !FIRST_PASS
|
2009-03-02 09:30:13 +03:00
|
|
|
#if __MonoCS__
|
2008-05-20 11:36:50 +04:00
|
|
|
SetClassLoadWrapperHack(ref ((java.lang.ClassLoader)javaClassLoader).wrapper, wrapper);
|
2009-03-02 09:30:13 +03:00
|
|
|
#else
|
|
|
|
((java.lang.ClassLoader)javaClassLoader).wrapper = wrapper;
|
|
|
|
#endif
|
2007-12-19 14:28:09 +03:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2007-03-29 13:17:19 +04:00
|
|
|
internal static ClassLoaderWrapper GetGenericClassLoaderByName(string name)
|
|
|
|
{
|
|
|
|
Debug.Assert(name.StartsWith("[[") && name.EndsWith("]]"));
|
2008-08-15 16:01:06 +04:00
|
|
|
Stack<List<ClassLoaderWrapper>> stack = new Stack<List<ClassLoaderWrapper>>();
|
|
|
|
List<ClassLoaderWrapper> list = null;
|
2007-03-29 13:17:19 +04:00
|
|
|
for(int i = 0; i < name.Length; i++)
|
|
|
|
{
|
|
|
|
if(name[i] == '[')
|
|
|
|
{
|
|
|
|
if(name[i + 1] == '[')
|
|
|
|
{
|
|
|
|
stack.Push(list);
|
2008-08-15 16:01:06 +04:00
|
|
|
list = new List<ClassLoaderWrapper>();
|
2007-03-29 13:17:19 +04:00
|
|
|
if(name[i + 2] == '[')
|
|
|
|
{
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int start = i + 1;
|
|
|
|
i = name.IndexOf(']', i);
|
|
|
|
list.Add(ClassLoaderWrapper.GetAssemblyClassLoaderByName(name.Substring(start, i - start)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(name[i] == ']')
|
|
|
|
{
|
2008-08-15 16:01:06 +04:00
|
|
|
ClassLoaderWrapper loader = GetGenericClassLoaderByKey(list.ToArray());
|
|
|
|
list = stack.Pop();
|
2007-03-29 13:17:19 +04:00
|
|
|
if(list == null)
|
|
|
|
{
|
|
|
|
return loader;
|
|
|
|
}
|
|
|
|
list.Add(loader);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
throw new InvalidOperationException();
|
2006-07-26 14:33:52 +04:00
|
|
|
}
|
|
|
|
}
|
2007-03-29 13:17:19 +04:00
|
|
|
throw new InvalidOperationException();
|
|
|
|
}
|
|
|
|
|
|
|
|
internal static ClassLoaderWrapper GetAssemblyClassLoaderByName(string name)
|
|
|
|
{
|
|
|
|
if(name.StartsWith("[["))
|
|
|
|
{
|
|
|
|
return GetGenericClassLoaderByName(name);
|
|
|
|
}
|
2007-11-26 11:38:38 +03:00
|
|
|
#if STATIC_COMPILER
|
2007-03-29 13:17:19 +04:00
|
|
|
return ClassLoaderWrapper.GetAssemblyClassLoader(Assembly.ReflectionOnlyLoad(name));
|
|
|
|
#else
|
|
|
|
return ClassLoaderWrapper.GetAssemblyClassLoader(Assembly.Load(name));
|
|
|
|
#endif
|
2006-07-26 14:33:52 +04:00
|
|
|
}
|
|
|
|
|
2006-12-05 10:52:25 +03:00
|
|
|
internal static int GetGenericClassLoaderId(ClassLoaderWrapper wrapper)
|
|
|
|
{
|
|
|
|
lock(wrapperLock)
|
|
|
|
{
|
2008-08-15 16:01:06 +04:00
|
|
|
return genericClassLoaders.IndexOf(wrapper as GenericClassLoader);
|
2006-12-05 10:52:25 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal static ClassLoaderWrapper GetGenericClassLoaderById(int id)
|
|
|
|
{
|
|
|
|
lock(wrapperLock)
|
|
|
|
{
|
2008-08-15 16:01:06 +04:00
|
|
|
return genericClassLoaders[id];
|
2006-12-05 10:52:25 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-05-15 13:08:01 +04:00
|
|
|
// this method only supports .NET or pre-compiled Java assemblies
|
2006-08-14 11:57:03 +04:00
|
|
|
internal static AssemblyClassLoader GetAssemblyClassLoader(Assembly assembly)
|
2006-05-15 13:08:01 +04:00
|
|
|
{
|
2008-11-14 11:42:07 +03:00
|
|
|
#if !COMPACT_FRAMEWORK && !IKVM_REF_EMIT
|
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
|
|
|
|
2007-10-21 11:14:53 +04:00
|
|
|
ConstructorInfo customClassLoaderCtor = null;
|
|
|
|
AssemblyClassLoader loader;
|
|
|
|
object javaClassLoader = null;
|
2006-08-14 11:57:03 +04:00
|
|
|
lock(wrapperLock)
|
2006-05-15 13:08:01 +04:00
|
|
|
{
|
2008-08-15 16:01:06 +04:00
|
|
|
if(!assemblyClassLoaders.TryGetValue(assembly, out loader))
|
2006-05-15 13:08:01 +04:00
|
|
|
{
|
2008-12-23 10:11:29 +03:00
|
|
|
// If the assembly is a part of a multi-assembly shared class loader,
|
|
|
|
// it will export the __<MainAssembly> type from the main assembly in the group.
|
|
|
|
Type forwarder = assembly.GetType("__<MainAssembly>");
|
|
|
|
if(forwarder != null)
|
|
|
|
{
|
|
|
|
Assembly mainAssembly = forwarder.Assembly;
|
|
|
|
if(mainAssembly != assembly)
|
|
|
|
{
|
|
|
|
loader = GetAssemblyClassLoader(mainAssembly);
|
|
|
|
assemblyClassLoaders[assembly] = loader;
|
|
|
|
return loader;
|
|
|
|
}
|
|
|
|
}
|
2008-12-24 08:11:48 +03:00
|
|
|
if(assembly == JVM.CoreAssembly)
|
|
|
|
{
|
2009-02-19 11:12:05 +03:00
|
|
|
// This cast is necessary for ikvmc and a no-op for the runtime.
|
|
|
|
// Note that the cast cannot fail, because ikvmc will only return a non AssemblyClassLoader
|
|
|
|
// from GetBootstrapClassLoader() when compiling the core assembly and in that case JVM.CoreAssembly
|
|
|
|
// will be null.
|
|
|
|
return (AssemblyClassLoader)GetBootstrapClassLoader();
|
2008-12-24 08:11:48 +03:00
|
|
|
}
|
2009-02-19 11:12:05 +03:00
|
|
|
#if !STATIC_COMPILER && !FIRST_PASS
|
2007-11-26 12:01:35 +03:00
|
|
|
if(!assembly.ReflectionOnly)
|
2007-10-21 11:14:53 +04:00
|
|
|
{
|
|
|
|
Type customClassLoaderClass = null;
|
|
|
|
LoadCustomClassLoaderRedirects();
|
|
|
|
if(customClassLoaderRedirects != null)
|
|
|
|
{
|
|
|
|
string assemblyName = assembly.FullName;
|
2008-08-15 16:01:06 +04:00
|
|
|
foreach(KeyValuePair<string, string> kv in customClassLoaderRedirects)
|
2007-10-21 11:14:53 +04:00
|
|
|
{
|
2008-08-15 16:01:06 +04:00
|
|
|
string asm = kv.Key;
|
2007-10-21 11:14:53 +04:00
|
|
|
// we only support matching on the assembly's simple name,
|
|
|
|
// because there appears to be no viable alternative.
|
|
|
|
// On .NET 2.0 there is AssemblyName.ReferenceMatchesDefinition()
|
|
|
|
// but it is broken (and .NET 2.0 specific).
|
|
|
|
if(assemblyName.StartsWith(asm + ","))
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
2008-08-15 16:01:06 +04:00
|
|
|
customClassLoaderClass = Type.GetType(kv.Value, true);
|
2007-10-21 11:14:53 +04:00
|
|
|
}
|
|
|
|
catch(Exception x)
|
|
|
|
{
|
2008-08-15 16:01:06 +04:00
|
|
|
Tracer.Error(Tracer.Runtime, "Unable to load custom class loader {0} specified in app.config for assembly {1}: {2}", kv.Value, assembly, x);
|
2007-10-21 11:14:53 +04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(customClassLoaderClass == null)
|
|
|
|
{
|
|
|
|
object[] attribs = assembly.GetCustomAttributes(typeof(CustomAssemblyClassLoaderAttribute), false);
|
|
|
|
if(attribs.Length == 1)
|
|
|
|
{
|
|
|
|
customClassLoaderClass = ((CustomAssemblyClassLoaderAttribute)attribs[0]).Type;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(customClassLoaderClass != null)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
2007-10-26 09:14:36 +04:00
|
|
|
if(!customClassLoaderClass.IsPublic && !customClassLoaderClass.Assembly.Equals(assembly))
|
|
|
|
{
|
|
|
|
throw new Exception("Type not accessible");
|
|
|
|
}
|
2007-10-21 11:14:53 +04:00
|
|
|
// NOTE we're creating an uninitialized instance of the custom class loader here, so that getClassLoader will return the proper object
|
|
|
|
// when it is called during the construction of the custom class loader later on. This still doesn't make it safe to use the custom
|
|
|
|
// class loader before it is constructed, but at least the object instance is valid and should anyone cache it, they will get the
|
|
|
|
// right object to use later on.
|
|
|
|
// Note also that we're not running the constructor here, because we don't want to run user code while holding a global lock.
|
2007-12-27 18:16:49 +03:00
|
|
|
javaClassLoader = (java.lang.ClassLoader)CreateUnitializedCustomClassLoader(customClassLoaderClass);
|
2007-10-25 16:57:40 +04:00
|
|
|
customClassLoaderCtor = customClassLoaderClass.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[] { typeof(Assembly) }, null);
|
2007-10-21 11:14:53 +04:00
|
|
|
if(customClassLoaderCtor == null)
|
|
|
|
{
|
|
|
|
javaClassLoader = null;
|
|
|
|
throw new Exception("No constructor");
|
|
|
|
}
|
2007-10-26 09:14:36 +04:00
|
|
|
if(!customClassLoaderCtor.IsPublic && !customClassLoaderClass.Assembly.Equals(assembly))
|
|
|
|
{
|
|
|
|
javaClassLoader = null;
|
|
|
|
throw new Exception("Constructor not accessible");
|
|
|
|
}
|
2007-10-21 11:14:53 +04:00
|
|
|
Tracer.Info(Tracer.Runtime, "Created custom assembly class loader {0} for assembly {1}", customClassLoaderClass.FullName, assembly);
|
|
|
|
}
|
|
|
|
catch(Exception x)
|
|
|
|
{
|
|
|
|
Tracer.Error(Tracer.Runtime, "Unable to create custom assembly class loader {0} for {1}: {2}", customClassLoaderClass.FullName, assembly, x);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(javaClassLoader == null)
|
2006-08-14 11:57:03 +04:00
|
|
|
{
|
2009-02-27 09:05:22 +03:00
|
|
|
javaClassLoader = DoPrivileged(new CreateAssemblyClassLoader(assembly));
|
2006-08-14 11:57:03 +04:00
|
|
|
}
|
2007-10-18 17:54:11 +04:00
|
|
|
#endif
|
2007-10-25 10:28:26 +04:00
|
|
|
loader = new AssemblyClassLoader(assembly, javaClassLoader, customClassLoaderCtor != null);
|
2006-08-14 11:57:03 +04:00
|
|
|
assemblyClassLoaders[assembly] = loader;
|
|
|
|
#if !STATIC_COMPILER
|
2007-10-21 11:14:53 +04:00
|
|
|
if(customClassLoaderCtor != null)
|
|
|
|
{
|
|
|
|
loader.SetInitInProgress();
|
|
|
|
}
|
2006-08-14 11:57:03 +04:00
|
|
|
if(javaClassLoader != null)
|
|
|
|
{
|
2007-12-19 14:28:09 +03:00
|
|
|
SetWrapperForClassLoader(javaClassLoader, loader);
|
2006-08-14 11:57:03 +04:00
|
|
|
}
|
|
|
|
#endif
|
2006-05-15 13:08:01 +04:00
|
|
|
}
|
2007-10-21 11:14:53 +04:00
|
|
|
}
|
|
|
|
#if !STATIC_COMPILER && !FIRST_PASS
|
|
|
|
if(customClassLoaderCtor != null)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
2009-02-27 09:05:22 +03:00
|
|
|
DoPrivileged(new CustomClassLoaderCtorCaller(customClassLoaderCtor, javaClassLoader, assembly));
|
2007-10-21 11:14:53 +04:00
|
|
|
}
|
|
|
|
finally
|
|
|
|
{
|
|
|
|
loader.SetInitDone();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
loader.WaitInitDone();
|
|
|
|
#endif
|
|
|
|
return loader;
|
|
|
|
}
|
|
|
|
|
2008-05-20 11:43:42 +04:00
|
|
|
#if !STATIC_COMPILER && !FIRST_PASS
|
2007-12-27 18:16:49 +03:00
|
|
|
private static object CreateUnitializedCustomClassLoader(Type customClassLoaderClass)
|
|
|
|
{
|
|
|
|
return System.Runtime.Serialization.FormatterServices.GetUninitializedObject(customClassLoaderClass);
|
|
|
|
}
|
|
|
|
|
2007-10-21 11:14:53 +04:00
|
|
|
private static void LoadCustomClassLoaderRedirects()
|
|
|
|
{
|
|
|
|
// this method assumes that we hold a global lock
|
|
|
|
if(!customClassLoaderRedirectsLoaded)
|
|
|
|
{
|
|
|
|
customClassLoaderRedirectsLoaded = true;
|
|
|
|
try
|
|
|
|
{
|
2008-08-28 10:50:16 +04:00
|
|
|
foreach(string key in System.Configuration.ConfigurationManager.AppSettings.AllKeys)
|
2007-10-21 11:14:53 +04:00
|
|
|
{
|
|
|
|
const string prefix = "ikvm-classloader:";
|
|
|
|
if(key.StartsWith(prefix))
|
|
|
|
{
|
|
|
|
if(customClassLoaderRedirects == null)
|
|
|
|
{
|
2008-08-15 16:01:06 +04:00
|
|
|
customClassLoaderRedirects = new Dictionary<string, string>();
|
2007-10-21 11:14:53 +04:00
|
|
|
}
|
2007-11-26 08:50:57 +03:00
|
|
|
customClassLoaderRedirects[key.Substring(prefix.Length)] = System.Configuration.ConfigurationManager.AppSettings.Get(key);
|
2007-10-21 11:14:53 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch(Exception x)
|
|
|
|
{
|
|
|
|
Tracer.Error(Tracer.Runtime, "Error while reading custom class loader redirects: {0}", x);
|
|
|
|
}
|
2006-05-15 13:08:01 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-12-19 14:28:09 +03:00
|
|
|
sealed class CreateAssemblyClassLoader : java.security.PrivilegedAction
|
|
|
|
{
|
|
|
|
private Assembly assembly;
|
|
|
|
|
|
|
|
internal CreateAssemblyClassLoader(Assembly assembly)
|
|
|
|
{
|
|
|
|
this.assembly = assembly;
|
|
|
|
}
|
|
|
|
|
|
|
|
public object run()
|
|
|
|
{
|
|
|
|
return new ikvm.runtime.AssemblyClassLoader(assembly);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-10-21 11:14:53 +04:00
|
|
|
sealed class CustomClassLoaderCtorCaller : java.security.PrivilegedAction
|
|
|
|
{
|
|
|
|
private ConstructorInfo ctor;
|
|
|
|
private object classLoader;
|
|
|
|
private Assembly assembly;
|
|
|
|
|
|
|
|
internal CustomClassLoaderCtorCaller(ConstructorInfo ctor, object classLoader, Assembly assembly)
|
|
|
|
{
|
|
|
|
this.ctor = ctor;
|
|
|
|
this.classLoader = classLoader;
|
|
|
|
this.assembly = assembly;
|
|
|
|
}
|
|
|
|
|
|
|
|
public object run()
|
|
|
|
{
|
|
|
|
ctor.Invoke(classLoader, new object[] { assembly });
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2005-06-01 13:49:30 +04:00
|
|
|
internal static void SetWrapperForType(Type type, TypeWrapper wrapper)
|
|
|
|
{
|
|
|
|
TypeWrapper.AssertFinished(type);
|
2008-08-15 16:01:06 +04:00
|
|
|
lock(typeToTypeWrapper)
|
|
|
|
{
|
|
|
|
typeToTypeWrapper.Add(type, wrapper);
|
|
|
|
}
|
2005-06-01 13:49:30 +04:00
|
|
|
}
|
2004-11-23 20:46:39 +03:00
|
|
|
|
2007-08-08 16:50:48 +04:00
|
|
|
internal static void ResetWrapperForType(Type type, TypeWrapper wrapper)
|
|
|
|
{
|
|
|
|
TypeWrapper.AssertFinished(type);
|
2008-08-15 16:01:06 +04:00
|
|
|
lock(typeToTypeWrapper)
|
|
|
|
{
|
|
|
|
typeToTypeWrapper[type] = wrapper;
|
|
|
|
}
|
2007-08-08 16:50:48 +04: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)
|
|
|
|
{
|
2008-08-15 16:01:06 +04:00
|
|
|
nativeLibraries = new List<IntPtr>();
|
2005-06-01 13:49:30 +04:00
|
|
|
}
|
|
|
|
nativeLibraries.Add(p);
|
2004-08-30 19:56:23 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-03-09 12:01:36 +03:00
|
|
|
internal void UnregisterNativeLibrary(IntPtr p)
|
|
|
|
{
|
|
|
|
lock(this)
|
|
|
|
{
|
|
|
|
nativeLibraries.Remove(p);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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];
|
|
|
|
}
|
2008-08-15 16:01:06 +04:00
|
|
|
return nativeLibraries.ToArray();
|
2004-08-30 19:56:23 +04:00
|
|
|
}
|
|
|
|
}
|
2005-02-23 15:56:15 +03:00
|
|
|
|
2007-04-23 12:24:33 +04:00
|
|
|
#if !STATIC_COMPILER && !FIRST_PASS
|
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
|
|
|
}
|
2007-04-23 12:24:33 +04:00
|
|
|
#endif
|
2007-12-17 13:59:02 +03:00
|
|
|
|
2009-02-10 10:24:30 +03:00
|
|
|
internal virtual bool InternalsVisibleToImpl(TypeWrapper wrapper, TypeWrapper friend)
|
2007-12-17 13:59:02 +03:00
|
|
|
{
|
2009-02-10 10:24:30 +03:00
|
|
|
Debug.Assert(wrapper.GetClassLoader() == this);
|
|
|
|
return this == friend.GetClassLoader();
|
2007-12-17 13:59:02 +03:00
|
|
|
}
|
2005-02-23 15:56:15 +03:00
|
|
|
}
|
2006-02-22 17:44:07 +03:00
|
|
|
|
2006-08-14 11:57:03 +04:00
|
|
|
class GenericClassLoader : ClassLoaderWrapper
|
2006-02-22 17:44:07 +03:00
|
|
|
{
|
2006-08-14 11:57:03 +04:00
|
|
|
private ClassLoaderWrapper[] delegates;
|
|
|
|
|
|
|
|
internal GenericClassLoader(ClassLoaderWrapper[] delegates, object javaClassLoader)
|
2006-09-01 11:53:36 +04:00
|
|
|
: base(CodeGenOptions.None, javaClassLoader)
|
2006-02-22 17:44:07 +03:00
|
|
|
{
|
2006-08-14 11:57:03 +04:00
|
|
|
this.delegates = delegates;
|
2006-02-22 17:44:07 +03:00
|
|
|
}
|
2006-07-10 13:37:06 +04:00
|
|
|
|
2006-08-14 11:57:03 +04:00
|
|
|
internal bool Matches(ClassLoaderWrapper[] key)
|
2006-07-10 13:37:06 +04:00
|
|
|
{
|
2006-08-14 11:57:03 +04:00
|
|
|
if(key.Length == delegates.Length)
|
2006-07-10 13:37:06 +04:00
|
|
|
{
|
2006-08-14 11:57:03 +04:00
|
|
|
for(int i = 0; i < key.Length; i++)
|
|
|
|
{
|
|
|
|
if(key[i] != delegates[i])
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
2006-07-10 13:37:06 +04:00
|
|
|
}
|
2006-08-14 11:57:03 +04:00
|
|
|
return false;
|
2006-07-10 13:37:06 +04:00
|
|
|
}
|
|
|
|
|
2009-02-04 10:10:59 +03:00
|
|
|
internal override Type GetGenericTypeDefinition(string name)
|
2006-07-10 13:37:06 +04:00
|
|
|
{
|
2006-08-14 11:57:03 +04:00
|
|
|
foreach(ClassLoaderWrapper loader in delegates)
|
2006-07-10 13:37:06 +04:00
|
|
|
{
|
2009-02-04 10:10:59 +03:00
|
|
|
Type t = loader.GetGenericTypeDefinition(name);
|
2006-08-14 11:57:03 +04:00
|
|
|
if(t != null)
|
|
|
|
{
|
|
|
|
return t;
|
|
|
|
}
|
2006-07-10 13:37:06 +04:00
|
|
|
}
|
2006-08-14 11:57:03 +04:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected override TypeWrapper LoadClassImpl(string name, bool throwClassNotFoundException)
|
|
|
|
{
|
2007-10-26 11:11:17 +04:00
|
|
|
TypeWrapper tw = LoadGenericClass(name);
|
|
|
|
if(tw != null)
|
|
|
|
{
|
|
|
|
return tw;
|
|
|
|
}
|
2006-08-14 11:57:03 +04:00
|
|
|
foreach(ClassLoaderWrapper loader in delegates)
|
2006-07-10 13:37:06 +04:00
|
|
|
{
|
2007-10-26 11:11:17 +04:00
|
|
|
tw = loader.LoadClassByDottedNameFast(name);
|
2006-08-14 11:57:03 +04:00
|
|
|
if(tw != null)
|
|
|
|
{
|
|
|
|
return tw;
|
|
|
|
}
|
2006-07-10 13:37:06 +04:00
|
|
|
}
|
2006-08-14 11:57:03 +04:00
|
|
|
return null;
|
|
|
|
}
|
2007-03-29 13:17:19 +04:00
|
|
|
|
|
|
|
internal string GetName()
|
|
|
|
{
|
|
|
|
System.Text.StringBuilder sb = new System.Text.StringBuilder();
|
|
|
|
sb.Append('[');
|
|
|
|
foreach(ClassLoaderWrapper loader in delegates)
|
|
|
|
{
|
|
|
|
sb.Append('[');
|
|
|
|
GenericClassLoader gcl = loader as GenericClassLoader;
|
|
|
|
if(gcl != null)
|
|
|
|
{
|
|
|
|
sb.Append(gcl.GetName());
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2009-02-10 10:27:25 +03:00
|
|
|
sb.Append(((AssemblyClassLoader)loader).MainAssembly.FullName);
|
2007-03-29 13:17:19 +04:00
|
|
|
}
|
|
|
|
sb.Append(']');
|
|
|
|
}
|
|
|
|
sb.Append(']');
|
|
|
|
return sb.ToString();
|
|
|
|
}
|
2006-08-14 11:57:03 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
class AssemblyClassLoader : ClassLoaderWrapper
|
|
|
|
{
|
2008-12-23 10:11:29 +03:00
|
|
|
private AssemblyLoader assemblyLoader;
|
2009-02-27 09:28:50 +03:00
|
|
|
private string[] references;
|
2006-08-14 11:57:03 +04:00
|
|
|
private AssemblyClassLoader[] delegates;
|
|
|
|
private bool isReflectionOnly;
|
2007-11-26 08:50:57 +03:00
|
|
|
#if !STATIC_COMPILER
|
2007-10-21 11:14:53 +04:00
|
|
|
private Thread initializerThread;
|
2007-10-26 11:11:17 +04:00
|
|
|
private volatile object protectionDomain;
|
2007-11-26 08:50:57 +03:00
|
|
|
#endif
|
2007-10-25 10:28:26 +04:00
|
|
|
private bool hasCustomClassLoader;
|
2008-12-23 10:11:29 +03:00
|
|
|
private Dictionary<int, List<int>> exports;
|
2009-02-27 09:28:50 +03:00
|
|
|
private string[] exportedAssemblyNames;
|
2008-12-23 10:11:29 +03:00
|
|
|
private AssemblyLoader[] exportedAssemblies;
|
|
|
|
private Dictionary<Assembly, AssemblyLoader> exportedLoaders;
|
2006-08-14 11:57:03 +04:00
|
|
|
|
2008-12-23 10:11:29 +03:00
|
|
|
private sealed class AssemblyLoader
|
2006-08-14 11:57:03 +04:00
|
|
|
{
|
2008-12-23 10:11:29 +03:00
|
|
|
private readonly Assembly assembly;
|
|
|
|
private bool[] isJavaModule;
|
|
|
|
private Module[] modules;
|
|
|
|
private Dictionary<string, string> nameMap;
|
|
|
|
private bool hasDotNetModule;
|
2009-02-10 10:24:30 +03:00
|
|
|
private AssemblyName[] internalsVisibleTo;
|
2008-12-23 10:11:29 +03:00
|
|
|
|
|
|
|
internal AssemblyLoader(Assembly assembly)
|
2006-07-10 13:37:06 +04:00
|
|
|
{
|
2008-12-23 10:11:29 +03:00
|
|
|
this.assembly = assembly;
|
|
|
|
modules = assembly.GetModules(false);
|
|
|
|
isJavaModule = new bool[modules.Length];
|
|
|
|
for (int i = 0; i < modules.Length; i++)
|
2006-07-10 13:37:06 +04:00
|
|
|
{
|
2009-03-02 07:51:05 +03:00
|
|
|
object[] attr;
|
|
|
|
try
|
|
|
|
{
|
|
|
|
attr = AttributeHelper.GetJavaModuleAttributes(modules[i]);
|
|
|
|
}
|
|
|
|
catch (Exception x)
|
|
|
|
{
|
|
|
|
// HACK we handle exceptions here, because there is at least one obfuscator that produces
|
|
|
|
// invalid assemblies that cause Module.GetCustomAttributes() to throw an exception
|
|
|
|
JVM.CriticalFailure("Unexpected exception", x);
|
|
|
|
throw null;
|
|
|
|
}
|
2008-12-23 10:11:29 +03:00
|
|
|
if (attr.Length > 0)
|
2006-07-10 13:37:06 +04:00
|
|
|
{
|
2008-12-23 10:11:29 +03:00
|
|
|
isJavaModule[i] = true;
|
|
|
|
foreach (JavaModuleAttribute jma in attr)
|
2006-08-14 11:57:03 +04:00
|
|
|
{
|
2008-12-23 10:11:29 +03:00
|
|
|
string[] map = jma.GetClassMap();
|
|
|
|
if (map != null)
|
2006-08-14 11:57:03 +04:00
|
|
|
{
|
2008-12-23 10:11:29 +03:00
|
|
|
if (nameMap == null)
|
|
|
|
{
|
|
|
|
nameMap = new Dictionary<string, string>();
|
|
|
|
}
|
|
|
|
for (int j = 0; j < map.Length; j += 2)
|
|
|
|
{
|
|
|
|
string key = map[j];
|
|
|
|
string val = map[j + 1];
|
|
|
|
// TODO if there is a name clash between modules, this will throw.
|
|
|
|
// Figure out how to handle that.
|
|
|
|
nameMap.Add(key, val);
|
|
|
|
}
|
2006-10-09 12:29:42 +04:00
|
|
|
}
|
2008-12-23 10:11:29 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
hasDotNetModule = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal bool HasJavaModule
|
|
|
|
{
|
|
|
|
get
|
|
|
|
{
|
|
|
|
for (int i = 0; i < isJavaModule.Length; i++)
|
|
|
|
{
|
|
|
|
if (isJavaModule[i])
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal Assembly Assembly
|
|
|
|
{
|
|
|
|
get { return assembly; }
|
|
|
|
}
|
|
|
|
|
|
|
|
private Type GetType(string name)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
return assembly.GetType(name);
|
|
|
|
}
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
private Type GetType(Module mod, string name)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
return mod.GetType(name);
|
|
|
|
}
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
private Type GetJavaType(Module mod, string name)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
string n = null;
|
|
|
|
if (nameMap != null)
|
|
|
|
{
|
|
|
|
nameMap.TryGetValue(name, out n);
|
|
|
|
}
|
|
|
|
Type t = GetType(mod, n != null ? n : name);
|
|
|
|
if (t == null)
|
|
|
|
{
|
|
|
|
n = name.Replace('$', '+');
|
|
|
|
if (!ReferenceEquals(n, name))
|
|
|
|
{
|
|
|
|
t = GetType(n);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (t != null
|
|
|
|
&& !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);
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal TypeWrapper DoLoad(string name)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < modules.Length; i++)
|
|
|
|
{
|
|
|
|
if (isJavaModule[i])
|
|
|
|
{
|
|
|
|
Type type = GetJavaType(modules[i], name);
|
|
|
|
if (type != null)
|
|
|
|
{
|
|
|
|
// check the name to make sure that the canonical name was used
|
|
|
|
if (CompiledTypeWrapper.GetName(type) == name)
|
2006-10-09 12:29:42 +04:00
|
|
|
{
|
2008-12-23 10:11:29 +03:00
|
|
|
return CompiledTypeWrapper.newInstance(name, type);
|
2006-08-14 11:57:03 +04:00
|
|
|
}
|
|
|
|
}
|
2006-07-10 13:37:06 +04:00
|
|
|
}
|
2008-12-23 10:11:29 +03:00
|
|
|
else
|
|
|
|
{
|
|
|
|
// TODO should we catch ArgumentException and prohibit array, pointer and byref here?
|
|
|
|
Type type = GetType(modules[i], DotNetTypeWrapper.DemangleTypeName(name));
|
|
|
|
if (type != null && DotNetTypeWrapper.IsAllowedOutside(type))
|
|
|
|
{
|
|
|
|
// check the name to make sure that the canonical name was used
|
|
|
|
if (DotNetTypeWrapper.GetName(type) == name)
|
|
|
|
{
|
|
|
|
return new DotNetTypeWrapper(type, name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (hasDotNetModule)
|
|
|
|
{
|
|
|
|
// for fake 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 = DoLoad(name.Substring(0, name.Length - DotNetTypeWrapper.DelegateInterfaceSuffix.Length));
|
|
|
|
}
|
|
|
|
else if (name.EndsWith(DotNetTypeWrapper.AttributeAnnotationSuffix))
|
|
|
|
{
|
|
|
|
outer = DoLoad(name.Substring(0, name.Length - DotNetTypeWrapper.AttributeAnnotationSuffix.Length));
|
|
|
|
}
|
|
|
|
else if (name.EndsWith(DotNetTypeWrapper.AttributeAnnotationReturnValueSuffix))
|
|
|
|
{
|
|
|
|
outer = DoLoad(name.Substring(0, name.Length - DotNetTypeWrapper.AttributeAnnotationReturnValueSuffix.Length));
|
|
|
|
}
|
|
|
|
else if (name.EndsWith(DotNetTypeWrapper.AttributeAnnotationMultipleSuffix))
|
|
|
|
{
|
|
|
|
outer = DoLoad(name.Substring(0, name.Length - DotNetTypeWrapper.AttributeAnnotationMultipleSuffix.Length));
|
|
|
|
}
|
|
|
|
else if (name.EndsWith(DotNetTypeWrapper.EnumEnumSuffix))
|
|
|
|
{
|
|
|
|
outer = DoLoad(name.Substring(0, name.Length - DotNetTypeWrapper.EnumEnumSuffix.Length));
|
|
|
|
}
|
|
|
|
if (outer != null && outer.IsFakeTypeContainer)
|
|
|
|
{
|
|
|
|
foreach (TypeWrapper tw in outer.InnerClasses)
|
|
|
|
{
|
|
|
|
if (tw.Name == name)
|
|
|
|
{
|
|
|
|
return tw;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal TypeWrapper CreateWrapperForAssemblyType(Type type)
|
|
|
|
{
|
|
|
|
Module mod = type.Module;
|
|
|
|
int moduleIndex = -1;
|
|
|
|
for (int i = 0; i < modules.Length; i++)
|
|
|
|
{
|
|
|
|
if (modules[i] == mod)
|
|
|
|
{
|
|
|
|
moduleIndex = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
string name;
|
|
|
|
if (isJavaModule[moduleIndex])
|
|
|
|
{
|
|
|
|
name = CompiledTypeWrapper.GetName(type);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
name = DotNetTypeWrapper.GetName(type);
|
|
|
|
if (name == null)
|
|
|
|
{
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (isJavaModule[moduleIndex])
|
|
|
|
{
|
|
|
|
if (AttributeHelper.IsHideFromJava(type))
|
|
|
|
{
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
// since this type was compiled from Java source, we have to look for our
|
|
|
|
// attributes
|
|
|
|
return CompiledTypeWrapper.newInstance(name, type);
|
2006-07-10 13:37:06 +04:00
|
|
|
}
|
2007-10-18 17:54:11 +04:00
|
|
|
else
|
|
|
|
{
|
2008-12-23 10:11:29 +03:00
|
|
|
if (!DotNetTypeWrapper.IsAllowedOutside(type))
|
|
|
|
{
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
// 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)
|
|
|
|
return new DotNetTypeWrapper(type, name);
|
2007-10-18 17:54:11 +04:00
|
|
|
}
|
2006-07-10 13:37:06 +04:00
|
|
|
}
|
2009-02-10 10:24:30 +03:00
|
|
|
|
|
|
|
internal bool InternalsVisibleTo(AssemblyName otherName)
|
|
|
|
{
|
|
|
|
if (internalsVisibleTo == null)
|
|
|
|
{
|
|
|
|
internalsVisibleTo = AttributeHelper.GetInternalsVisibleToAttributes(assembly);
|
|
|
|
}
|
|
|
|
foreach (AssemblyName name in internalsVisibleTo)
|
|
|
|
{
|
|
|
|
if (AssemblyName.ReferenceMatchesDefinition(name, otherName))
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2006-08-14 11:57:03 +04:00
|
|
|
}
|
|
|
|
|
2008-12-23 10:11:29 +03:00
|
|
|
internal AssemblyClassLoader(Assembly assembly, object javaClassLoader, bool hasCustomClassLoader)
|
2009-02-19 11:12:05 +03:00
|
|
|
: this(assembly, null, javaClassLoader, hasCustomClassLoader)
|
2006-08-14 11:57:03 +04:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2009-02-27 09:28:50 +03:00
|
|
|
internal AssemblyClassLoader(Assembly assembly, string[] fixedReferences, object javaClassLoader, bool hasCustomClassLoader)
|
2008-12-23 10:11:29 +03:00
|
|
|
: base(CodeGenOptions.None, javaClassLoader)
|
2006-08-14 11:57:03 +04:00
|
|
|
{
|
2008-12-23 10:11:29 +03:00
|
|
|
this.assemblyLoader = new AssemblyLoader(assembly);
|
2009-02-19 11:12:05 +03:00
|
|
|
this.references = fixedReferences;
|
2008-12-23 10:11:29 +03:00
|
|
|
this.isReflectionOnly = assembly.ReflectionOnly;
|
|
|
|
this.hasCustomClassLoader = hasCustomClassLoader;
|
2009-02-27 09:33:19 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
private void DoInitializeExports()
|
|
|
|
{
|
|
|
|
lock (this)
|
|
|
|
{
|
|
|
|
if (delegates == null)
|
|
|
|
{
|
2009-02-27 09:43:00 +03:00
|
|
|
#pragma warning disable 184
|
|
|
|
// during ikvmc build: warning CS0184: The given expression is never of the provided ('IKVM.Reflection.Emit.AssemblyBuilder') type
|
2009-02-27 09:33:19 +03:00
|
|
|
if (!(assemblyLoader.Assembly is AssemblyBuilder) && assemblyLoader.Assembly.GetManifestResourceInfo("ikvm.exports") != null)
|
2009-02-27 09:43:00 +03:00
|
|
|
#pragma warning restore 184
|
2008-12-23 10:11:29 +03:00
|
|
|
{
|
2009-02-27 09:33:19 +03:00
|
|
|
List<string> wildcardExports = new List<string>();
|
|
|
|
using (Stream stream = assemblyLoader.Assembly.GetManifestResourceStream("ikvm.exports"))
|
2008-12-23 10:11:29 +03:00
|
|
|
{
|
2009-02-27 09:33:19 +03:00
|
|
|
BinaryReader rdr = new BinaryReader(stream);
|
|
|
|
int assemblyCount = rdr.ReadInt32();
|
|
|
|
exports = new Dictionary<int, List<int>>();
|
|
|
|
exportedAssemblies = new AssemblyLoader[assemblyCount];
|
|
|
|
exportedAssemblyNames = new string[assemblyCount];
|
|
|
|
exportedLoaders = new Dictionary<Assembly, AssemblyLoader>();
|
|
|
|
for (int i = 0; i < assemblyCount; i++)
|
2008-12-23 10:11:29 +03:00
|
|
|
{
|
2009-02-27 09:33:19 +03:00
|
|
|
exportedAssemblyNames[i] = rdr.ReadString();
|
|
|
|
int typeCount = rdr.ReadInt32();
|
|
|
|
if (typeCount == 0 && references == null)
|
|
|
|
{
|
|
|
|
wildcardExports.Add(exportedAssemblyNames[i]);
|
|
|
|
}
|
|
|
|
for (int j = 0; j < typeCount; j++)
|
|
|
|
{
|
|
|
|
int hash = rdr.ReadInt32();
|
|
|
|
List<int> assemblies;
|
|
|
|
if (!exports.TryGetValue(hash, out assemblies))
|
|
|
|
{
|
|
|
|
assemblies = new List<int>();
|
|
|
|
exports.Add(hash, assemblies);
|
|
|
|
}
|
|
|
|
assemblies.Add(i);
|
|
|
|
}
|
2008-12-23 10:11:29 +03:00
|
|
|
}
|
2009-02-27 09:33:19 +03:00
|
|
|
}
|
|
|
|
if (references == null)
|
|
|
|
{
|
|
|
|
references = wildcardExports.ToArray();
|
2008-12-23 10:11:29 +03:00
|
|
|
}
|
|
|
|
}
|
2009-02-27 09:33:19 +03:00
|
|
|
else
|
|
|
|
{
|
|
|
|
AssemblyName[] refNames = assemblyLoader.Assembly.GetReferencedAssemblies();
|
|
|
|
references = new string[refNames.Length];
|
|
|
|
for (int i = 0; i < references.Length; i++)
|
|
|
|
{
|
|
|
|
references[i] = refNames[i].FullName;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
delegates = new AssemblyClassLoader[references.Length];
|
2009-02-19 11:12:05 +03:00
|
|
|
}
|
2006-08-14 11:57:03 +04:00
|
|
|
}
|
2009-02-27 09:33:19 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
private void LazyInitExports()
|
|
|
|
{
|
|
|
|
if (delegates == null)
|
2009-02-19 11:12:05 +03:00
|
|
|
{
|
2009-02-27 09:33:19 +03:00
|
|
|
DoInitializeExports();
|
2009-02-19 11:12:05 +03:00
|
|
|
}
|
2008-12-23 10:11:29 +03:00
|
|
|
}
|
|
|
|
|
2009-02-10 10:27:25 +03:00
|
|
|
internal Assembly MainAssembly
|
2008-12-23 10:11:29 +03:00
|
|
|
{
|
|
|
|
get
|
2006-08-14 11:57:03 +04:00
|
|
|
{
|
2008-12-23 10:11:29 +03:00
|
|
|
return assemblyLoader.Assembly;
|
2006-08-14 11:57:03 +04:00
|
|
|
}
|
2006-07-10 13:37:06 +04:00
|
|
|
}
|
|
|
|
|
2009-02-04 10:24:44 +03:00
|
|
|
internal Assembly GetAssembly(TypeWrapper wrapper)
|
|
|
|
{
|
|
|
|
Debug.Assert(wrapper.GetClassLoader() == this);
|
2009-02-04 11:10:24 +03:00
|
|
|
while (wrapper.IsFakeNestedType)
|
|
|
|
{
|
|
|
|
wrapper = wrapper.DeclaringTypeWrapper;
|
|
|
|
}
|
2009-02-04 10:24:44 +03:00
|
|
|
return wrapper.TypeAsBaseType.Assembly;
|
|
|
|
}
|
|
|
|
|
2009-02-04 10:10:59 +03:00
|
|
|
internal override Type GetGenericTypeDefinition(string name)
|
2006-10-09 12:29:42 +04:00
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
2009-02-04 10:10:59 +03:00
|
|
|
// we only have to look in the main assembly, because only a .NET assembly can contain generic type definitions
|
|
|
|
// and it cannot be part of a multi assembly sharedclassloader group
|
|
|
|
Type type = assemblyLoader.Assembly.GetType(name);
|
|
|
|
if (type != null && type.IsGenericTypeDefinition)
|
|
|
|
{
|
|
|
|
return type;
|
|
|
|
}
|
2006-10-09 12:29:42 +04:00
|
|
|
}
|
2009-02-04 10:10:59 +03:00
|
|
|
catch (FileLoadException x)
|
2006-10-09 12:29:42 +04:00
|
|
|
{
|
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
|
2009-02-27 09:28:50 +03:00
|
|
|
private Assembly LoadAssemblyOrClearName(ref string name)
|
2006-07-10 13:37:06 +04:00
|
|
|
{
|
2009-02-05 09:44:30 +03:00
|
|
|
if (name == null)
|
|
|
|
{
|
|
|
|
// previous load attemp failed
|
|
|
|
return null;
|
|
|
|
}
|
2006-07-10 13:37:06 +04:00
|
|
|
try
|
|
|
|
{
|
2008-12-23 10:11:29 +03:00
|
|
|
if (isReflectionOnly)
|
2006-07-10 13:37:06 +04:00
|
|
|
{
|
2009-02-27 09:28:50 +03:00
|
|
|
return Assembly.ReflectionOnlyLoad(name);
|
2006-07-10 13:37:06 +04:00
|
|
|
}
|
2008-12-23 10:11:29 +03:00
|
|
|
else
|
2006-07-10 13:37:06 +04:00
|
|
|
{
|
2008-12-23 10:11:29 +03:00
|
|
|
return Assembly.Load(name);
|
2006-07-10 13:37:06 +04:00
|
|
|
}
|
|
|
|
}
|
2008-12-23 10:11:29 +03:00
|
|
|
catch
|
2006-07-10 13:37:06 +04:00
|
|
|
{
|
2009-02-05 09:44:30 +03:00
|
|
|
// cache failure by clearing out the name the caller uses
|
2009-02-27 09:28:50 +03:00
|
|
|
name = null;
|
2009-02-05 09:44:30 +03:00
|
|
|
// should we issue a warning error (in ikvmc)?
|
2008-12-23 10:11:29 +03:00
|
|
|
return null;
|
2006-07-10 13:37:06 +04:00
|
|
|
}
|
|
|
|
}
|
2006-07-21 14:18:13 +04:00
|
|
|
|
2006-08-14 11:57:03 +04:00
|
|
|
internal TypeWrapper DoLoad(string name)
|
2006-07-21 14:18:13 +04:00
|
|
|
{
|
2008-12-23 10:11:29 +03:00
|
|
|
TypeWrapper tw = assemblyLoader.DoLoad(name);
|
|
|
|
if (tw != null)
|
|
|
|
{
|
|
|
|
return RegisterInitiatingLoader(tw);
|
|
|
|
}
|
2009-02-27 09:33:19 +03:00
|
|
|
LazyInitExports();
|
2008-12-23 10:11:29 +03:00
|
|
|
if (exports != null)
|
2006-07-26 11:57:18 +04:00
|
|
|
{
|
2008-12-23 10:11:29 +03:00
|
|
|
List<int> assemblies;
|
|
|
|
if (exports.TryGetValue(JVM.PersistableHash(name), out assemblies))
|
2006-07-21 14:18:13 +04:00
|
|
|
{
|
2008-12-23 10:11:29 +03:00
|
|
|
foreach (int index in assemblies)
|
2006-07-21 14:18:13 +04:00
|
|
|
{
|
2008-12-23 10:11:29 +03:00
|
|
|
AssemblyLoader loader = exportedAssemblies[index];
|
|
|
|
if (loader == null)
|
2006-10-09 12:29:42 +04:00
|
|
|
{
|
2009-02-05 09:44:30 +03:00
|
|
|
Assembly asm = LoadAssemblyOrClearName(ref exportedAssemblyNames[index]);
|
2008-12-23 10:11:29 +03:00
|
|
|
if (asm == null)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
loader = exportedAssemblies[index] = GetLoaderForExportedAssembly(asm);
|
2006-10-09 12:29:42 +04:00
|
|
|
}
|
2008-12-23 10:11:29 +03:00
|
|
|
tw = loader.DoLoad(name);
|
|
|
|
if (tw != null)
|
2006-10-09 12:29:42 +04:00
|
|
|
{
|
2008-12-23 10:11:29 +03:00
|
|
|
return RegisterInitiatingLoader(tw);
|
2006-10-09 12:29:42 +04:00
|
|
|
}
|
2006-07-26 14:33:52 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2008-12-23 10:11:29 +03:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
private AssemblyLoader GetLoader(Assembly assembly)
|
|
|
|
{
|
|
|
|
if (assemblyLoader.Assembly == assembly)
|
2007-10-18 17:54:11 +04:00
|
|
|
{
|
2008-12-23 10:11:29 +03:00
|
|
|
return assemblyLoader;
|
|
|
|
}
|
|
|
|
return GetLoaderForExportedAssembly(assembly);
|
|
|
|
}
|
|
|
|
|
|
|
|
private AssemblyLoader GetLoaderForExportedAssembly(Assembly assembly)
|
|
|
|
{
|
2009-02-27 09:33:19 +03:00
|
|
|
LazyInitExports();
|
2008-12-23 10:11:29 +03:00
|
|
|
AssemblyLoader loader;
|
|
|
|
lock (exportedLoaders)
|
|
|
|
{
|
|
|
|
exportedLoaders.TryGetValue(assembly, out loader);
|
|
|
|
}
|
|
|
|
if (loader == null)
|
|
|
|
{
|
|
|
|
loader = new AssemblyLoader(assembly);
|
|
|
|
lock (exportedLoaders)
|
2007-10-18 17:54:11 +04:00
|
|
|
{
|
2008-12-23 10:11:29 +03:00
|
|
|
AssemblyLoader existing;
|
|
|
|
if (exportedLoaders.TryGetValue(assembly, out existing))
|
2007-10-18 17:54:11 +04:00
|
|
|
{
|
2008-12-23 10:11:29 +03:00
|
|
|
// another thread beat us to it
|
|
|
|
loader = existing;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
exportedLoaders.Add(assembly, loader);
|
2007-10-18 17:54:11 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2008-12-23 10:11:29 +03:00
|
|
|
return loader;
|
2006-07-26 14:33:52 +04:00
|
|
|
}
|
|
|
|
|
2008-04-22 10:24:55 +04:00
|
|
|
internal virtual TypeWrapper GetWrapperFromAssemblyType(Type type)
|
2006-07-26 14:33:52 +04:00
|
|
|
{
|
2006-08-14 11:57:03 +04:00
|
|
|
//Tracer.Info(Tracer.Runtime, "GetWrapperFromAssemblyType: {0}", type.FullName);
|
2007-01-16 13:14:47 +03:00
|
|
|
Debug.Assert(!type.Name.EndsWith("[]"), "!type.IsArray", type.FullName);
|
2008-12-23 10:11:29 +03:00
|
|
|
Debug.Assert(ClassLoaderWrapper.GetAssemblyClassLoader(type.Assembly) == this);
|
2008-11-14 11:42:07 +03:00
|
|
|
#if !COMPACT_FRAMEWORK && !IKVM_REF_EMIT
|
2006-08-14 11:57:03 +04:00
|
|
|
Debug.Assert(!(type.Assembly is AssemblyBuilder), "!(type.Assembly is AssemblyBuilder)", type.FullName);
|
|
|
|
#endif
|
2008-12-23 10:11:29 +03:00
|
|
|
TypeWrapper wrapper = GetLoader(type.Assembly).CreateWrapperForAssemblyType(type);
|
2006-08-14 11:57:03 +04:00
|
|
|
if(wrapper != null)
|
|
|
|
{
|
2008-12-23 10:11:29 +03:00
|
|
|
wrapper = RegisterInitiatingLoader(wrapper);
|
2006-08-14 11:57:03 +04:00
|
|
|
if(wrapper.TypeAsTBD != type && (!wrapper.IsRemapped || wrapper.TypeAsBaseType != type))
|
2006-07-26 14:33:52 +04:00
|
|
|
{
|
2006-08-14 11:57:03 +04:00
|
|
|
// this really shouldn't happen, it means that we have two different types in our assembly that both
|
|
|
|
// have the same Java name
|
2008-12-23 10:11:29 +03:00
|
|
|
string msg = String.Format("\nType \"{0}\" and \"{1}\" both map to the same name \"{2}\".\n", type.FullName, wrapper.TypeAsTBD.FullName, wrapper.Name);
|
2006-08-14 11:57:03 +04:00
|
|
|
JVM.CriticalFailure(msg, null);
|
|
|
|
}
|
|
|
|
return wrapper;
|
|
|
|
}
|
2008-12-23 10:11:29 +03:00
|
|
|
return null;
|
2006-07-26 11:57:18 +04:00
|
|
|
}
|
|
|
|
|
2006-07-10 13:37:06 +04:00
|
|
|
protected override TypeWrapper LoadClassImpl(string name, bool throwClassNotFoundException)
|
2007-10-18 17:54:11 +04:00
|
|
|
{
|
2007-10-26 11:11:17 +04:00
|
|
|
TypeWrapper tw = DoLoad(name);
|
|
|
|
if(tw != null)
|
|
|
|
{
|
|
|
|
return tw;
|
|
|
|
}
|
2007-10-25 10:28:26 +04:00
|
|
|
if(hasCustomClassLoader)
|
|
|
|
{
|
|
|
|
return base.LoadClassImpl(name, throwClassNotFoundException);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2007-10-26 11:11:17 +04:00
|
|
|
tw = LoadGenericClass(name);
|
|
|
|
if(tw != null)
|
|
|
|
{
|
|
|
|
return tw;
|
|
|
|
}
|
|
|
|
return LoadReferenced(name);
|
2007-10-25 10:28:26 +04:00
|
|
|
}
|
|
|
|
}
|
2007-10-18 17:54:11 +04:00
|
|
|
|
2007-10-26 11:11:17 +04:00
|
|
|
internal TypeWrapper LoadReferenced(string name)
|
2006-07-10 13:37:06 +04:00
|
|
|
{
|
2009-02-27 09:33:19 +03:00
|
|
|
LazyInitExports();
|
2006-08-14 11:57:03 +04:00
|
|
|
for(int i = 0; i < delegates.Length; i++)
|
|
|
|
{
|
|
|
|
if(delegates[i] == null)
|
2006-07-21 14:18:13 +04:00
|
|
|
{
|
2009-02-05 09:44:30 +03:00
|
|
|
Assembly asm = LoadAssemblyOrClearName(ref references[i]);
|
2006-08-14 11:57:03 +04:00
|
|
|
if(asm != null)
|
|
|
|
{
|
|
|
|
delegates[i] = ClassLoaderWrapper.GetAssemblyClassLoader(asm);
|
|
|
|
}
|
|
|
|
}
|
2006-10-06 10:53:34 +04:00
|
|
|
if(delegates[i] != null)
|
2006-08-14 11:57:03 +04:00
|
|
|
{
|
2007-10-26 11:11:17 +04:00
|
|
|
TypeWrapper tw = delegates[i].DoLoad(name);
|
2006-10-06 10:53:34 +04:00
|
|
|
if(tw != null)
|
|
|
|
{
|
|
|
|
return tw;
|
|
|
|
}
|
2006-07-21 14:18:13 +04:00
|
|
|
}
|
|
|
|
}
|
2008-12-23 10:11:29 +03:00
|
|
|
if(!assemblyLoader.HasJavaModule)
|
2006-07-26 11:57:18 +04:00
|
|
|
{
|
2006-08-14 11:57:03 +04:00
|
|
|
return GetBootstrapClassLoader().LoadClassByDottedNameFast(name);
|
2006-07-26 11:57:18 +04:00
|
|
|
}
|
2006-08-14 11:57:03 +04:00
|
|
|
return null;
|
2006-07-10 13:37:06 +04:00
|
|
|
}
|
2006-11-30 17:29:43 +03:00
|
|
|
|
|
|
|
#if !STATIC_COMPILER
|
2009-02-05 10:00:59 +03:00
|
|
|
internal Assembly FindResourceAssembliesImpl(string unmangledName, string name, bool firstOnly, ref List<Assembly> list)
|
2006-11-30 17:29:43 +03:00
|
|
|
{
|
2008-12-23 10:11:29 +03:00
|
|
|
if(assemblyLoader.Assembly.GetManifestResourceInfo(name) != null)
|
2006-11-30 17:29:43 +03:00
|
|
|
{
|
|
|
|
if(firstOnly)
|
|
|
|
{
|
2009-02-05 10:00:59 +03:00
|
|
|
return assemblyLoader.Assembly;
|
2006-11-30 17:29:43 +03:00
|
|
|
}
|
2008-08-15 16:01:06 +04:00
|
|
|
list = new List<Assembly>();
|
2008-12-23 10:11:29 +03:00
|
|
|
list.Add(assemblyLoader.Assembly);
|
2006-11-30 17:29:43 +03:00
|
|
|
}
|
2009-02-27 09:33:19 +03:00
|
|
|
LazyInitExports();
|
2008-12-23 10:11:29 +03:00
|
|
|
if(exports != null)
|
2006-11-30 17:29:43 +03:00
|
|
|
{
|
2008-12-23 10:11:29 +03:00
|
|
|
List<int> assemblies;
|
|
|
|
if(exports.TryGetValue(JVM.PersistableHash(unmangledName), out assemblies))
|
2006-11-30 17:29:43 +03:00
|
|
|
{
|
2008-12-23 10:11:29 +03:00
|
|
|
foreach(int index in assemblies)
|
2006-11-30 17:29:43 +03:00
|
|
|
{
|
2008-12-23 10:11:29 +03:00
|
|
|
AssemblyLoader loader = exportedAssemblies[index];
|
|
|
|
if(loader == null)
|
2006-11-30 17:29:43 +03:00
|
|
|
{
|
2009-02-05 09:44:30 +03:00
|
|
|
Assembly asm = LoadAssemblyOrClearName(ref exportedAssemblyNames[index]);
|
2008-12-23 10:11:29 +03:00
|
|
|
if(asm == null)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
loader = exportedAssemblies[index] = GetLoaderForExportedAssembly(asm);
|
|
|
|
}
|
|
|
|
if(loader.Assembly.GetManifestResourceInfo(name) != null)
|
|
|
|
{
|
|
|
|
if(firstOnly)
|
|
|
|
{
|
2009-02-05 10:00:59 +03:00
|
|
|
return loader.Assembly;
|
2008-12-23 10:11:29 +03:00
|
|
|
}
|
|
|
|
if(list == null)
|
|
|
|
{
|
|
|
|
list = new List<Assembly>();
|
|
|
|
}
|
|
|
|
list.Add(loader.Assembly);
|
2006-11-30 17:29:43 +03:00
|
|
|
}
|
|
|
|
}
|
2008-12-23 10:11:29 +03:00
|
|
|
}
|
|
|
|
}
|
2009-02-05 10:00:59 +03:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal Assembly[] FindResourceAssemblies(string unmangledName, bool firstOnly)
|
|
|
|
{
|
|
|
|
List<Assembly> list = null;
|
|
|
|
string name = JVM.MangleResourceName(unmangledName);
|
|
|
|
Assembly first = FindResourceAssembliesImpl(unmangledName, name, firstOnly, ref list);
|
|
|
|
if(first != null)
|
|
|
|
{
|
|
|
|
return new Assembly[] { first };
|
|
|
|
}
|
2008-12-23 10:11:29 +03:00
|
|
|
for(int i = 0; i < delegates.Length; i++)
|
|
|
|
{
|
|
|
|
if(delegates[i] == null)
|
|
|
|
{
|
2009-02-05 09:44:30 +03:00
|
|
|
Assembly asm = LoadAssemblyOrClearName(ref references[i]);
|
2006-11-30 17:29:43 +03:00
|
|
|
if(asm != null)
|
|
|
|
{
|
|
|
|
delegates[i] = ClassLoaderWrapper.GetAssemblyClassLoader(asm);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(delegates[i] != null)
|
|
|
|
{
|
2009-02-05 10:00:59 +03:00
|
|
|
first = delegates[i].FindResourceAssembliesImpl(unmangledName, name, firstOnly, ref list);
|
|
|
|
if(first != null)
|
2006-11-30 17:29:43 +03:00
|
|
|
{
|
2009-02-05 10:00:59 +03:00
|
|
|
return new Assembly[] { first };
|
2006-11-30 17:29:43 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2008-12-23 10:11:29 +03:00
|
|
|
if(!assemblyLoader.HasJavaModule)
|
2006-11-30 17:29:43 +03:00
|
|
|
{
|
2008-12-23 10:11:29 +03:00
|
|
|
if(firstOnly)
|
2006-11-30 17:29:43 +03:00
|
|
|
{
|
2008-12-23 10:11:29 +03:00
|
|
|
return GetBootstrapClassLoader().FindResourceAssemblies(unmangledName, firstOnly);
|
2006-11-30 17:29:43 +03:00
|
|
|
}
|
2008-12-23 10:11:29 +03:00
|
|
|
else
|
2006-11-30 17:29:43 +03:00
|
|
|
{
|
2008-12-23 10:11:29 +03:00
|
|
|
Assembly[] assemblies = GetBootstrapClassLoader().FindResourceAssemblies(unmangledName, firstOnly);
|
|
|
|
if(assemblies != null)
|
2007-10-18 17:57:05 +04:00
|
|
|
{
|
2008-12-23 10:11:29 +03:00
|
|
|
foreach(Assembly asm in assemblies)
|
|
|
|
{
|
|
|
|
if(list == null)
|
|
|
|
{
|
|
|
|
list = new List<Assembly>();
|
|
|
|
}
|
|
|
|
if(!list.Contains(asm))
|
|
|
|
{
|
|
|
|
list.Add(asm);
|
|
|
|
}
|
|
|
|
}
|
2007-10-18 17:57:05 +04:00
|
|
|
}
|
2006-11-30 17:29:43 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if(list == null)
|
|
|
|
{
|
|
|
|
return null;
|
|
|
|
}
|
2008-08-15 16:01:06 +04:00
|
|
|
return list.ToArray();
|
2006-11-30 17:29:43 +03:00
|
|
|
}
|
2007-10-21 11:14:53 +04:00
|
|
|
|
|
|
|
internal void SetInitInProgress()
|
|
|
|
{
|
|
|
|
initializerThread = Thread.CurrentThread;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void SetInitDone()
|
|
|
|
{
|
|
|
|
lock(this)
|
|
|
|
{
|
|
|
|
initializerThread = null;
|
|
|
|
Monitor.PulseAll(this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void WaitInitDone()
|
|
|
|
{
|
|
|
|
lock(this)
|
|
|
|
{
|
|
|
|
if(initializerThread != Thread.CurrentThread)
|
|
|
|
{
|
|
|
|
while(initializerThread != null)
|
|
|
|
{
|
|
|
|
Monitor.Wait(this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2006-11-30 17:29:43 +03:00
|
|
|
#endif // !STATIC_COMPILER
|
2007-10-21 11:14:53 +04:00
|
|
|
|
|
|
|
internal virtual object GetProtectionDomain()
|
|
|
|
{
|
2007-11-26 08:50:57 +03:00
|
|
|
#if STATIC_COMPILER || FIRST_PASS
|
|
|
|
return null;
|
|
|
|
#else
|
2007-10-26 11:11:17 +04:00
|
|
|
if(protectionDomain == null)
|
2007-10-21 11:14:53 +04:00
|
|
|
{
|
2007-10-26 11:11:17 +04:00
|
|
|
java.net.URL codebase;
|
|
|
|
try
|
|
|
|
{
|
2008-12-23 10:11:29 +03:00
|
|
|
codebase = new java.net.URL(assemblyLoader.Assembly.CodeBase);
|
2007-10-26 11:11:17 +04:00
|
|
|
}
|
2008-03-14 12:15:08 +03:00
|
|
|
catch(NotSupportedException)
|
|
|
|
{
|
|
|
|
// dynamic assemblies don't have a codebase
|
|
|
|
codebase = null;
|
|
|
|
}
|
2007-10-26 11:11:17 +04:00
|
|
|
catch(java.net.MalformedURLException)
|
|
|
|
{
|
|
|
|
codebase = null;
|
|
|
|
}
|
|
|
|
java.security.Permissions permissions = new java.security.Permissions();
|
|
|
|
permissions.add(new java.security.AllPermission());
|
|
|
|
object pd = new java.security.ProtectionDomain(new java.security.CodeSource(codebase, (java.security.cert.Certificate[])null), permissions, (java.lang.ClassLoader)GetJavaClassLoader(), null);
|
|
|
|
lock(this)
|
|
|
|
{
|
|
|
|
if(protectionDomain == null)
|
2007-10-21 11:14:53 +04:00
|
|
|
{
|
2007-10-26 11:11:17 +04:00
|
|
|
protectionDomain = pd;
|
2007-10-21 11:14:53 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2007-10-26 11:11:17 +04:00
|
|
|
return protectionDomain;
|
2007-11-26 08:50:57 +03:00
|
|
|
#endif
|
2007-10-21 11:14:53 +04:00
|
|
|
}
|
2007-10-22 09:20:42 +04:00
|
|
|
|
|
|
|
protected override void CheckDefineClassAllowed(string className)
|
|
|
|
{
|
|
|
|
if(DoLoad(className) != null)
|
|
|
|
{
|
|
|
|
throw new LinkageError("duplicate class definition: " + className);
|
|
|
|
}
|
|
|
|
}
|
2007-10-26 11:11:17 +04:00
|
|
|
|
|
|
|
internal override TypeWrapper GetLoadedClass(string name)
|
|
|
|
{
|
|
|
|
TypeWrapper tw = base.GetLoadedClass(name);
|
|
|
|
return tw != null ? tw : DoLoad(name);
|
|
|
|
}
|
2007-12-17 13:59:02 +03:00
|
|
|
|
2009-02-10 10:24:30 +03:00
|
|
|
internal override bool InternalsVisibleToImpl(TypeWrapper wrapper, TypeWrapper friend)
|
2007-12-17 13:59:02 +03:00
|
|
|
{
|
2009-02-10 10:24:30 +03:00
|
|
|
ClassLoaderWrapper other = friend.GetClassLoader();
|
2007-12-17 13:59:02 +03:00
|
|
|
if(this == other)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
AssemblyName otherName;
|
|
|
|
#if STATIC_COMPILER
|
|
|
|
CompilerClassLoader ccl = other as CompilerClassLoader;
|
|
|
|
if(ccl == null)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
otherName = ccl.GetAssemblyName();
|
|
|
|
#else
|
|
|
|
AssemblyClassLoader acl = other as AssemblyClassLoader;
|
|
|
|
if(acl == null)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2009-02-10 10:24:30 +03:00
|
|
|
otherName = acl.GetAssembly(friend).GetName();
|
2007-12-17 13:59:02 +03:00
|
|
|
#endif
|
2009-02-10 10:24:30 +03:00
|
|
|
return GetLoaderForExportedAssembly(GetAssembly(wrapper)).InternalsVisibleTo(otherName);
|
2007-12-17 13:59:02 +03:00
|
|
|
}
|
2006-05-15 13:08:01 +04:00
|
|
|
}
|
2007-10-18 17:54:11 +04:00
|
|
|
|
|
|
|
class BootstrapClassLoader : AssemblyClassLoader
|
|
|
|
{
|
|
|
|
internal BootstrapClassLoader()
|
2009-02-27 09:28:50 +03:00
|
|
|
: base(JVM.CoreAssembly, new string[] {
|
|
|
|
typeof(object).Assembly.FullName, // mscorlib
|
|
|
|
typeof(System.Uri).Assembly.FullName // System
|
2008-12-23 10:11:29 +03:00
|
|
|
}, null, false)
|
2007-10-18 17:54:11 +04:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2008-04-22 10:24:55 +04:00
|
|
|
internal override TypeWrapper GetWrapperFromAssemblyType(Type type)
|
|
|
|
{
|
|
|
|
// we have to special case the fake types here
|
|
|
|
if(type.IsGenericType)
|
|
|
|
{
|
|
|
|
TypeWrapper outer = ClassLoaderWrapper.GetWrapperFromType(type.GetGenericArguments()[0]);
|
|
|
|
foreach(TypeWrapper inner in outer.InnerClasses)
|
|
|
|
{
|
|
|
|
if(inner.TypeAsTBD == type)
|
|
|
|
{
|
|
|
|
return inner;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
return base.GetWrapperFromAssemblyType(type);
|
|
|
|
}
|
|
|
|
|
2007-10-21 11:14:53 +04:00
|
|
|
internal override object GetProtectionDomain()
|
|
|
|
{
|
|
|
|
return null;
|
|
|
|
}
|
2007-10-18 17:54:11 +04:00
|
|
|
}
|
2002-12-18 19:00:25 +03:00
|
|
|
}
|