This commit is contained in:
jfrijters 2003-08-21 10:06:34 +00:00
Родитель 57c81013a1
Коммит 9d6bf7d010
36 изменённых файлов: 1948 добавлений и 1543 удалений

Просмотреть файл

@ -484,11 +484,11 @@ class ClassFile
} }
} }
internal string NetExpTypeAttribute internal string NetExpAssemblyAttribute
{ {
get get
{ {
Attribute attr = GetAttribute("IK.VM.NET.Type"); Attribute attr = GetAttribute("IKVM.NET.Assembly");
if(attr != null) if(attr != null)
{ {
return ((ConstantPoolItemUtf8)GetConstantPoolItem(attr.Data.ReadUInt16())).Value; return ((ConstantPoolItemUtf8)GetConstantPoolItem(attr.Data.ReadUInt16())).Value;

Просмотреть файл

@ -126,7 +126,7 @@ class ClassLoaderWrapper
this.javaClassLoader = javaClassLoader; this.javaClassLoader = javaClassLoader;
if(javaClassLoader != null && loadClassDelegate == null) if(javaClassLoader != null && loadClassDelegate == null)
{ {
loadClassDelegate = (LoadClassDelegate)Delegate.CreateDelegate(typeof(LoadClassDelegate), GetType("java.lang.VMClass"), "__loadClassHelper"); loadClassDelegate = (LoadClassDelegate)Delegate.CreateDelegate(typeof(LoadClassDelegate), GetType("java.lang.VMClass"), "loadClassHelper");
} }
} }
@ -141,6 +141,11 @@ class ClassLoaderWrapper
return (TypeWrapper[])((ArrayList)ghosts[wrapper.Name]).ToArray(typeof(TypeWrapper)); return (TypeWrapper[])((ArrayList)ghosts[wrapper.Name]).ToArray(typeof(TypeWrapper));
} }
internal static bool IsRemappedType(Type type)
{
return typeToTypeWrapper[type] is RemappedTypeWrapper;
}
internal void LoadRemappedTypes() internal void LoadRemappedTypes()
{ {
nativeMethods = new Hashtable(); nativeMethods = new Hashtable();
@ -161,7 +166,9 @@ class ClassLoaderWrapper
baseWrapper = null; baseWrapper = null;
} }
TypeWrapper tw = new RemappedTypeWrapper(this, modifiers, name, type, new TypeWrapper[0], baseWrapper); TypeWrapper tw = new RemappedTypeWrapper(this, modifiers, name, type, new TypeWrapper[0], baseWrapper);
Debug.Assert(!types.ContainsKey(name));
types.Add(name, tw); types.Add(name, tw);
Debug.Assert(!typeToTypeWrapper.ContainsKey(tw.Type));
typeToTypeWrapper.Add(tw.Type, tw); typeToTypeWrapper.Add(tw.Type, tw);
} }
// find the ghost interfaces // find the ghost interfaces
@ -301,16 +308,44 @@ class ClassLoaderWrapper
Type t = Type.GetType(name); Type t = Type.GetType(name);
if(t != null) if(t != null)
{ {
return GetCompiledTypeWrapper(t); if(t.Assembly.IsDefined(typeof(JavaAssemblyAttribute), false))
{
return GetWrapperFromType(t);
}
else
{
// HACK weird way to load the .NET type wrapper that always works
// (for remapped types as well, because netexp uses this way of
// loading types, we need the remapped types to appear in their
// .NET "warped" form).
return LoadClassByDottedName(DotNetTypeWrapper.GetName(t));
}
} }
} }
// TODO why is this check here and not at the top of the method?
if(name != "") if(name != "")
{ {
type = GetBootstrapType(name); Type t = GetBootstrapTypeRaw(name);
} if(t != null)
if(type != null) {
{ return GetWrapperFromBootstrapType(t);
return type; }
type = DotNetTypeWrapper.LoadDotNetTypeWrapper(name);
if(type != null)
{
Debug.Assert(type.Name == name, type.Name + " != " + name);
Debug.Assert(!types.ContainsKey(name), name);
types.Add(name, type);
return type;
}
// NOTE it is important that this is done last, because otherwise we will
// load the netexp generated fake types (e.g. delegate inner interface) instead
// of having DotNetTypeWrapper generating it.
type = GetTypeWrapperCompilerHook(name);
if(type != null)
{
return type;
}
} }
if(javaClassLoader == null) if(javaClassLoader == null)
{ {
@ -347,34 +382,45 @@ class ClassLoaderWrapper
} }
} }
private TypeWrapper GetCompiledTypeWrapper(Type type) private TypeWrapper GetWrapperFromBootstrapType(Type type)
{ {
TypeWrapper.AssertFinished(type); Debug.Assert(GetWrapperFromTypeFast(type) == null);
Debug.Assert(!type.IsArray);
Debug.Assert(!(type.Assembly is AssemblyBuilder));
// only the bootstrap classloader can own compiled types // only the bootstrap classloader can own compiled types
Debug.Assert(this == GetBootstrapClassLoader()); Debug.Assert(this == GetBootstrapClassLoader());
string name = NativeCode.java.lang.VMClass.getName(type); TypeWrapper wrapper = null;
TypeWrapper wrapper = (TypeWrapper)types[name]; if(type.Assembly.IsDefined(typeof(JavaAssemblyAttribute), false))
if(wrapper == null)
{ {
wrapper = new CompiledTypeWrapper(name, type); string name = CompiledTypeWrapper.GetName(type);
types.Add(name, wrapper);
typeToTypeWrapper[type] = wrapper;
}
else if(wrapper is RemappedTypeWrapper)
{
// When remapped types are loaded by their original name (e.g. System.Object)
// we end up here, and we make a CompiledTypeWrapper for it that reflects on
// the original type (note that you can never encounter these types anywhere,
// except when explicitly loaded with Class.forName)
name = type.FullName;
wrapper = (TypeWrapper)types[name]; wrapper = (TypeWrapper)types[name];
if(wrapper == null) if(wrapper == null)
{ {
// TODO instead of using CompiledTypeWrapper here, we probably should // since this type was compiled from Java source, we have to look for our
// have a subclass that converts all instance methods to static methods (and // attributes
// makes the class appear final with only a private constructor)
wrapper = new CompiledTypeWrapper(name, type); wrapper = new CompiledTypeWrapper(name, type);
types.Add(name, wrapper); Debug.Assert(wrapper.Name == name);
Debug.Assert(!types.ContainsKey(wrapper.Name), wrapper.Name);
types.Add(wrapper.Name, wrapper);
Debug.Assert(!typeToTypeWrapper.ContainsKey(type));
typeToTypeWrapper.Add(type, wrapper);
}
}
else
{
string name = DotNetTypeWrapper.GetName(type);
wrapper = (TypeWrapper)types[name];
if(wrapper == 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)
wrapper = new DotNetTypeWrapper(type);
Debug.Assert(wrapper.Name == name);
Debug.Assert(!types.ContainsKey(wrapper.Name), wrapper.Name);
types.Add(wrapper.Name, wrapper);
Debug.Assert(!typeToTypeWrapper.ContainsKey(type));
typeToTypeWrapper.Add(type, wrapper);
} }
} }
return wrapper; return wrapper;
@ -398,18 +444,11 @@ class ClassLoaderWrapper
return t; return t;
} }
} }
// HACK we also try mscorlib and this assembly (for the remapped types) return null;
// TODO this should be fixed by making the map.xml type names for .NET types assembly qualified
return Type.GetType(name);
} }
internal virtual TypeWrapper GetBootstrapType(string name) internal virtual TypeWrapper GetTypeWrapperCompilerHook(string name)
{ {
Type t = GetBootstrapTypeRaw(name);
if(t != null)
{
return GetCompiledTypeWrapper(t);
}
return null; return null;
} }
@ -454,10 +493,12 @@ class ClassLoaderWrapper
modifiers |= Modifiers.Public; modifiers |= Modifiers.Public;
} }
wrapper = new ArrayTypeWrapper(array, modifiers, name, this); wrapper = new ArrayTypeWrapper(array, modifiers, name, this);
Debug.Assert(!types.ContainsKey(name));
types.Add(name, wrapper); types.Add(name, wrapper);
if(!(elementType is TypeBuilder)) if(!(elementType is TypeBuilder))
{ {
typeToTypeWrapper[array] = wrapper; Debug.Assert(!typeToTypeWrapper.ContainsKey(array));
typeToTypeWrapper.Add(array, wrapper);
} }
} }
return wrapper; return wrapper;
@ -510,14 +551,24 @@ class ClassLoaderWrapper
{ {
throw JavaException.IncompatibleClassChangeError("Class {0} has interface {1} as superclass", f.Name, baseType.Name); throw JavaException.IncompatibleClassChangeError("Class {0} has interface {1} as superclass", f.Name, baseType.Name);
} }
string dotnetType = f.NetExpTypeAttribute; string dotnetAssembly = f.NetExpAssemblyAttribute;
if(dotnetType != null) if(dotnetAssembly != null)
{ {
type = new NetExpTypeWrapper(f, dotnetType, baseType); // The sole purpose of the netexp class is to let us load the assembly that the class lives in,
// once we've done that, all types in it become visible.
Assembly.Load(dotnetAssembly);
types.Remove(f.Name);
type = GetBootstrapClassLoader().LoadClassByDottedNameFast(f.Name);
if(type == null)
{
throw JavaException.NoClassDefFoundError("{0} (loaded through NetExp class)", f.Name);
}
return type;
} }
else else
{ {
type = new DynamicTypeWrapper(f, this, nativeMethods); type = new DynamicTypeWrapper(f, this, nativeMethods);
Debug.Assert(!dynamicTypes.ContainsKey(type.Type.FullName));
dynamicTypes.Add(type.Type.FullName, type); dynamicTypes.Add(type.Type.FullName, type);
} }
Debug.Assert(types[f.Name] == null); Debug.Assert(types[f.Name] == null);
@ -856,7 +907,8 @@ class ClassLoaderWrapper
// if we found it, store it in the map // if we found it, store it in the map
if(wrapper != null) if(wrapper != null)
{ {
typeToTypeWrapper[type] = wrapper; Debug.Assert(!typeToTypeWrapper.ContainsKey(type));
typeToTypeWrapper.Add(type, wrapper);
} }
} }
return wrapper; return wrapper;
@ -880,58 +932,14 @@ class ClassLoaderWrapper
} }
wrapper = GetWrapperFromType(elem); wrapper = GetWrapperFromType(elem);
// HACK this is a lame way of creating the array wrapper // HACK this is a lame way of creating the array wrapper
if(wrapper.IsPrimitive) return wrapper.GetClassLoader().LoadClassByDottedName(new String('[', rank) + wrapper.SigName);
{
string elemType;
if(wrapper == PrimitiveTypeWrapper.BYTE)
{
elemType = "B";
}
else if(wrapper == PrimitiveTypeWrapper.BOOLEAN)
{
elemType = "Z";
}
else if(wrapper == PrimitiveTypeWrapper.SHORT)
{
elemType = "S";
}
else if(wrapper == PrimitiveTypeWrapper.CHAR)
{
elemType = "C";
}
else if(wrapper == PrimitiveTypeWrapper.INT)
{
elemType = "I";
}
else if(wrapper == PrimitiveTypeWrapper.LONG)
{
elemType = "J";
}
else if(wrapper == PrimitiveTypeWrapper.FLOAT)
{
elemType = "F";
}
else if(wrapper == PrimitiveTypeWrapper.DOUBLE)
{
elemType = "D";
}
else
{
throw new InvalidOperationException();
}
return wrapper.GetClassLoader().LoadClassByDottedName(new String('[', rank) + elemType);
}
else
{
return wrapper.GetClassLoader().LoadClassByDottedName(new String('[', rank) + "L" + wrapper.Name + ";");
}
} }
// if the wrapper doesn't already exist, that must mean that the type // 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 // is a .NET type (or a pre-compiled Java class), which means that it
// was "loaded" by the bootstrap classloader // was "loaded" by the bootstrap classloader
// TODO think up a scheme to deal with .NET types that have the same name. Since all .NET types // TODO think up a scheme to deal with .NET types that have the same name. Since all .NET types
// appear in the boostrap classloader, we need to devise a scheme to mangle the class name // appear in the boostrap classloader, we need to devise a scheme to mangle the class name
return GetBootstrapClassLoader().GetCompiledTypeWrapper(type); return GetBootstrapClassLoader().GetWrapperFromBootstrapType(type);
} }
return wrapper; return wrapper;
} }
@ -939,6 +947,7 @@ class ClassLoaderWrapper
internal static void SetWrapperForType(Type type, TypeWrapper wrapper) internal static void SetWrapperForType(Type type, TypeWrapper wrapper)
{ {
TypeWrapper.AssertFinished(type); TypeWrapper.AssertFinished(type);
Debug.Assert(!typeToTypeWrapper.ContainsKey(type));
typeToTypeWrapper.Add(type, wrapper); typeToTypeWrapper.Add(type, wrapper);
} }

Просмотреть файл

@ -151,7 +151,7 @@ public abstract class CodeEmitter
{ {
return new CodeEmitter.OpCodeEmitter(OpCodes.Ldnull); return new CodeEmitter.OpCodeEmitter(OpCodes.Ldnull);
} }
else if(constant is int || constant is uint || else if(constant is int ||
constant is short || constant is ushort || constant is short || constant is ushort ||
constant is byte || constant is sbyte || constant is byte || constant is sbyte ||
constant is char || constant is char ||
@ -159,6 +159,10 @@ public abstract class CodeEmitter
{ {
return CodeEmitter.Create(OpCodes.Ldc_I4, ((IConvertible)constant).ToInt32(null)); return CodeEmitter.Create(OpCodes.Ldc_I4, ((IConvertible)constant).ToInt32(null));
} }
else if(constant is uint)
{
return CodeEmitter.Create(OpCodes.Ldc_I4, unchecked((int)((IConvertible)constant).ToUInt32(null)));
}
else if(constant is string) else if(constant is string)
{ {
return CodeEmitter.Create(OpCodes.Ldstr, (string)constant); return CodeEmitter.Create(OpCodes.Ldstr, (string)constant);
@ -171,17 +175,29 @@ public abstract class CodeEmitter
{ {
return CodeEmitter.Create(OpCodes.Ldc_R8, (double)constant); return CodeEmitter.Create(OpCodes.Ldc_R8, (double)constant);
} }
else if(constant is long || constant is ulong) else if(constant is long)
{ {
return CodeEmitter.Create(OpCodes.Ldc_I8, (long)constant); return CodeEmitter.Create(OpCodes.Ldc_I8, (long)constant);
} }
else if(constant is ulong)
{
return CodeEmitter.Create(OpCodes.Ldc_I8, unchecked((long)(ulong)constant));
}
else if(constant is Enum) else if(constant is Enum)
{ {
Type underlying = Enum.GetUnderlyingType(constant.GetType()); Type underlying = Enum.GetUnderlyingType(constant.GetType());
if(underlying == typeof(long) || underlying == typeof(ulong)) if(underlying == typeof(long))
{ {
return CodeEmitter.Create(OpCodes.Ldc_I8, ((IConvertible)constant).ToInt64(null)); return CodeEmitter.Create(OpCodes.Ldc_I8, ((IConvertible)constant).ToInt64(null));
} }
if(underlying == typeof(ulong))
{
return CodeEmitter.Create(OpCodes.Ldc_I8, unchecked((long)((IConvertible)constant).ToUInt64(null)));
}
else if(underlying == typeof(uint))
{
return CodeEmitter.Create(OpCodes.Ldc_I4, unchecked((int)((IConvertible)constant).ToUInt32(null)));
}
else else
{ {
return CodeEmitter.Create(OpCodes.Ldc_I4, ((IConvertible)constant).ToInt32(null)); return CodeEmitter.Create(OpCodes.Ldc_I4, ((IConvertible)constant).ToInt32(null));

Просмотреть файл

@ -531,8 +531,9 @@ sealed class FieldWrapper : MemberWrapper
internal readonly CodeEmitter EmitSet; internal readonly CodeEmitter EmitSet;
private FieldInfo field; private FieldInfo field;
private TypeWrapper fieldType; private TypeWrapper fieldType;
private static System.Collections.Hashtable warnOnce;
private FieldWrapper(TypeWrapper declaringType, TypeWrapper fieldType, string name, string sig, Modifiers modifiers, CodeEmitter emitGet, CodeEmitter emitSet) private FieldWrapper(TypeWrapper declaringType, TypeWrapper fieldType, string name, string sig, Modifiers modifiers, FieldInfo field, CodeEmitter emitGet, CodeEmitter emitSet)
: base(declaringType, modifiers, false) : base(declaringType, modifiers, false)
{ {
Debug.Assert(fieldType != null); Debug.Assert(fieldType != null);
@ -543,10 +544,48 @@ sealed class FieldWrapper : MemberWrapper
this.name = name; this.name = name;
this.sig = sig; this.sig = sig;
this.fieldType = fieldType; this.fieldType = fieldType;
this.field = field;
this.EmitGet = emitGet; this.EmitGet = emitGet;
this.EmitSet = emitSet; this.EmitSet = emitSet;
} }
// HACK used (indirectly thru NativeCode.java.lang.Field.getConstant) by netexp to find out if the
// field is a constant (and if it is its value)
internal object GetConstant()
{
// NOTE only pritimives and string can be literals in Java (because the other "primitives" (like uint),
// are treated as NonPrimitiveValueTypes)
TypeWrapper java_lang_String = ClassLoaderWrapper.GetBootstrapClassLoader().LoadClassByDottedName("java.lang.String");
if(field != null && (fieldType.IsPrimitive || fieldType == java_lang_String) && field.IsLiteral)
{
// NOTE .NET BUG this causes the type initializer to run and we don't want that.
// TODO may need to find a workaround, for now we just spit out a warning (only shows up during netexp)
if(field.DeclaringType.TypeInitializer != null)
{
// HACK lame way to support a command line switch to suppress this warning
if(Environment.CommandLine.IndexOf("-noTypeInitWarning") == -1)
{
if(warnOnce == null)
{
warnOnce = new System.Collections.Hashtable();
}
if(!warnOnce.ContainsKey(field.DeclaringType.FullName))
{
warnOnce.Add(field.DeclaringType.FullName, null);
Console.WriteLine("Warning: Running type initializer for {0} due to .NET bug", field.DeclaringType.FullName);
}
}
}
object val = field.GetValue(null);
if(val != null && !(val is string))
{
return NativeCode.java.lang.reflect.JavaWrapper.Box(val);
}
return val;
}
return null;
}
internal static FieldWrapper FromCookie(IntPtr cookie) internal static FieldWrapper FromCookie(IntPtr cookie)
{ {
return (FieldWrapper)FromCookieImpl(cookie); return (FieldWrapper)FromCookieImpl(cookie);
@ -679,9 +718,9 @@ sealed class FieldWrapper : MemberWrapper
} }
} }
internal static FieldWrapper Create(TypeWrapper declaringType, TypeWrapper fieldType, string name, string sig, Modifiers modifiers, CodeEmitter getter, CodeEmitter setter) internal static FieldWrapper Create(TypeWrapper declaringType, TypeWrapper fieldType, string name, string sig, Modifiers modifiers, FieldInfo fi, CodeEmitter getter, CodeEmitter setter)
{ {
return new FieldWrapper(declaringType, fieldType, name, sig, modifiers, getter, setter); return new FieldWrapper(declaringType, fieldType, name, sig, modifiers, fi, getter, setter);
} }
internal static FieldWrapper Create(TypeWrapper declaringType, TypeWrapper fieldType, FieldInfo fi, string sig, Modifiers modifiers) internal static FieldWrapper Create(TypeWrapper declaringType, TypeWrapper fieldType, FieldInfo fi, string sig, Modifiers modifiers)
@ -697,7 +736,7 @@ sealed class FieldWrapper : MemberWrapper
{ {
emitGet += CodeEmitter.NoClassDefFoundError(fieldType.Name); emitGet += CodeEmitter.NoClassDefFoundError(fieldType.Name);
emitSet += CodeEmitter.NoClassDefFoundError(fieldType.Name); emitSet += CodeEmitter.NoClassDefFoundError(fieldType.Name);
return new FieldWrapper(declaringType, fieldType, fi.Name, sig, modifiers, emitGet, emitSet); return new FieldWrapper(declaringType, fieldType, fi.Name, sig, modifiers, fi, emitGet, emitSet);
} }
if(fieldType.IsNonPrimitiveValueType) if(fieldType.IsNonPrimitiveValueType)
{ {
@ -712,7 +751,7 @@ sealed class FieldWrapper : MemberWrapper
// TODO shouldn't we use += here (for volatile fields inside of value types)? // TODO shouldn't we use += here (for volatile fields inside of value types)?
emitGet = new VolatileLongDoubleGetter(fi); emitGet = new VolatileLongDoubleGetter(fi);
emitSet = new VolatileLongDoubleSetter(fi); emitSet = new VolatileLongDoubleSetter(fi);
return new FieldWrapper(declaringType, fieldType, fi.Name, sig, modifiers, emitGet, emitSet); return new FieldWrapper(declaringType, fieldType, fi.Name, sig, modifiers, fi, emitGet, emitSet);
} }
emitGet += CodeEmitter.Volatile; emitGet += CodeEmitter.Volatile;
emitSet += CodeEmitter.Volatile; emitSet += CodeEmitter.Volatile;
@ -731,7 +770,7 @@ sealed class FieldWrapper : MemberWrapper
{ {
emitGet += CodeEmitter.Create(OpCodes.Box, fieldType.Type); emitGet += CodeEmitter.Create(OpCodes.Box, fieldType.Type);
} }
return new FieldWrapper(declaringType, fieldType, fi.Name, sig, modifiers, emitGet, emitSet); return new FieldWrapper(declaringType, fieldType, fi.Name, sig, modifiers, fi, emitGet, emitSet);
} }
private void LookupField() private void LookupField()
@ -751,7 +790,7 @@ sealed class FieldWrapper : MemberWrapper
internal void SetValue(object obj, object val) internal void SetValue(object obj, object val)
{ {
// TODO this is a broken implementation (for one thing, it needs to support redirection) // TODO this is a broken implementation (for one thing, it needs to support redirection)
if(field == null) if(field == null || field is FieldBuilder)
{ {
LookupField(); LookupField();
} }
@ -761,7 +800,7 @@ sealed class FieldWrapper : MemberWrapper
internal object GetValue(object obj) internal object GetValue(object obj)
{ {
// TODO this is a broken implementation (for one thing, it needs to support redirection) // TODO this is a broken implementation (for one thing, it needs to support redirection)
if(field == null) if(field == null || field is FieldBuilder)
{ {
LookupField(); LookupField();
} }

Просмотреть файл

@ -47,7 +47,7 @@ sealed class MethodDescriptor
{ {
} }
private MethodDescriptor(ClassLoaderWrapper classLoader, string name, string sig, TypeWrapper[] args, TypeWrapper ret) internal MethodDescriptor(ClassLoaderWrapper classLoader, string name, string sig, TypeWrapper[] args, TypeWrapper ret)
{ {
Debug.Assert(classLoader != null); Debug.Assert(classLoader != null);
// class name in the sig should be dotted // class name in the sig should be dotted
@ -178,6 +178,11 @@ sealed class MethodDescriptor
} }
else else
{ {
if(type.IsByRef)
{
type = type.Assembly.GetType(type.GetElementType().FullName + "[]", true);
// TODO test type for unsupported types
}
name = GetSigNameFromType(type); name = GetSigNameFromType(type);
typeWrapper = ClassLoaderWrapper.GetWrapperFromType(type); typeWrapper = ClassLoaderWrapper.GetWrapperFromType(type);
} }
@ -300,6 +305,8 @@ sealed class MethodDescriptor
} }
} }
// TODO ensure that FromMethodBase is only used on statically compiled Java types, and
// remove support for ByRef
internal static MethodDescriptor FromMethodBase(MethodBase mb) internal static MethodDescriptor FromMethodBase(MethodBase mb)
{ {
System.Text.StringBuilder sb = new System.Text.StringBuilder(); System.Text.StringBuilder sb = new System.Text.StringBuilder();
@ -348,6 +355,7 @@ class EmitHelper
internal static void RunClassConstructor(ILGenerator ilgen, Type type) internal static void RunClassConstructor(ILGenerator ilgen, Type type)
{ {
// TODO RunClassConstructor requires full trust, so we need to use a different mechanism...
ilgen.Emit(OpCodes.Ldtoken, type); ilgen.Emit(OpCodes.Ldtoken, type);
ilgen.Emit(OpCodes.Call, typeof(System.Runtime.CompilerServices.RuntimeHelpers).GetMethod("RunClassConstructor")); ilgen.Emit(OpCodes.Call, typeof(System.Runtime.CompilerServices.RuntimeHelpers).GetMethod("RunClassConstructor"));
} }
@ -436,7 +444,7 @@ class AttributeHelper
} }
// NOTE Java doesn't support non-virtual methods, but we set the Final modifier for // NOTE Java doesn't support non-virtual methods, but we set the Final modifier for
// non-virtual methods to approximate the semantics // non-virtual methods to approximate the semantics
if(mb.IsFinal || (!mb.IsStatic && !mb.IsVirtual && !mb.IsConstructor)) if((mb.IsFinal || !mb.IsVirtual) && !mb.IsStatic && !mb.IsConstructor)
{ {
modifiers |= Modifiers.Final; modifiers |= Modifiers.Final;
} }
@ -444,14 +452,20 @@ class AttributeHelper
{ {
modifiers |= Modifiers.Abstract; modifiers |= Modifiers.Abstract;
} }
else
{
// Some .NET interfaces (like System._AppDomain) have synchronized methods,
// Java doesn't allow synchronized on an abstract methods, so we ignore it for
// abstract methods.
if((mb.GetMethodImplementationFlags() & MethodImplAttributes.Synchronized) != 0)
{
modifiers |= Modifiers.Synchronized;
}
}
if(mb.IsStatic) if(mb.IsStatic)
{ {
modifiers |= Modifiers.Static; modifiers |= Modifiers.Static;
} }
if((mb.GetMethodImplementationFlags() & MethodImplAttributes.Synchronized) != 0)
{
modifiers |= Modifiers.Synchronized;
}
if((mb.Attributes & MethodAttributes.PinvokeImpl) != 0) if((mb.Attributes & MethodAttributes.PinvokeImpl) != 0)
{ {
modifiers |= Modifiers.Native; modifiers |= Modifiers.Native;
@ -597,6 +611,15 @@ class AttributeHelper
CustomAttributeBuilder attrib = new CustomAttributeBuilder(typeof(UnloadableTypeAttribute).GetConstructor(new Type[] { typeof(string) }), new object[] { name }); CustomAttributeBuilder attrib = new CustomAttributeBuilder(typeof(UnloadableTypeAttribute).GetConstructor(new Type[] { typeof(string) }), new object[] { name });
field.SetCustomAttribute(attrib); field.SetCustomAttribute(attrib);
} }
internal static void SetInnerClass(TypeBuilder typeBuilder, string innerClass, string outerClass, string name, Modifiers modifiers)
{
Type[] argTypes = new Type[] { typeof(string), typeof(string), typeof(string), typeof(Modifiers) };
object[] args = new object[] { innerClass, outerClass, name, modifiers };
ConstructorInfo ci = typeof(InnerClassAttribute).GetConstructor(argTypes);
CustomAttributeBuilder customAttributeBuilder = new CustomAttributeBuilder(ci, args);
typeBuilder.SetCustomAttribute(customAttributeBuilder);
}
} }
abstract class TypeWrapper abstract class TypeWrapper
@ -861,6 +884,15 @@ abstract class TypeWrapper
} }
} }
// the name of the type as it appears in a Java signature string (e.g. "Ljava.lang.Object;" or "I")
internal virtual string SigName
{
get
{
return "L" + this.Name + ";";
}
}
internal string PackageName internal string PackageName
{ {
get get
@ -1361,22 +1393,32 @@ class UnloadableTypeWrapper : TypeWrapper
class PrimitiveTypeWrapper : TypeWrapper class PrimitiveTypeWrapper : TypeWrapper
{ {
internal static readonly PrimitiveTypeWrapper BYTE = new PrimitiveTypeWrapper(typeof(sbyte)); internal static readonly PrimitiveTypeWrapper BYTE = new PrimitiveTypeWrapper(typeof(sbyte), "B");
internal static readonly PrimitiveTypeWrapper CHAR = new PrimitiveTypeWrapper(typeof(char)); internal static readonly PrimitiveTypeWrapper CHAR = new PrimitiveTypeWrapper(typeof(char), "C");
internal static readonly PrimitiveTypeWrapper DOUBLE = new PrimitiveTypeWrapper(typeof(double)); internal static readonly PrimitiveTypeWrapper DOUBLE = new PrimitiveTypeWrapper(typeof(double), "D");
internal static readonly PrimitiveTypeWrapper FLOAT = new PrimitiveTypeWrapper(typeof(float)); internal static readonly PrimitiveTypeWrapper FLOAT = new PrimitiveTypeWrapper(typeof(float), "F");
internal static readonly PrimitiveTypeWrapper INT = new PrimitiveTypeWrapper(typeof(int)); internal static readonly PrimitiveTypeWrapper INT = new PrimitiveTypeWrapper(typeof(int), "I");
internal static readonly PrimitiveTypeWrapper LONG = new PrimitiveTypeWrapper(typeof(long)); internal static readonly PrimitiveTypeWrapper LONG = new PrimitiveTypeWrapper(typeof(long), "J");
internal static readonly PrimitiveTypeWrapper SHORT = new PrimitiveTypeWrapper(typeof(short)); internal static readonly PrimitiveTypeWrapper SHORT = new PrimitiveTypeWrapper(typeof(short), "S");
internal static readonly PrimitiveTypeWrapper BOOLEAN = new PrimitiveTypeWrapper(typeof(bool)); internal static readonly PrimitiveTypeWrapper BOOLEAN = new PrimitiveTypeWrapper(typeof(bool), "Z");
internal static readonly PrimitiveTypeWrapper VOID = new PrimitiveTypeWrapper(typeof(void)); internal static readonly PrimitiveTypeWrapper VOID = new PrimitiveTypeWrapper(typeof(void), "V");
private readonly Type type; private readonly Type type;
private readonly string sigName;
private PrimitiveTypeWrapper(Type type) private PrimitiveTypeWrapper(Type type, string sigName)
: base(Modifiers.Public | Modifiers.Abstract | Modifiers.Final, null, null, null) : base(Modifiers.Public | Modifiers.Abstract | Modifiers.Final, null, null, null)
{ {
this.type = type; this.type = type;
this.sigName = sigName;
}
internal override string SigName
{
get
{
return sigName;
}
} }
internal override ClassLoaderWrapper GetClassLoader() internal override ClassLoaderWrapper GetClassLoader()
@ -1721,16 +1763,11 @@ class DynamicTypeWrapper : TypeWrapper
{ {
declaringTypeWrapper = classFile.GetConstantPoolClassType(innerclasses[i].outerClass, wrapper.GetClassLoader()); declaringTypeWrapper = classFile.GetConstantPoolClassType(innerclasses[i].outerClass, wrapper.GetClassLoader());
reflectiveModifiers = innerclasses[i].accessFlags; reflectiveModifiers = innerclasses[i].accessFlags;
Type[] argTypes = new Type[] { typeof(string), typeof(string), typeof(string), typeof(Modifiers) }; AttributeHelper.SetInnerClass(typeBuilder,
object[] args = new object[] {
classFile.GetConstantPoolClass(innerclasses[i].innerClass), classFile.GetConstantPoolClass(innerclasses[i].innerClass),
classFile.GetConstantPoolClass(innerclasses[i].outerClass), classFile.GetConstantPoolClass(innerclasses[i].outerClass),
innerclasses[i].name == 0 ? null : classFile.GetConstantPoolUtf8String(innerclasses[i].name), innerclasses[i].name == 0 ? null : classFile.GetConstantPoolUtf8String(innerclasses[i].name),
reflectiveModifiers reflectiveModifiers);
};
ConstructorInfo ci = typeof(InnerClassAttribute).GetConstructor(argTypes);
CustomAttributeBuilder customAttributeBuilder = new CustomAttributeBuilder(ci, args);
typeBuilder.SetCustomAttribute(customAttributeBuilder);
} }
} }
} }
@ -2227,7 +2264,7 @@ class DynamicTypeWrapper : TypeWrapper
// when non-blank final fields are updated, the JIT normally doesn't see that (because the // when non-blank final fields are updated, the JIT normally doesn't see that (because the
// constant value is inlined), so we emulate that behavior by emitting a Pop // constant value is inlined), so we emulate that behavior by emitting a Pop
CodeEmitter emitSet = CodeEmitter.Pop; CodeEmitter emitSet = CodeEmitter.Pop;
fields[i] = FieldWrapper.Create(wrapper, fld.GetFieldType(wrapper.GetClassLoader()), fld.Name, fld.Signature, fld.Modifiers, emitGet, emitSet); fields[i] = FieldWrapper.Create(wrapper, fld.GetFieldType(wrapper.GetClassLoader()), fld.Name, fld.Signature, fld.Modifiers, field, emitGet, emitSet);
} }
else else
{ {
@ -2292,7 +2329,7 @@ class DynamicTypeWrapper : TypeWrapper
{ {
emitSet += CodeEmitter.Create(OpCodes.Stfld, field); emitSet += CodeEmitter.Create(OpCodes.Stfld, field);
} }
fields[i] = FieldWrapper.Create(wrapper, fld.GetFieldType(wrapper.GetClassLoader()), fld.Name, fld.Signature, fld.Modifiers, emitGet, emitSet); fields[i] = FieldWrapper.Create(wrapper, fld.GetFieldType(wrapper.GetClassLoader()), fld.Name, fld.Signature, fld.Modifiers, field, emitGet, emitSet);
} }
else else
{ {
@ -3232,7 +3269,7 @@ class RemappedTypeWrapper : TypeWrapper
} }
CodeEmitter setter = CodeEmitter.Throw("java.lang.IllegalAccessError", "Redirected field " + this.Name + "." + fieldName + " is read-only"); CodeEmitter setter = CodeEmitter.Throw("java.lang.IllegalAccessError", "Redirected field " + this.Name + "." + fieldName + " is read-only");
// HACK we abuse RetTypeWrapperFromSig // HACK we abuse RetTypeWrapperFromSig
FieldWrapper fw = FieldWrapper.Create(this, GetClassLoader().RetTypeWrapperFromSig("()" + fieldSig), fieldName, fieldSig, modifiers, getter, setter); FieldWrapper fw = FieldWrapper.Create(this, GetClassLoader().RetTypeWrapperFromSig("()" + fieldSig), fieldName, fieldSig, modifiers, null, getter, setter);
AddField(fw); AddField(fw);
} }
} }
@ -3515,199 +3552,31 @@ class RemappedTypeWrapper : TypeWrapper
} }
} }
class NetExpTypeWrapper : TypeWrapper // TODO CompiledTypeWrapper & DotNetTypeWrapper should have a common base class
{
private readonly ClassFile classFile;
private readonly Type type;
// TODO consider constructing modifiers from .NET type instead of the netexp class
public NetExpTypeWrapper(ClassFile f, string dotnetType, TypeWrapper baseType)
: base(f.Modifiers, f.Name, baseType, ClassLoaderWrapper.GetBootstrapClassLoader())
{
this.classFile = f;
// TODO if the type isn't found, it should be handled differently
type = Type.GetType(dotnetType, true);
}
public override TypeWrapper[] Interfaces
{
get
{
// TODO resolve the interfaces!
return TypeWrapper.EmptyArray;
}
}
public override TypeWrapper[] InnerClasses
{
get
{
// TODO resolve the inner classes!
return TypeWrapper.EmptyArray;
}
}
public override TypeWrapper DeclaringTypeWrapper
{
get
{
// TODO resolve the outer class!
return null;
}
}
protected override FieldWrapper GetFieldImpl(string fieldName)
{
// HACK this is a totally broken quick & dirty implementation
// TODO clean this up, add error checking and whatnot
FieldInfo field = type.GetField(fieldName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance);
if(!AttributeHelper.IsHideFromReflection(field))
{
return FieldWrapper.Create(this, ClassLoaderWrapper.GetWrapperFromType(field.FieldType), field, MethodDescriptor.GetFieldSigName(field), AttributeHelper.GetModifiers(field));
}
return null;
}
private class DelegateConstructorEmitter : CodeEmitter
{
private ConstructorInfo delegateConstructor;
private MethodInfo method;
internal DelegateConstructorEmitter(ConstructorInfo delegateConstructor, MethodInfo method)
{
this.delegateConstructor = delegateConstructor;
this.method = method;
}
internal override void Emit(ILGenerator ilgen)
{
ilgen.Emit(OpCodes.Dup);
ilgen.Emit(OpCodes.Ldvirtftn, method);
ilgen.Emit(OpCodes.Newobj, delegateConstructor);
}
}
private class RefArgConverter : CodeEmitter
{
private Type[] args;
internal RefArgConverter(Type[] args)
{
this.args = args;
}
internal override void Emit(ILGenerator ilgen)
{
LocalBuilder[] locals = new LocalBuilder[args.Length];
for(int i = args.Length - 1; i >= 0; i--)
{
Type type = args[i];
if(type.IsByRef)
{
type = type.Assembly.GetType(type.GetElementType().FullName + "[]", true);
}
locals[i] = ilgen.DeclareLocal(type);
ilgen.Emit(OpCodes.Stloc, locals[i]);
}
for(int i = 0; i < args.Length; i++)
{
ilgen.Emit(OpCodes.Ldloc, locals[i]);
if(args[i].IsByRef)
{
ilgen.Emit(OpCodes.Ldc_I4_0);
ilgen.Emit(OpCodes.Ldelema, args[i].GetElementType());
}
}
}
}
protected override MethodWrapper GetMethodImpl(MethodDescriptor md)
{
// special case for delegate constructors!
if(md.Name == "<init>" && type.IsSubclassOf(typeof(MulticastDelegate)))
{
// TODO set method flags
MethodWrapper method = new MethodWrapper(this, md, null, null, Modifiers.Public, false);
// TODO what class loader should we use?
TypeWrapper iface = ClassLoaderWrapper.GetBootstrapClassLoader().LoadClassByDottedName(classFile.Name + "$Method");
iface.Finish();
method.EmitNewobj = new DelegateConstructorEmitter(type.GetConstructor(new Type[] { typeof(object), typeof(IntPtr) }), iface.Type.GetMethod("Invoke"));
return method;
}
// HACK this is a totally broken quick & dirty implementation
// TODO clean this up, add error checking and whatnot
ClassFile.Method[] methods = classFile.Methods;
for(int i = 0; i < methods.Length; i++)
{
if(methods[i].Name == md.Name && methods[i].Signature == md.Signature)
{
bool hasByRefArgs = false;
Type[] args;
string[] sig = methods[i].NetExpSigAttribute;
if(sig == null)
{
args = md.ArgTypes;
}
else
{
args = new Type[sig.Length];
for(int j = 0; j < sig.Length; j++)
{
args[j] = Type.GetType(sig[j], true);
if(args[j].IsByRef)
{
hasByRefArgs = true;
}
}
}
MethodBase method;
if(md.Name == "<init>")
{
method = type.GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, CallingConventions.Standard, args, null);
}
else
{
method = type.GetMethod(md.Name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance, null, CallingConventions.Standard, args, null);
}
if(method != null)
{
// TODO we can decode the actual method attributes, or we can use them from the NetExp class, what is
// preferred?
MethodWrapper mw = MethodWrapper.Create(this, md, method, method, AttributeHelper.GetModifiers(method), AttributeHelper.IsHideFromReflection(method));
if(hasByRefArgs)
{
mw.EmitCall = new RefArgConverter(args) + mw.EmitCall;
mw.EmitCallvirt = new RefArgConverter(args) + mw.EmitCallvirt;
mw.EmitNewobj = new RefArgConverter(args) + mw.EmitNewobj;
}
return mw;
}
}
}
return null;
}
public override Type Type
{
get
{
return type;
}
}
public override void Finish()
{
}
}
class CompiledTypeWrapper : TypeWrapper class CompiledTypeWrapper : TypeWrapper
{ {
private readonly Type type; private readonly Type type;
private TypeWrapper[] interfaces; private TypeWrapper[] interfaces;
private TypeWrapper[] innerclasses; private TypeWrapper[] innerclasses;
internal static string GetName(Type type)
{
Debug.Assert(type.Assembly.IsDefined(typeof(JavaAssemblyAttribute), false));
if(type.IsDefined(typeof(HideFromReflectionAttribute), false))
{
return ClassLoaderWrapper.GetWrapperFromType(type.BaseType).Name;
}
// look for our custom attribute, that contains the real name of the type (for inner classes)
Object[] attribs = type.GetCustomAttributes(typeof(InnerClassAttribute), false);
if(attribs.Length == 1)
{
return ((InnerClassAttribute)attribs[0]).InnerClassName;
}
return type.FullName;
}
// TODO consider resolving the baseType lazily // TODO consider resolving the baseType lazily
private static TypeWrapper GetBaseTypeWrapper(Type type) internal static TypeWrapper GetBaseTypeWrapper(Type type)
{ {
if(type.IsInterface) if(type.IsInterface)
{ {
@ -3727,12 +3596,15 @@ class CompiledTypeWrapper : TypeWrapper
internal CompiledTypeWrapper(string name, Type type) internal CompiledTypeWrapper(string name, Type type)
: base(GetModifiers(type), name, GetBaseTypeWrapper(type), ClassLoaderWrapper.GetBootstrapClassLoader()) : base(GetModifiers(type), name, GetBaseTypeWrapper(type), ClassLoaderWrapper.GetBootstrapClassLoader())
{ {
Debug.Assert(!type.IsDefined(typeof(HideFromReflectionAttribute), false));
Debug.Assert(!(type is TypeBuilder)); Debug.Assert(!(type is TypeBuilder));
Debug.Assert(!type.IsArray); Debug.Assert(!type.IsArray);
Debug.Assert(!ClassLoaderWrapper.IsRemappedType(type));
this.type = type; this.type = type;
} }
private static Modifiers GetModifiers(Type type) internal static Modifiers GetModifiers(Type type)
{ {
try try
{ {
@ -3922,7 +3794,7 @@ class CompiledTypeWrapper : TypeWrapper
emitSet = CodeEmitter.Nop; emitSet = CodeEmitter.Nop;
} }
} }
return FieldWrapper.Create(this, ClassLoaderWrapper.GetWrapperFromType(fieldType), name, MethodDescriptor.GetFieldSigName(field), modifiers, emitGet, emitSet); return FieldWrapper.Create(this, ClassLoaderWrapper.GetWrapperFromType(fieldType), name, MethodDescriptor.GetFieldSigName(field), modifiers, field, emitGet, emitSet);
} }
protected override FieldWrapper GetFieldImpl(string fieldName) protected override FieldWrapper GetFieldImpl(string fieldName)
@ -4071,6 +3943,555 @@ class CompiledTypeWrapper : TypeWrapper
} }
} }
class DotNetTypeWrapper : TypeWrapper
{
private const string NamePrefix = "cli.";
private const string DelegateInterfaceSuffix = "$Method";
private readonly Type type;
private bool membersPublished;
private TypeWrapper[] innerClasses;
private TypeWrapper outerClass;
private static Modifiers GetModifiers(Type type)
{
Modifiers mods = CompiledTypeWrapper.GetModifiers(type);
if(ClassLoaderWrapper.IsRemappedType(type) && !type.IsInterface)
{
mods |= Modifiers.Final;
}
return mods;
}
// NOTE when this is called on a remapped type, the "warped" underlying type name is returned.
// E.g. GetName(typeof(object)) returns "cli.System.Object".
internal static string GetName(Type type)
{
Debug.Assert(!type.Assembly.IsDefined(typeof(JavaAssemblyAttribute), false), type.FullName);
// TODO a fully reversible name mangling should be used (all characters not supported by Java should be escaped)
return NamePrefix + type.FullName.Replace('+', '$');
}
// this method should only be called once for each name, it doesn't do any caching or duplicate prevention
internal static TypeWrapper LoadDotNetTypeWrapper(string name)
{
if(name.StartsWith(NamePrefix))
{
name = name.Substring(NamePrefix.Length);
Type type = LoadTypeFromLoadedAssemblies(name);
if(type != null)
{
return new DotNetTypeWrapper(type);
}
if(name.EndsWith(DelegateInterfaceSuffix))
{
Type delegateType = LoadTypeFromLoadedAssemblies(name.Substring(0, name.Length - DelegateInterfaceSuffix.Length));
if(delegateType.IsSubclassOf(typeof(Delegate)))
{
ModuleBuilder moduleBuilder = ClassLoaderWrapper.GetBootstrapClassLoader().ModuleBuilder;
TypeBuilder typeBuilder = moduleBuilder.DefineType(NamePrefix + name, TypeAttributes.Public | TypeAttributes.Interface | TypeAttributes.Abstract);
AttributeHelper.SetInnerClass(typeBuilder, NamePrefix + name, NamePrefix + delegateType.FullName, "Method", Modifiers.Public | Modifiers.Interface | Modifiers.Static | Modifiers.Abstract);
MethodInfo invoke = delegateType.GetMethod("Invoke");
if(invoke != null)
{
ParameterInfo[] parameters = invoke.GetParameters();
Type[] args = new Type[parameters.Length];
for(int i = 0; i < args.Length; i++)
{
// HACK if the delegate has pointer args, we cannot handle them, but it is already
// to late to refuse to load the class, so we replace pointers with IntPtr.
// This is not a solution, because if the delegate would be instantiated the generated
// code would be invalid.
if(parameters[i].ParameterType.IsPointer)
{
args[i] = typeof(IntPtr);
}
else
{
args[i] = parameters[i].ParameterType;
}
}
typeBuilder.DefineMethod("Invoke", MethodAttributes.Public | MethodAttributes.Abstract | MethodAttributes.Virtual, CallingConventions.Standard, invoke.ReturnType, args);
return new CompiledTypeWrapper(NamePrefix + name, typeBuilder.CreateType());
}
}
}
}
return null;
}
private static Type LoadTypeFromLoadedAssemblies(string name)
{
foreach(Assembly a in AppDomain.CurrentDomain.GetAssemblies())
{
// HACK we also look inside Java assemblies, because precompiled delegate interfaces might have ended up there
if(!(a is AssemblyBuilder))
{
Type t = a.GetType(name);
if(t != null)
{
return t;
}
// HACK we might be looking for an inner classes
t = a.GetType(name.Replace('$', '+'));
if(t != null)
{
return t;
}
}
}
return null;
}
internal DotNetTypeWrapper(Type type)
: base(GetModifiers(type), GetName(type), CompiledTypeWrapper.GetBaseTypeWrapper(type), ClassLoaderWrapper.GetBootstrapClassLoader())
{
Debug.Assert(!(type.IsByRef), type.FullName);
Debug.Assert(!(type.IsPointer), type.FullName);
Debug.Assert(!(type.IsArray), type.FullName);
Debug.Assert(!(type is TypeBuilder), type.FullName);
Debug.Assert(!(type.Assembly.IsDefined(typeof(JavaAssemblyAttribute), false)));
this.type = type;
}
private void LazyPublishMembers()
{
// special support for enums
if(type.IsEnum)
{
// TODO handle unsigned underlying type
TypeWrapper fieldType = ClassLoaderWrapper.GetWrapperFromType(Enum.GetUnderlyingType(type));
FieldInfo[] fields = type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Static);
for(int i = 0; i < fields.Length; i++)
{
if(fields[i].FieldType == type)
{
// TODO handle name/signature clash
AddField(FieldWrapper.Create(this, fieldType, fields[i].Name, fieldType.SigName, Modifiers.Public | Modifiers.Static | Modifiers.Final, fields[i], CodeEmitter.CreateLoadConstant(fields[i].GetValue(null)), CodeEmitter.Pop));
}
}
CodeEmitter getter = CodeEmitter.Create(OpCodes.Unbox, type) + CodeEmitter.Create(OpCodes.Ldobj, type);
CodeEmitter setter = CodeEmitter.Pop + CodeEmitter.Pop;
FieldWrapper fw = FieldWrapper.Create(this, fieldType, "Value", fieldType.SigName, Modifiers.Public | Modifiers.Final, null, getter, setter);
AddField(fw);
MethodWrapper mw = new MethodWrapper(this, MethodDescriptor.FromNameSig(GetClassLoader(), "wrap", "(" + fieldType.SigName + ")" + this.SigName), null, null, Modifiers.Static | Modifiers.Public, false);
mw.EmitCall = CodeEmitter.Create(OpCodes.Box, type);
AddMethod(mw);
}
else
{
bool isRemapped = ClassLoaderWrapper.IsRemappedType(type) && !type.IsInterface;
FieldInfo[] fields = type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance);
for(int i = 0; i < fields.Length; i++)
{
// TODO for remapped types, instance fields need to be converted to static getter/setter methods
if(fields[i].FieldType.IsPointer)
{
// skip, pointer fields are not supported
}
else
{
// TODO handle name/signature clash
AddField(CreateFieldWrapper(AttributeHelper.GetModifiers(fields[i]), fields[i].Name, fields[i].FieldType, fields[i], null));
}
}
// special case for delegate constructors!
if(!type.IsAbstract && type.IsSubclassOf(typeof(Delegate)))
{
TypeWrapper iface = GetClassLoader().LoadClassByDottedName(this.Name + DelegateInterfaceSuffix);
Debug.Assert(iface is CompiledTypeWrapper);
iface.Finish();
MethodDescriptor md = MethodDescriptor.FromNameSig(GetClassLoader(), "<init>", "(" + iface.SigName + ")V");
// TODO set method flags
MethodWrapper method = new MethodWrapper(this, md, null, null, Modifiers.Public, false);
method.EmitNewobj = new DelegateConstructorEmitter(type.GetConstructor(new Type[] { typeof(object), typeof(IntPtr) }), iface.Type.GetMethod("Invoke"));
AddMethod(method);
innerClasses = new TypeWrapper[] { iface };
}
ConstructorInfo[] constructors = type.GetConstructors(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance);
for(int i = 0; i < constructors.Length; i++)
{
MethodDescriptor md = MakeMethodDescriptor(constructors[i], isRemapped);
if(md != null)
{
// TODO handle name/signature clash
AddMethod(CreateMethodWrapper(md, constructors[i], isRemapped));
}
}
MethodInfo[] methods = type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance);
for(int i = 0; i < methods.Length; i++)
{
MethodDescriptor md = MakeMethodDescriptor(methods[i], isRemapped);
if(md != null)
{
// TODO handle name/signature clash
AddMethod(CreateMethodWrapper(md, methods[i], isRemapped));
}
}
}
}
private MethodDescriptor MakeMethodDescriptor(MethodBase mb, bool isRemapped)
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
sb.Append('(');
ParameterInfo[] parameters = mb.GetParameters();
int bias = (isRemapped && !mb.IsStatic && !mb.IsConstructor) ? 1 : 0;
TypeWrapper[] args = new TypeWrapper[parameters.Length + bias];
if(bias == 1)
{
args[0] = ClassLoaderWrapper.GetWrapperFromType(mb.DeclaringType);
sb.Append(args[0].SigName);
}
for(int i = 0; i < parameters.Length; i++)
{
Type type = parameters[i].ParameterType;
if(type.IsPointer)
{
return null;
}
if(type.IsByRef)
{
type = type.Assembly.GetType(type.GetElementType().FullName + "[]", true);
}
TypeWrapper tw = ClassLoaderWrapper.GetWrapperFromType(type);
args[i + bias] = tw;
sb.Append(tw.SigName);
}
sb.Append(')');
if(mb is ConstructorInfo)
{
TypeWrapper ret = PrimitiveTypeWrapper.VOID;
string name;
if(mb.IsStatic)
{
name = "<clinit>";
}
else if(isRemapped)
{
name = "__new";
ret = ClassLoaderWrapper.GetWrapperFromType(mb.DeclaringType);
}
else
{
name = "<init>";
}
sb.Append(ret.SigName);
return new MethodDescriptor(GetClassLoader(), name, sb.ToString(), args, ret);
}
else
{
Type type = ((MethodInfo)mb).ReturnType;
if(type.IsPointer)
{
return null;
}
TypeWrapper ret = ClassLoaderWrapper.GetWrapperFromType(type);
sb.Append(ret.SigName);
return new MethodDescriptor(GetClassLoader(), mb.Name, sb.ToString(), args, ret);
}
}
public override TypeWrapper[] Interfaces
{
get
{
// remapped type cannot be instantiated, so it wouldn't make sense to implement
// interfaces
if(ClassLoaderWrapper.IsRemappedType(Type) && !Type.IsInterface)
{
return TypeWrapper.EmptyArray;
}
Type[] interfaces = type.GetInterfaces();
TypeWrapper[] interfaceWrappers = new TypeWrapper[interfaces.Length];
for(int i = 0; i < interfaces.Length; i++)
{
interfaceWrappers[i] = ClassLoaderWrapper.GetWrapperFromType(interfaces[i]);
}
return interfaceWrappers;
}
}
public override TypeWrapper[] InnerClasses
{
get
{
lock(this)
{
if(innerClasses == null)
{
Type[] nestedTypes = type.GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic);
innerClasses = new TypeWrapper[nestedTypes.Length];
for(int i = 0; i < nestedTypes.Length; i++)
{
innerClasses[i] = ClassLoaderWrapper.GetWrapperFromType(nestedTypes[i]);
}
}
}
return innerClasses;
}
}
public override TypeWrapper DeclaringTypeWrapper
{
get
{
if(outerClass == null)
{
Type outer = type.DeclaringType;
if(outer != null)
{
outerClass = ClassLoaderWrapper.GetWrapperFromType(outer);
}
}
return outerClass;
}
}
internal override Modifiers ReflectiveModifiers
{
get
{
if(DeclaringTypeWrapper != null)
{
return Modifiers | Modifiers.Static;
}
return Modifiers;
}
}
// TODO support NonPrimitiveValueTypes
// TODO why doesn't this use the standard FieldWrapper.Create?
private FieldWrapper CreateFieldWrapper(Modifiers modifiers, string name, Type fieldType, FieldInfo field, MethodInfo getter)
{
CodeEmitter emitGet;
CodeEmitter emitSet;
if((modifiers & Modifiers.Static) != 0)
{
if(getter != null)
{
emitGet = CodeEmitter.Create(OpCodes.Call, getter);
}
else
{
// if field is a literal, we must emit an ldc instead of a ldsfld
if(field.IsLiteral)
{
emitGet = CodeEmitter.CreateLoadConstant(field.GetValue(null));
}
else
{
emitGet = CodeEmitter.Create(OpCodes.Ldsfld, field);
}
}
if(field != null && !field.IsLiteral)
{
emitSet = CodeEmitter.Create(OpCodes.Stsfld, field);
}
else
{
// TODO what happens when you try to set a final field?
// through reflection: java.lang.IllegalAccessException: Field is final
// through code: java.lang.IllegalAccessError: Field <class>.<field> is final
emitSet = CodeEmitter.Nop;
}
}
else
{
if(getter != null)
{
emitGet = CodeEmitter.Create(OpCodes.Callvirt, getter);
}
else
{
// TODO is it possible to have literal instance fields?
emitGet = CodeEmitter.Create(OpCodes.Ldfld, field);
}
if(field != null)
{
emitSet = CodeEmitter.Create(OpCodes.Stfld, field);
}
else
{
// TODO what happens when you try to set a final field through reflection?
// see above
emitSet = CodeEmitter.Nop;
}
}
return FieldWrapper.Create(this, ClassLoaderWrapper.GetWrapperFromType(fieldType), name, MethodDescriptor.GetFieldSigName(field), modifiers, field, emitGet, emitSet);
}
// TODO why doesn't this use the standard MethodWrapper.Create?
private MethodWrapper CreateMethodWrapper(MethodDescriptor md, MethodBase mb, bool isRemapped)
{
ParameterInfo[] parameters = mb.GetParameters();
Type[] args = new Type[parameters.Length];
bool hasByRefArgs = false;
for(int i = 0; i < parameters.Length; i++)
{
args[i] = parameters[i].ParameterType;
if(parameters[i].ParameterType.IsByRef)
{
hasByRefArgs = true;
}
}
Modifiers mods = AttributeHelper.GetModifiers(mb);
if(isRemapped)
{
// all methods are static and final doesn't make sense
mods |= Modifiers.Static;
mods &= ~Modifiers.Final;
}
MethodWrapper method = new MethodWrapper(this, md, mb, null, mods, false);
if(mb is ConstructorInfo)
{
if(isRemapped)
{
method.EmitCall = CodeEmitter.Create(OpCodes.Newobj, (ConstructorInfo)mb);
}
else
{
method.EmitCall = CodeEmitter.Create(OpCodes.Call, (ConstructorInfo)mb);
method.EmitNewobj = CodeEmitter.Create(OpCodes.Newobj, (ConstructorInfo)mb);
if(this.IsNonPrimitiveValueType)
{
method.EmitNewobj += CodeEmitter.Create(OpCodes.Box, this.Type);
}
}
}
else
{
bool nonPrimitiveValueType = md.RetTypeWrapper.IsNonPrimitiveValueType;
method.EmitCall = CodeEmitter.Create(OpCodes.Call, (MethodInfo)mb);
if(nonPrimitiveValueType)
{
method.EmitCall += CodeEmitter.Create(OpCodes.Box, md.RetTypeWrapper.Type);
}
if(!mb.IsStatic)
{
method.EmitCallvirt = CodeEmitter.Create(OpCodes.Callvirt, (MethodInfo)mb);
if(nonPrimitiveValueType)
{
method.EmitCallvirt += CodeEmitter.Create(OpCodes.Box, md.RetTypeWrapper.Type);
}
}
}
if(hasByRefArgs)
{
method.EmitCall = new RefArgConverter(args) + method.EmitCall;
method.EmitCallvirt = new RefArgConverter(args) + method.EmitCallvirt;
method.EmitNewobj = new RefArgConverter(args) + method.EmitNewobj;
}
return method;
}
private class DelegateConstructorEmitter : CodeEmitter
{
private ConstructorInfo delegateConstructor;
private MethodInfo method;
internal DelegateConstructorEmitter(ConstructorInfo delegateConstructor, MethodInfo method)
{
this.delegateConstructor = delegateConstructor;
this.method = method;
}
internal override void Emit(ILGenerator ilgen)
{
ilgen.Emit(OpCodes.Dup);
ilgen.Emit(OpCodes.Ldvirtftn, method);
ilgen.Emit(OpCodes.Newobj, delegateConstructor);
}
}
private class RefArgConverter : CodeEmitter
{
private Type[] args;
internal RefArgConverter(Type[] args)
{
this.args = args;
}
internal override void Emit(ILGenerator ilgen)
{
LocalBuilder[] locals = new LocalBuilder[args.Length];
for(int i = args.Length - 1; i >= 0; i--)
{
Type type = args[i];
if(type.IsByRef)
{
type = type.Assembly.GetType(type.GetElementType().FullName + "[]", true);
}
locals[i] = ilgen.DeclareLocal(type);
ilgen.Emit(OpCodes.Stloc, locals[i]);
}
for(int i = 0; i < args.Length; i++)
{
ilgen.Emit(OpCodes.Ldloc, locals[i]);
if(args[i].IsByRef)
{
ilgen.Emit(OpCodes.Ldc_I4_0);
ilgen.Emit(OpCodes.Ldelema, args[i].GetElementType());
}
}
}
}
protected override FieldWrapper GetFieldImpl(string fieldName)
{
lock(this)
{
if(!membersPublished)
{
membersPublished = true;
LazyPublishMembers();
return GetFieldWrapper(fieldName);
}
}
return null;
}
protected override MethodWrapper GetMethodImpl(MethodDescriptor md)
{
lock(this)
{
if(!membersPublished)
{
membersPublished = true;
LazyPublishMembers();
return GetMethodWrapper(md, false);
}
}
return null;
}
public override Type Type
{
get
{
return type;
}
}
public override void Finish()
{
lock(this)
{
if(!membersPublished)
{
membersPublished = true;
LazyPublishMembers();
}
}
}
}
class ArrayTypeWrapper : TypeWrapper class ArrayTypeWrapper : TypeWrapper
{ {
private static TypeWrapper[] interfaces; private static TypeWrapper[] interfaces;
@ -4101,6 +4522,15 @@ class ArrayTypeWrapper : TypeWrapper
AddMethod(mw); AddMethod(mw);
} }
internal override string SigName
{
get
{
// for arrays the signature name is the same as the normal name
return Name;
}
}
public override TypeWrapper[] Interfaces public override TypeWrapper[] Interfaces
{ {
get get

Просмотреть файл

@ -179,6 +179,10 @@ namespace NativeCode.java
{ {
return Activator.CreateInstance(java_lang_Byte, new object[] { o }); return Activator.CreateInstance(java_lang_Byte, new object[] { o });
} }
else if(o is byte)
{
return Activator.CreateInstance(java_lang_Byte, new object[] { (sbyte)(byte)o });
}
else if(o is bool) else if(o is bool)
{ {
return Activator.CreateInstance(java_lang_Boolean, new object[] { o }); return Activator.CreateInstance(java_lang_Boolean, new object[] { o });
@ -187,6 +191,10 @@ namespace NativeCode.java
{ {
return Activator.CreateInstance(java_lang_Short, new object[] { o }); return Activator.CreateInstance(java_lang_Short, new object[] { o });
} }
else if(o is ushort)
{
return Activator.CreateInstance(java_lang_Short, new object[] { (short)(ushort)o });
}
else if(o is char) else if(o is char)
{ {
return Activator.CreateInstance(java_lang_Character, new object[] { o }); return Activator.CreateInstance(java_lang_Character, new object[] { o });
@ -195,10 +203,18 @@ namespace NativeCode.java
{ {
return Activator.CreateInstance(java_lang_Integer, new object[] { o }); return Activator.CreateInstance(java_lang_Integer, new object[] { o });
} }
else if(o is uint)
{
return Activator.CreateInstance(java_lang_Integer, new object[] { (int)(uint)o });
}
else if(o is long) else if(o is long)
{ {
return Activator.CreateInstance(java_lang_Long, new object[] { o }); return Activator.CreateInstance(java_lang_Long, new object[] { o });
} }
else if(o is ulong)
{
return Activator.CreateInstance(java_lang_Long, new object[] { (long)(ulong)o });
}
else if(o is float) else if(o is float)
{ {
return Activator.CreateInstance(java_lang_Float, new object[] { o }); return Activator.CreateInstance(java_lang_Float, new object[] { o });
@ -207,6 +223,38 @@ namespace NativeCode.java
{ {
return Activator.CreateInstance(java_lang_Double, new object[] { o }); return Activator.CreateInstance(java_lang_Double, new object[] { o });
} }
else if(o is Enum)
{
Type enumType = Enum.GetUnderlyingType(o.GetType());
if(enumType == typeof(byte) || enumType == typeof(sbyte))
{
return JavaWrapper.Box((sbyte)((IConvertible)o).ToInt32(null));
}
else if(enumType == typeof(short) || enumType == typeof(ushort))
{
return JavaWrapper.Box((short)((IConvertible)o).ToInt32(null));
}
else if(enumType == typeof(int))
{
return JavaWrapper.Box(((IConvertible)o).ToInt32(null));
}
else if(enumType == typeof(uint))
{
return JavaWrapper.Box(unchecked((int)((IConvertible)o).ToUInt32(null)));
}
else if(enumType == typeof(long))
{
return JavaWrapper.Box(((IConvertible)o).ToInt64(null));
}
else if(enumType == typeof(ulong))
{
return JavaWrapper.Box(unchecked((long)((IConvertible)o).ToUInt64(null)));
}
else
{
throw new InvalidOperationException();
}
}
else else
{ {
throw new NotImplementedException(o.GetType().FullName); throw new NotImplementedException(o.GetType().FullName);
@ -327,6 +375,14 @@ namespace NativeCode.java
public class Field public class Field
{ {
// HACK this is used by netexp to query the constant value of a field
public static object getConstant(object field)
{
// HACK we use reflection to extract the fieldCookie from the java.lang.reflect.Field object
FieldWrapper wrapper = (FieldWrapper)field.GetType().GetField("fieldCookie", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(field);
return wrapper.GetConstant();
}
public static string GetName(object fieldCookie) public static string GetName(object fieldCookie)
{ {
FieldWrapper wrapper = (FieldWrapper)fieldCookie; FieldWrapper wrapper = (FieldWrapper)fieldCookie;
@ -951,28 +1007,28 @@ namespace NativeCode.java
return null; return null;
} }
public static Type getPrimitiveType(char type) public static object getPrimitiveClass(char type)
{ {
switch(type) switch(type)
{ {
case 'Z': case 'Z':
return typeof(bool); return VMClass.getClassFromType(typeof(bool));
case 'B': case 'B':
return typeof(sbyte); return VMClass.getClassFromType(typeof(sbyte));
case 'C': case 'C':
return typeof(char); return VMClass.getClassFromType(typeof(char));
case 'D': case 'D':
return typeof(double); return VMClass.getClassFromType(typeof(double));
case 'F': case 'F':
return typeof(float); return VMClass.getClassFromType(typeof(float));
case 'I': case 'I':
return typeof(int); return VMClass.getClassFromType(typeof(int));
case 'J': case 'J':
return typeof(long); return VMClass.getClassFromType(typeof(long));
case 'S': case 'S':
return typeof(short); return VMClass.getClassFromType(typeof(short));
case 'V': case 'V':
return typeof(void); return VMClass.getClassFromType(typeof(void));
default: default:
throw new InvalidOperationException(); throw new InvalidOperationException();
} }
@ -990,7 +1046,7 @@ namespace NativeCode.java
throw JavaException.NoClassDefFoundError("{0} (wrong name: {1})", name, classFile.Name); throw JavaException.NoClassDefFoundError("{0} (wrong name: {1})", name, classFile.Name);
} }
TypeWrapper type = ClassLoaderWrapper.GetClassLoaderWrapper(classLoader).DefineClass(classFile); TypeWrapper type = ClassLoaderWrapper.GetClassLoaderWrapper(classLoader).DefineClass(classFile);
object clazz = VMClass.CreateInstance(null, type); object clazz = VMClass.CreateClassInstance(type);
if(protectionDomain != null) if(protectionDomain != null)
{ {
// TODO cache the FieldInfo // TODO cache the FieldInfo
@ -1008,8 +1064,9 @@ namespace NativeCode.java
public class VMClass public class VMClass
{ {
private static Hashtable map = new Hashtable(); private static Hashtable map = new Hashtable();
private static MethodInfo createClass; private delegate object CreateClassDelegate(object typeWrapper);
private static MethodInfo getTypeMethod; private static CreateClassDelegate CreateClass;
private static MethodInfo getWrapper;
public static void throwException(Exception e) public static void throwException(Exception e)
{ {
@ -1038,20 +1095,27 @@ namespace NativeCode.java
return null; return null;
} }
internal static object CreateInstance(Type type, TypeWrapper wrapper) internal static object CreateClassInstance(TypeWrapper wrapper)
{ {
TypeWrapper.AssertFinished(type); if(CreateClass == null)
if(createClass == null)
{ {
createClass = ClassLoaderWrapper.GetType("java.lang.VMClass").GetMethod("createClass", BindingFlags.Static | BindingFlags.NonPublic); CreateClass = (CreateClassDelegate)Delegate.CreateDelegate(typeof(CreateClassDelegate), ClassLoaderWrapper.GetType("java.lang.VMClass").GetMethod("createClass", BindingFlags.Static | BindingFlags.Public));
// HACK to make sure we don't run into any problems creating class objects for classes that
// participate in the VMClass static initialization, we first do a bogus call to initialize
// the machinery (I ran into this when running netexp on classpath.dll)
CreateClass(null);
lock(map.SyncRoot)
{
object o = map[wrapper];
if(o != null)
{
return o;
}
}
} }
object clazz = createClass.Invoke(null, new object[] { type, wrapper }); object clazz = CreateClass(wrapper);
lock(map.SyncRoot) lock(map.SyncRoot)
{ {
if(type != null)
{
map.Add(type, clazz);
}
if(wrapper != null) if(wrapper != null)
{ {
map.Add(wrapper, clazz); map.Add(wrapper, clazz);
@ -1060,11 +1124,21 @@ namespace NativeCode.java
return clazz; return clazz;
} }
public static bool IsAssignableFrom(Object w1, Object w2) public static bool IsAssignableFrom(object w1, object w2)
{ {
return ((TypeWrapper)w2).IsAssignableTo((TypeWrapper)w1); return ((TypeWrapper)w2).IsAssignableTo((TypeWrapper)w1);
} }
public static bool IsInterface(object wrapper)
{
return ((TypeWrapper)wrapper).IsInterface;
}
public static bool IsArray(object wrapper)
{
return ((TypeWrapper)wrapper).IsArray;
}
public static object GetSuperClassFromWrapper(object wrapper) public static object GetSuperClassFromWrapper(object wrapper)
{ {
TypeWrapper baseWrapper = ((TypeWrapper)wrapper).BaseTypeWrapper; TypeWrapper baseWrapper = ((TypeWrapper)wrapper).BaseTypeWrapper;
@ -1093,13 +1167,6 @@ namespace NativeCode.java
((TypeWrapper)wrapper).Finish(); ((TypeWrapper)wrapper).Finish();
Type type = ((TypeWrapper)wrapper).Type; Type type = ((TypeWrapper)wrapper).Type;
TypeWrapper.AssertFinished(type); TypeWrapper.AssertFinished(type);
lock(map.SyncRoot)
{
// NOTE since this method can be called multiple times (or after getClassFromType has added
// the Class to the map), we don't use Add() here, but the indexer because that can handle
// "overwriting" the existing association (which should always be the same as the new one)
map[type] = clazz;
}
return type; return type;
} }
@ -1110,11 +1177,13 @@ namespace NativeCode.java
public static Type getType(object clazz) public static Type getType(object clazz)
{ {
if(getTypeMethod == null) if(getWrapper == null)
{ {
getTypeMethod = ClassLoaderWrapper.GetType("java.lang.VMClass").GetMethod("getTypeFromClass", BindingFlags.NonPublic | BindingFlags.Static); getWrapper = ClassLoaderWrapper.GetType("java.lang.VMClass").GetMethod("getWrapperFromClass", BindingFlags.NonPublic | BindingFlags.Static);
} }
return (Type)getTypeMethod.Invoke(null, new object[] { clazz }); TypeWrapper wrapper = (TypeWrapper)getWrapper.Invoke(null, new object[] { clazz });
wrapper.Finish();
return wrapper.Type;
} }
internal static object getClassFromWrapper(TypeWrapper wrapper) internal static object getClassFromWrapper(TypeWrapper wrapper)
@ -1124,12 +1193,7 @@ namespace NativeCode.java
object clazz = map[wrapper]; object clazz = map[wrapper];
if(clazz == null) if(clazz == null)
{ {
// Maybe the Class object was already constructed from the type clazz = CreateClassInstance(wrapper);
clazz = map[wrapper.Type];
if(clazz == null)
{
clazz = CreateInstance(null, wrapper);
}
} }
return clazz; return clazz;
} }
@ -1142,71 +1206,61 @@ namespace NativeCode.java
{ {
return null; return null;
} }
lock(map.SyncRoot) return getClassFromWrapper(ClassLoaderWrapper.GetWrapperFromType(type));
{
object clazz = map[type];
if(clazz == null)
{
// maybe the Class object was constructed from the wrapper
TypeWrapper wrapper = ClassLoaderWrapper.GetWrapperFromTypeFast(type);
if(wrapper != null)
{
clazz = map[wrapper];
if(clazz != null)
{
map.Add(type, clazz);
return clazz;
}
}
// NOTE we need to get the bootstrap classloader to trigger its construction (if it
// hasn't been created yet), because otherwise CreateInstance will do that and this
// causes the same class object to be created multiple times)
ClassLoaderWrapper.GetBootstrapClassLoader();
clazz = map[type];
if(clazz == null)
{
// if this type is an override stub (e.g. java.lang.Object), we need to return the
// class object for the parent type
// NOTE we first check if type isn't an array, because Type.IsDefined throws an exception
// when called on an array type (?)
if(!type.IsArray && type.IsDefined(typeof(HideFromReflectionAttribute), false))
{
clazz = getClassFromType(type.BaseType);
map.Add(type, clazz);
}
else
{
// TODO should we specify the wrapper?
// NOTE CreateInstance adds the Class to the "map"
clazz = CreateInstance(type, null);
}
}
}
return clazz;
}
} }
public static string getName(Type type) public static string GetName(object wrapper)
{ {
return GetName(type, null); TypeWrapper typeWrapper = (TypeWrapper)wrapper;
if(typeWrapper.IsPrimitive)
{
if(typeWrapper == PrimitiveTypeWrapper.VOID)
{
return "void";
}
else if(typeWrapper == PrimitiveTypeWrapper.BYTE)
{
return "byte";
}
else if(typeWrapper == PrimitiveTypeWrapper.BOOLEAN)
{
return "boolean";
}
else if(typeWrapper == PrimitiveTypeWrapper.SHORT)
{
return "short";
}
else if(typeWrapper == PrimitiveTypeWrapper.CHAR)
{
return "char";
}
else if(typeWrapper == PrimitiveTypeWrapper.INT)
{
return "int";
}
else if(typeWrapper == PrimitiveTypeWrapper.LONG)
{
return "long";
}
else if(typeWrapper == PrimitiveTypeWrapper.FLOAT)
{
return "float";
}
else if(typeWrapper == PrimitiveTypeWrapper.DOUBLE)
{
return "double";
}
else
{
throw new InvalidOperationException();
}
}
return typeWrapper.Name;
} }
public static string GetName(Type type, object wrapperType) internal static string getName(Type type)
{ {
if(type == null) TypeWrapper wrapperType = ClassLoaderWrapper.GetWrapperFromTypeFast(type);
{
string name = ((TypeWrapper)wrapperType).Name;
// HACK name is null for primitives
if(name != null)
{
return name;
}
type = ((TypeWrapper)wrapperType).Type;
}
if(wrapperType == null)
{
wrapperType = ClassLoaderWrapper.GetWrapperFromTypeFast(type);
}
if(wrapperType != null) if(wrapperType != null)
{ {
string name = ((TypeWrapper)wrapperType).Name; string name = ((TypeWrapper)wrapperType).Name;
@ -1256,7 +1310,8 @@ namespace NativeCode.java
} }
else else
{ {
return type.FullName; // HACK we're assuming for the time being that Java code cannot define new value types
return DotNetTypeWrapper.GetName(type);
} }
} }
else if(type.IsArray) else if(type.IsArray)
@ -1307,12 +1362,13 @@ namespace NativeCode.java
} }
else else
{ {
sb.Append(type.FullName); // HACK we're assuming for the time being that Java code cannot define new value types
sb.Append(DotNetTypeWrapper.GetName(type));
} }
} }
else else
{ {
sb.Append('L').Append(GetName(type, null)).Append(';'); sb.Append('L').Append(getName(type)).Append(';');
} }
return sb.ToString(); return sb.ToString();
} }
@ -1333,32 +1389,38 @@ namespace NativeCode.java
{ {
return ((InnerClassAttribute)attribs[0]).InnerClassName; return ((InnerClassAttribute)attribs[0]).InnerClassName;
} }
return type.FullName; if(type.Assembly is System.Reflection.Emit.AssemblyBuilder || type.Assembly.IsDefined(typeof(JavaAssemblyAttribute), false))
{
return type.FullName;
}
else
{
return DotNetTypeWrapper.GetName(type);
}
} }
} }
[StackTraceInfo(Hidden = true)] [StackTraceInfo(Hidden = true)]
public static void initializeType(Type type) public static void initialize(object cwrapper)
{ {
RuntimeHelpers.RunClassConstructor(type.TypeHandle); TypeWrapper wrapper = (TypeWrapper)cwrapper;
} wrapper.Finish();
RuntimeHelpers.RunClassConstructor(wrapper.Type.TypeHandle);
public static object getClassLoader0(Type type, object wrapper) }
{
if(wrapper != null) public static object getClassLoader0(object wrapper)
{ {
return ((TypeWrapper)wrapper).GetClassLoader().GetJavaClassLoader(); return ((TypeWrapper)wrapper).GetClassLoader().GetJavaClassLoader();
} }
return ClassLoaderWrapper.GetClassLoader(type).GetJavaClassLoader();
} public static object getClassLoaderFromType(Type type)
{
public static object[] GetDeclaredMethods(Type type, object cwrapper, bool getMethods, bool publicOnly) return ClassLoaderWrapper.GetWrapperFromType(type).GetClassLoader().GetJavaClassLoader();
}
public static object[] GetDeclaredMethods(object cwrapper, bool getMethods, bool publicOnly)
{ {
TypeWrapper wrapper = (TypeWrapper)cwrapper; TypeWrapper wrapper = (TypeWrapper)cwrapper;
if(wrapper == null)
{
wrapper = ClassLoaderWrapper.GetWrapperFromType(type);
}
// we need to finish the type otherwise all methods will not be in the method map yet // we need to finish the type otherwise all methods will not be in the method map yet
wrapper.Finish(); wrapper.Finish();
// we need to look through the array for unloadable types, because we may not let them // we need to look through the array for unloadable types, because we may not let them
@ -1400,13 +1462,9 @@ namespace NativeCode.java
return (MethodWrapper[])list.ToArray(typeof(MethodWrapper)); return (MethodWrapper[])list.ToArray(typeof(MethodWrapper));
} }
public static object[] GetDeclaredFields(Type type, object cwrapper, bool publicOnly) public static object[] GetDeclaredFields(object cwrapper, bool publicOnly)
{ {
TypeWrapper wrapper = (TypeWrapper)cwrapper; TypeWrapper wrapper = (TypeWrapper)cwrapper;
if(wrapper == null)
{
wrapper = ClassLoaderWrapper.GetWrapperFromType(type);
}
// we need to finish the type otherwise all fields will not be in the field map yet // we need to finish the type otherwise all fields will not be in the field map yet
wrapper.Finish(); wrapper.Finish();
// we need to look through the array for unloadable types, because we may not let them // we need to look through the array for unloadable types, because we may not let them
@ -1434,13 +1492,9 @@ namespace NativeCode.java
return fields; return fields;
} }
public static object[] GetDeclaredClasses(Type type, object cwrapper, bool publicOnly) public static object[] GetDeclaredClasses(object cwrapper, bool publicOnly)
{ {
TypeWrapper wrapper = (TypeWrapper)cwrapper; TypeWrapper wrapper = (TypeWrapper)cwrapper;
if(wrapper == null)
{
wrapper = ClassLoaderWrapper.GetWrapperFromType(type);
}
// NOTE to get at the InnerClasses we need to finish the type // NOTE to get at the InnerClasses we need to finish the type
wrapper.Finish(); wrapper.Finish();
TypeWrapper[] wrappers = wrapper.InnerClasses; TypeWrapper[] wrappers = wrapper.InnerClasses;
@ -1476,13 +1530,9 @@ namespace NativeCode.java
return innerclasses; return innerclasses;
} }
public static object GetDeclaringClass(Type type, object cwrapper) public static object GetDeclaringClass(object cwrapper)
{ {
TypeWrapper wrapper = (TypeWrapper)cwrapper; TypeWrapper wrapper = (TypeWrapper)cwrapper;
if(wrapper == null)
{
wrapper = ClassLoaderWrapper.GetWrapperFromType(type);
}
// before we can call DeclaringTypeWrapper, we need to finish the type // before we can call DeclaringTypeWrapper, we need to finish the type
wrapper.Finish(); wrapper.Finish();
TypeWrapper declaring = wrapper.DeclaringTypeWrapper; TypeWrapper declaring = wrapper.DeclaringTypeWrapper;
@ -1497,14 +1547,11 @@ namespace NativeCode.java
return getClassFromWrapper(declaring); return getClassFromWrapper(declaring);
} }
public static object[] GetInterfaces(Type type, object cwrapper) public static object[] GetInterfaces(object cwrapper)
{ {
TypeWrapper wrapper = (TypeWrapper)cwrapper; TypeWrapper wrapper = (TypeWrapper)cwrapper;
if(wrapper == null)
{
wrapper = ClassLoaderWrapper.GetWrapperFromType(type);
}
// we need to finish the type otherwise all fields will not be in the field map yet // we need to finish the type otherwise all fields will not be in the field map yet
// TODO this should not be needed (make sure it isn't and remove)
wrapper.Finish(); wrapper.Finish();
TypeWrapper[] interfaceWrappers = wrapper.Interfaces; TypeWrapper[] interfaceWrappers = wrapper.Interfaces;
object[] interfaces = new object[interfaceWrappers.Length]; object[] interfaces = new object[interfaceWrappers.Length];
@ -1515,13 +1562,9 @@ namespace NativeCode.java
return interfaces; return interfaces;
} }
public static int GetModifiers(Type type, Object cwrapper) public static int GetModifiers(Object cwrapper)
{ {
TypeWrapper wrapper = (TypeWrapper)cwrapper; TypeWrapper wrapper = (TypeWrapper)cwrapper;
if(wrapper == null)
{
wrapper = ClassLoaderWrapper.GetWrapperFromType(type);
}
// NOTE ReflectiveModifiers is only available for finished types // NOTE ReflectiveModifiers is only available for finished types
wrapper.Finish(); wrapper.Finish();
// NOTE we don't return the modifiers from the TypeWrapper, because for inner classes // NOTE we don't return the modifiers from the TypeWrapper, because for inner classes

Просмотреть файл

@ -960,7 +960,7 @@ class Compiler
if(instr.NormalizedOpCode == NormalizedByteCode.__invokespecial && cpi.Name == "<init>" && VerifierTypeWrapper.IsNew(type)) if(instr.NormalizedOpCode == NormalizedByteCode.__invokespecial && cpi.Name == "<init>" && VerifierTypeWrapper.IsNew(type))
{ {
TypeWrapper[] args = cpi.GetArgTypes(classLoader); TypeWrapper[] args = cpi.GetArgTypes(classLoader);
CastInterfaceArgs(args, i, true, false); CastInterfaceArgs(args, i, false, false);
} }
else else
{ {

Просмотреть файл

@ -27,23 +27,22 @@
<class name="java.lang.Object" type="System.Object" modifiers="public"> <class name="java.lang.Object" type="System.Object" modifiers="public">
<constructor sig="()V" modifiers="public" /> <constructor sig="()V" modifiers="public" />
<method name="notifyAll" sig="()V" modifiers="public final"> <method name="notifyAll" sig="()V" modifiers="public final">
<redirect class="System.Threading.Monitor" name="PulseAll" sig="(Ljava.lang.Object;)V" type="static" /> <redirect class="System.Threading.Monitor, mscorlib" name="PulseAll" sig="(Ljava.lang.Object;)V" type="static" />
</method> </method>
<method name="notify" sig="()V" modifiers="public final"> <method name="notify" sig="()V" modifiers="public final">
<redirect class="System.Threading.Monitor" name="Pulse" sig="(Ljava.lang.Object;)V" type="static" /> <redirect class="System.Threading.Monitor, mscorlib" name="Pulse" sig="(Ljava.lang.Object;)V" type="static" />
</method> </method>
<method name="wait" sig="()V" modifiers="public final"> <method name="wait" sig="()V" modifiers="public final">
<invokespecial> <invokespecial>
<call type="System.Threading.Monitor" name="Wait" sig="(Ljava.lang.Object;)Z" /> <call type="System.Threading.Monitor, mscorlib" name="Wait" sig="(Ljava.lang.Object;)Z" />
<!-- For some reason, Wait returns a boolean --> <!-- For some reason, Wait returns a boolean -->
<pop /> <pop />
</invokespecial> </invokespecial>
<invokevirtual> <invokevirtual>
<call type="System.Threading.Monitor" name="Wait" sig="(Ljava.lang.Object;)Z" /> <call type="System.Threading.Monitor, mscorlib" name="Wait" sig="(Ljava.lang.Object;)Z" />
<!-- For some reason, Wait returns a boolean --> <!-- For some reason, Wait returns a boolean -->
<pop /> <pop />
</invokevirtual> </invokevirtual>
<!--redirect class="System.Threading.Monitor" name="Wait" sig="(Ljava.lang.Object;)V" type="static" /-->
</method> </method>
<method name="wait" sig="(J)V" modifiers="public final"> <method name="wait" sig="(J)V" modifiers="public final">
<redirect class="java.lang.ObjectHelper" name="wait" sig="(Ljava.lang.Object;J)V" type="static" /> <redirect class="java.lang.ObjectHelper" name="wait" sig="(Ljava.lang.Object;J)V" type="static" />
@ -68,7 +67,7 @@
<invokespecial> <invokespecial>
<!-- TODO if we already know statically that the type implements java.lang.Cloneable this check can be omitted --> <!-- TODO if we already know statically that the type implements java.lang.Cloneable this check can be omitted -->
<dup /> <dup />
<isinst type="java.lang.Cloneable" /> <isinst class="java.lang.Cloneable" />
<brtrue name="ok" /> <brtrue name="ok" />
<newobj class="java.lang.CloneNotSupportedException" name="&lt;init&gt;" sig="()V" /> <newobj class="java.lang.CloneNotSupportedException" name="&lt;init&gt;" sig="()V" />
<throw /> <throw />
@ -104,9 +103,9 @@
<override name="GetHashCode" /> <override name="GetHashCode" />
<invokevirtual> <invokevirtual>
<dup /> <dup />
<isinst type="System.String" /> <isinst type="System.String, mscorlib" />
<brfalse name="skip" /> <brfalse name="skip" />
<castclass type="System.String" /> <castclass type="System.String, mscorlib" />
<call class="java.lang.StringHelper" name="hashCode" sig="(Ljava.lang.String;)I" /> <call class="java.lang.StringHelper" name="hashCode" sig="(Ljava.lang.String;)I" />
<br name="end" /> <br name="end" />
<label name="skip" /> <label name="skip" />
@ -121,7 +120,7 @@
<override name="Finalize" /> <override name="Finalize" />
</method> </method>
</class> </class>
<class name="java.lang.String" type="System.String" modifiers="public final"> <class name="java.lang.String" type="System.String, mscorlib" modifiers="public final">
<implements class="java.lang.Comparable" /> <implements class="java.lang.Comparable" />
<implements class="java.lang.CharSequence" /> <implements class="java.lang.CharSequence" />
<implements class="java.io.Serializable" /> <implements class="java.io.Serializable" />
@ -129,7 +128,7 @@
<!-- TODO --> <!-- TODO -->
<newobj> <newobj>
<ldstr value="" /> <ldstr value="" />
<call type="System.String" name="Copy" /> <call type="System.String, mscorlib" name="Copy" />
</newobj> </newobj>
</constructor> </constructor>
<constructor sig="([C)V" modifiers="public" /> <constructor sig="([C)V" modifiers="public" />
@ -139,7 +138,7 @@
<redirect class="java.lang.StringHelper" name="NewString" type="static" sig="([CIIZ)Ljava.lang.String;" /> <redirect class="java.lang.StringHelper" name="NewString" type="static" sig="([CIIZ)Ljava.lang.String;" />
</constructor> </constructor>
<constructor sig="(Ljava.lang.String;)V" modifiers="public"> <constructor sig="(Ljava.lang.String;)V" modifiers="public">
<redirect class="System.String" name="Copy" type="static" sig="(Ljava.lang.String;)Ljava.lang.String;" /> <redirect class="System.String, mscorlib" name="Copy" type="static" sig="(Ljava.lang.String;)Ljava.lang.String;" />
</constructor> </constructor>
<constructor sig="(Ljava.lang.StringBuffer;)V" modifiers="public"> <constructor sig="(Ljava.lang.StringBuffer;)V" modifiers="public">
<redirect class="java.lang.StringHelper" name="NewString" type="static" sig="(Ljava.lang.StringBuffer;)Ljava.lang.String;" /> <redirect class="java.lang.StringHelper" name="NewString" type="static" sig="(Ljava.lang.StringBuffer;)Ljava.lang.String;" />
@ -299,12 +298,12 @@
</method> </method>
<method name="copyValueOf" sig="([C)Ljava.lang.String;" modifiers="public static"> <method name="copyValueOf" sig="([C)Ljava.lang.String;" modifiers="public static">
<invokestatic> <invokestatic>
<newobj type="System.String" name=".ctor" sig="([C)V" /> <newobj type="System.String, mscorlib" name=".ctor" sig="([C)V" />
</invokestatic> </invokestatic>
</method> </method>
<method name="copyValueOf" sig="([CII)Ljava.lang.String;" modifiers="public static"> <method name="copyValueOf" sig="([CII)Ljava.lang.String;" modifiers="public static">
<invokestatic> <invokestatic>
<newobj type="System.String" name=".ctor" sig="([CII)V" /> <newobj type="System.String, mscorlib" name=".ctor" sig="([CII)V" />
</invokestatic> </invokestatic>
</method> </method>
<field name="CASE_INSENSITIVE_ORDER" sig="Ljava.util.Comparator;" modifiers="public static final"> <field name="CASE_INSENSITIVE_ORDER" sig="Ljava.util.Comparator;" modifiers="public static final">
@ -335,20 +334,20 @@
<implements class="java.io.Serializable" /> <implements class="java.io.Serializable" />
<constructor sig="()V" modifiers="public"> <constructor sig="()V" modifiers="public">
<invokespecial> <invokespecial>
<call type="ExceptionHelper" name="get_NullString" /> <call type="ExceptionHelper, ik.vm.net" name="get_NullString" />
<call type="System.Exception" name=".ctor" sig="(Ljava.lang.String;)V" /> <call type="System.Exception" name=".ctor" sig="(Ljava.lang.String;)V" />
</invokespecial> </invokespecial>
</constructor> </constructor>
<constructor sig="(Ljava.lang.String;)V" modifiers="public"> <constructor sig="(Ljava.lang.String;)V" modifiers="public">
<invokespecial> <invokespecial>
<call type="ExceptionHelper" name="FilterMessage" /> <call type="ExceptionHelper, ik.vm.net" name="FilterMessage" />
<call type="System.Exception" name=".ctor" sig="(Ljava.lang.String;)V" /> <call type="System.Exception" name=".ctor" sig="(Ljava.lang.String;)V" />
</invokespecial> </invokespecial>
</constructor> </constructor>
<constructor sig="(Ljava.lang.String;Ljava.lang.Throwable;)V" modifiers="public"> <constructor sig="(Ljava.lang.String;Ljava.lang.Throwable;)V" modifiers="public">
<invokespecial> <invokespecial>
<stloc name="x" type="System.Exception" /> <stloc name="x" type="System.Exception" />
<call type="ExceptionHelper" name="FilterMessage" /> <call type="ExceptionHelper, ik.vm.net" name="FilterMessage" />
<ldloc name="x" /> <ldloc name="x" />
<call type="System.Exception" name=".ctor" sig="(Ljava.lang.String;Ljava.lang.Throwable;)V" /> <call type="System.Exception" name=".ctor" sig="(Ljava.lang.String;Ljava.lang.Throwable;)V" />
</invokespecial> </invokespecial>
@ -357,47 +356,47 @@
<invokespecial> <invokespecial>
<stloc name="x" type="System.Exception" /> <stloc name="x" type="System.Exception" />
<ldloc name="x" /> <ldloc name="x" />
<call type="ExceptionHelper" name="GetMessageFromCause" /> <call type="ExceptionHelper, ik.vm.net" name="GetMessageFromCause" />
<ldloc name="x" /> <ldloc name="x" />
<call type="System.Exception" name=".ctor" sig="(Ljava.lang.String;Ljava.lang.Throwable;)V" /> <call type="System.Exception" name=".ctor" sig="(Ljava.lang.String;Ljava.lang.Throwable;)V" />
</invokespecial> </invokespecial>
</constructor> </constructor>
<method type="virtual" name="printStackTrace" sig="()V" modifiers="public"> <method type="virtual" name="printStackTrace" sig="()V" modifiers="public">
<redirect class="ExceptionHelper" sig="(Ljava.lang.Throwable;)V" type="static" /> <redirect class="ExceptionHelper, ik.vm.net" sig="(Ljava.lang.Throwable;)V" type="static" />
</method> </method>
<method type="virtual" name="printStackTrace" sig="(Ljava.io.PrintStream;)V" modifiers="public"> <method type="virtual" name="printStackTrace" sig="(Ljava.io.PrintStream;)V" modifiers="public">
<!-- NOTE both printStackTrace(Ljava.io.PrintStream;)V & printStackTrace(Ljava.io.PrintWriter;)V redirect <!-- NOTE both printStackTrace(Ljava.io.PrintStream;)V & printStackTrace(Ljava.io.PrintWriter;)V redirect
to the same method, this is not a bug --> to the same method, this is not a bug -->
<redirect class="ExceptionHelper" sig="(Ljava.lang.Throwable;Ljava.lang.Object;)V" type="static" /> <redirect class="ExceptionHelper, ik.vm.net" sig="(Ljava.lang.Throwable;Ljava.lang.Object;)V" type="static" />
</method> </method>
<method type="virtual" name="printStackTrace" sig="(Ljava.io.PrintWriter;)V" modifiers="public"> <method type="virtual" name="printStackTrace" sig="(Ljava.io.PrintWriter;)V" modifiers="public">
<!-- NOTE both printStackTrace(Ljava.io.PrintStream;)V & printStackTrace(Ljava.io.PrintWriter;)V redirect <!-- NOTE both printStackTrace(Ljava.io.PrintStream;)V & printStackTrace(Ljava.io.PrintWriter;)V redirect
to the same method, this is not a bug --> to the same method, this is not a bug -->
<redirect class="ExceptionHelper" sig="(Ljava.lang.Throwable;Ljava.lang.Object;)V" type="static" /> <redirect class="ExceptionHelper, ik.vm.net" sig="(Ljava.lang.Throwable;Ljava.lang.Object;)V" type="static" />
</method> </method>
<method type="virtual" name="getMessage" sig="()Ljava.lang.String;" modifiers="public"> <method type="virtual" name="getMessage" sig="()Ljava.lang.String;" modifiers="public">
<redirect class="ExceptionHelper" sig="(Ljava.lang.Throwable;)Ljava.lang.String;" type="static" /> <redirect class="ExceptionHelper, ik.vm.net" sig="(Ljava.lang.Throwable;)Ljava.lang.String;" type="static" />
</method> </method>
<method type="virtual" name="getLocalizedMessage" sig="()Ljava.lang.String;" modifiers="public"> <method type="virtual" name="getLocalizedMessage" sig="()Ljava.lang.String;" modifiers="public">
<redirect class="ExceptionHelper" sig="(Ljava.lang.Throwable;)Ljava.lang.String;" type="static" /> <redirect class="ExceptionHelper, ik.vm.net" sig="(Ljava.lang.Throwable;)Ljava.lang.String;" type="static" />
</method> </method>
<method type="virtual" name="fillInStackTrace" sig="()Ljava.lang.Throwable;" modifiers="public"> <method type="virtual" name="fillInStackTrace" sig="()Ljava.lang.Throwable;" modifiers="public">
<redirect class="ExceptionHelper" sig="(Ljava.lang.Throwable;)Ljava.lang.Throwable;" type="static" /> <redirect class="ExceptionHelper, ik.vm.net" sig="(Ljava.lang.Throwable;)Ljava.lang.Throwable;" type="static" />
</method> </method>
<method type="virtual" name="initCause" sig="(Ljava.lang.Throwable;)Ljava.lang.Throwable;" modifiers="public"> <method type="virtual" name="initCause" sig="(Ljava.lang.Throwable;)Ljava.lang.Throwable;" modifiers="public">
<redirect class="ExceptionHelper" sig="(Ljava.lang.Throwable;Ljava.lang.Throwable;)Ljava.lang.Throwable;" type="static" /> <redirect class="ExceptionHelper, ik.vm.net" sig="(Ljava.lang.Throwable;Ljava.lang.Throwable;)Ljava.lang.Throwable;" type="static" />
</method> </method>
<method type="virtual" name="getCause" sig="()Ljava.lang.Throwable;" modifiers="public"> <method type="virtual" name="getCause" sig="()Ljava.lang.Throwable;" modifiers="public">
<redirect class="ExceptionHelper" sig="(Ljava.lang.Throwable;)Ljava.lang.Throwable;" type="static" /> <redirect class="ExceptionHelper, ik.vm.net" sig="(Ljava.lang.Throwable;)Ljava.lang.Throwable;" type="static" />
</method> </method>
<method type="virtual" name="getStackTrace" sig="()[Ljava.lang.StackTraceElement;" modifiers="public"> <method type="virtual" name="getStackTrace" sig="()[Ljava.lang.StackTraceElement;" modifiers="public">
<redirect class="ExceptionHelper" sig="(Ljava.lang.Throwable;)[Ljava.lang.StackTraceElement;" type="static" /> <redirect class="ExceptionHelper, ik.vm.net" sig="(Ljava.lang.Throwable;)[Ljava.lang.StackTraceElement;" type="static" />
</method> </method>
<method type="virtual" name="setStackTrace" sig="([Ljava.lang.StackTraceElement;)V" modifiers="public"> <method type="virtual" name="setStackTrace" sig="([Ljava.lang.StackTraceElement;)V" modifiers="public">
<redirect class="ExceptionHelper" sig="(Ljava.lang.Throwable;[Ljava.lang.StackTraceElement;)V" type="static" /> <redirect class="ExceptionHelper, ik.vm.net" sig="(Ljava.lang.Throwable;[Ljava.lang.StackTraceElement;)V" type="static" />
</method> </method>
<method type="virtual" name="toString" sig="()Ljava.lang.String;" modifiers="public"> <method type="virtual" name="toString" sig="()Ljava.lang.String;" modifiers="public">
<redirect class="ExceptionHelper" sig="(Ljava.lang.Throwable;)Ljava.lang.String;" type="static" /> <redirect class="ExceptionHelper, ik.vm.net" sig="(Ljava.lang.Throwable;)Ljava.lang.String;" type="static" />
</method> </method>
</class> </class>
<class name="java.lang.Comparable" type="System.IComparable" modifiers="public interface"> <class name="java.lang.Comparable" type="System.IComparable" modifiers="public interface">
@ -449,5 +448,15 @@
<ret /> <ret />
</method> </method>
</class> </class>
<class name="ikvm.lang.ByteArrayHack">
<method name="cast" sig="([B)[Lcli.System.Byte;">
<ldarg_0 />
<ret />
</method>
<method name="cast" sig="([Lcli.System.Byte;)[B">
<ldarg_0 />
<ret />
</method>
</class>
</nativeMethods> </nativeMethods>
</root> </root>

Просмотреть файл

@ -20,7 +20,7 @@ obj11.Name = "notifyAll";
obj11.Sig = "()V"; obj11.Sig = "()V";
obj11.Modifiers = (MapXml.MapModifiers)17; obj11.Modifiers = (MapXml.MapModifiers)17;
MapXml.Redirect obj15 = new MapXml.Redirect(); MapXml.Redirect obj15 = new MapXml.Redirect();
obj15.Class = "System.Threading.Monitor"; obj15.Class = "System.Threading.Monitor, mscorlib";
obj15.Name = "PulseAll"; obj15.Name = "PulseAll";
obj15.Sig = "(Ljava.lang.Object;)V"; obj15.Sig = "(Ljava.lang.Object;)V";
obj15.Type = "static"; obj15.Type = "static";
@ -31,7 +31,7 @@ obj20.Name = "notify";
obj20.Sig = "()V"; obj20.Sig = "()V";
obj20.Modifiers = (MapXml.MapModifiers)17; obj20.Modifiers = (MapXml.MapModifiers)17;
MapXml.Redirect obj24 = new MapXml.Redirect(); MapXml.Redirect obj24 = new MapXml.Redirect();
obj24.Class = "System.Threading.Monitor"; obj24.Class = "System.Threading.Monitor, mscorlib";
obj24.Name = "Pulse"; obj24.Name = "Pulse";
obj24.Sig = "(Ljava.lang.Object;)V"; obj24.Sig = "(Ljava.lang.Object;)V";
obj24.Type = "static"; obj24.Type = "static";
@ -44,7 +44,7 @@ obj29.Modifiers = (MapXml.MapModifiers)17;
MapXml.InstructionList obj33 = new MapXml.InstructionList(); MapXml.InstructionList obj33 = new MapXml.InstructionList();
MapXml.Instruction[] obj34 = new MapXml.Instruction[2]; MapXml.Instruction[] obj34 = new MapXml.Instruction[2];
MapXml.Call obj35 = new MapXml.Call(); MapXml.Call obj35 = new MapXml.Call();
obj35.type = "System.Threading.Monitor"; obj35.type = "System.Threading.Monitor, mscorlib";
obj35.Name = "Wait"; obj35.Name = "Wait";
obj35.Sig = "(Ljava.lang.Object;)Z"; obj35.Sig = "(Ljava.lang.Object;)Z";
obj34[0] = obj35; obj34[0] = obj35;
@ -55,7 +55,7 @@ obj29.invokevirtual = obj33;
MapXml.InstructionList obj40 = new MapXml.InstructionList(); MapXml.InstructionList obj40 = new MapXml.InstructionList();
MapXml.Instruction[] obj41 = new MapXml.Instruction[2]; MapXml.Instruction[] obj41 = new MapXml.Instruction[2];
MapXml.Call obj42 = new MapXml.Call(); MapXml.Call obj42 = new MapXml.Call();
obj42.type = "System.Threading.Monitor"; obj42.type = "System.Threading.Monitor, mscorlib";
obj42.Name = "Wait"; obj42.Name = "Wait";
obj42.Sig = "(Ljava.lang.Object;)Z"; obj42.Sig = "(Ljava.lang.Object;)Z";
obj41[0] = obj42; obj41[0] = obj42;
@ -138,7 +138,7 @@ MapXml.Instruction[] obj99 = new MapXml.Instruction[7];
MapXml.Dup obj100 = new MapXml.Dup(); MapXml.Dup obj100 = new MapXml.Dup();
obj99[0] = obj100; obj99[0] = obj100;
MapXml.IsInst obj101 = new MapXml.IsInst(); MapXml.IsInst obj101 = new MapXml.IsInst();
obj101.type = "java.lang.Cloneable"; obj101.Class = "java.lang.Cloneable";
obj99[1] = obj101; obj99[1] = obj101;
MapXml.BrTrue obj103 = new MapXml.BrTrue(); MapXml.BrTrue obj103 = new MapXml.BrTrue();
obj103.Name = "ok"; obj103.Name = "ok";
@ -216,13 +216,13 @@ MapXml.Instruction[] obj152 = new MapXml.Instruction[9];
MapXml.Dup obj153 = new MapXml.Dup(); MapXml.Dup obj153 = new MapXml.Dup();
obj152[0] = obj153; obj152[0] = obj153;
MapXml.IsInst obj154 = new MapXml.IsInst(); MapXml.IsInst obj154 = new MapXml.IsInst();
obj154.type = "System.String"; obj154.type = "System.String, mscorlib";
obj152[1] = obj154; obj152[1] = obj154;
MapXml.BrFalse obj156 = new MapXml.BrFalse(); MapXml.BrFalse obj156 = new MapXml.BrFalse();
obj156.Name = "skip"; obj156.Name = "skip";
obj152[2] = obj156; obj152[2] = obj156;
MapXml.Castclass obj158 = new MapXml.Castclass(); MapXml.Castclass obj158 = new MapXml.Castclass();
obj158.type = "System.String"; obj158.type = "System.String, mscorlib";
obj152[3] = obj158; obj152[3] = obj158;
MapXml.Call obj160 = new MapXml.Call(); MapXml.Call obj160 = new MapXml.Call();
obj160.Class = "java.lang.StringHelper"; obj160.Class = "java.lang.StringHelper";
@ -268,7 +268,7 @@ obj2.Methods = obj10;
obj1[0] = obj2; obj1[0] = obj2;
MapXml.Class obj187 = new MapXml.Class(); MapXml.Class obj187 = new MapXml.Class();
obj187.Name = "java.lang.String"; obj187.Name = "java.lang.String";
obj187.Type = "System.String"; obj187.Type = "System.String, mscorlib";
obj187.Modifiers = (MapXml.MapModifiers)17; obj187.Modifiers = (MapXml.MapModifiers)17;
MapXml.Constructor[] obj191 = new MapXml.Constructor[12]; MapXml.Constructor[] obj191 = new MapXml.Constructor[12];
MapXml.Constructor obj192 = new MapXml.Constructor(); MapXml.Constructor obj192 = new MapXml.Constructor();
@ -280,7 +280,7 @@ MapXml.Ldstr obj197 = new MapXml.Ldstr();
obj197.Value = ""; obj197.Value = "";
obj196[0] = obj197; obj196[0] = obj197;
MapXml.Call obj199 = new MapXml.Call(); MapXml.Call obj199 = new MapXml.Call();
obj199.type = "System.String"; obj199.type = "System.String, mscorlib";
obj199.Name = "Copy"; obj199.Name = "Copy";
obj196[1] = obj199; obj196[1] = obj199;
obj195.invoke = obj196; obj195.invoke = obj196;
@ -308,7 +308,7 @@ MapXml.Constructor obj216 = new MapXml.Constructor();
obj216.Sig = "(Ljava.lang.String;)V"; obj216.Sig = "(Ljava.lang.String;)V";
obj216.Modifiers = (MapXml.MapModifiers)1; obj216.Modifiers = (MapXml.MapModifiers)1;
MapXml.Redirect obj219 = new MapXml.Redirect(); MapXml.Redirect obj219 = new MapXml.Redirect();
obj219.Class = "System.String"; obj219.Class = "System.String, mscorlib";
obj219.Name = "Copy"; obj219.Name = "Copy";
obj219.Sig = "(Ljava.lang.String;)Ljava.lang.String;"; obj219.Sig = "(Ljava.lang.String;)Ljava.lang.String;";
obj219.Type = "static"; obj219.Type = "static";
@ -808,7 +808,7 @@ obj606.Modifiers = (MapXml.MapModifiers)9;
MapXml.InstructionList obj610 = new MapXml.InstructionList(); MapXml.InstructionList obj610 = new MapXml.InstructionList();
MapXml.Instruction[] obj611 = new MapXml.Instruction[1]; MapXml.Instruction[] obj611 = new MapXml.Instruction[1];
MapXml.NewObj obj612 = new MapXml.NewObj(); MapXml.NewObj obj612 = new MapXml.NewObj();
obj612.type = "System.String"; obj612.type = "System.String, mscorlib";
obj612.Name = ".ctor"; obj612.Name = ".ctor";
obj612.Sig = "([C)V"; obj612.Sig = "([C)V";
obj611[0] = obj612; obj611[0] = obj612;
@ -822,7 +822,7 @@ obj616.Modifiers = (MapXml.MapModifiers)9;
MapXml.InstructionList obj620 = new MapXml.InstructionList(); MapXml.InstructionList obj620 = new MapXml.InstructionList();
MapXml.Instruction[] obj621 = new MapXml.Instruction[1]; MapXml.Instruction[] obj621 = new MapXml.Instruction[1];
MapXml.NewObj obj622 = new MapXml.NewObj(); MapXml.NewObj obj622 = new MapXml.NewObj();
obj622.type = "System.String"; obj622.type = "System.String, mscorlib";
obj622.Name = ".ctor"; obj622.Name = ".ctor";
obj622.Sig = "([CII)V"; obj622.Sig = "([CII)V";
obj621[0] = obj622; obj621[0] = obj622;
@ -908,7 +908,7 @@ obj682.Modifiers = (MapXml.MapModifiers)1;
MapXml.InstructionList obj685 = new MapXml.InstructionList(); MapXml.InstructionList obj685 = new MapXml.InstructionList();
MapXml.Instruction[] obj686 = new MapXml.Instruction[2]; MapXml.Instruction[] obj686 = new MapXml.Instruction[2];
MapXml.Call obj687 = new MapXml.Call(); MapXml.Call obj687 = new MapXml.Call();
obj687.type = "ExceptionHelper"; obj687.type = "ExceptionHelper, ik.vm.net";
obj687.Name = "get_NullString"; obj687.Name = "get_NullString";
obj686[0] = obj687; obj686[0] = obj687;
MapXml.Call obj690 = new MapXml.Call(); MapXml.Call obj690 = new MapXml.Call();
@ -925,7 +925,7 @@ obj694.Modifiers = (MapXml.MapModifiers)1;
MapXml.InstructionList obj697 = new MapXml.InstructionList(); MapXml.InstructionList obj697 = new MapXml.InstructionList();
MapXml.Instruction[] obj698 = new MapXml.Instruction[2]; MapXml.Instruction[] obj698 = new MapXml.Instruction[2];
MapXml.Call obj699 = new MapXml.Call(); MapXml.Call obj699 = new MapXml.Call();
obj699.type = "ExceptionHelper"; obj699.type = "ExceptionHelper, ik.vm.net";
obj699.Name = "FilterMessage"; obj699.Name = "FilterMessage";
obj698[0] = obj699; obj698[0] = obj699;
MapXml.Call obj702 = new MapXml.Call(); MapXml.Call obj702 = new MapXml.Call();
@ -946,7 +946,7 @@ obj711.Name = "x";
obj711.type = "System.Exception"; obj711.type = "System.Exception";
obj710[0] = obj711; obj710[0] = obj711;
MapXml.Call obj714 = new MapXml.Call(); MapXml.Call obj714 = new MapXml.Call();
obj714.type = "ExceptionHelper"; obj714.type = "ExceptionHelper, ik.vm.net";
obj714.Name = "FilterMessage"; obj714.Name = "FilterMessage";
obj710[1] = obj714; obj710[1] = obj714;
MapXml.LdLoc obj717 = new MapXml.LdLoc(); MapXml.LdLoc obj717 = new MapXml.LdLoc();
@ -973,7 +973,7 @@ MapXml.LdLoc obj731 = new MapXml.LdLoc();
obj731.Name = "x"; obj731.Name = "x";
obj727[1] = obj731; obj727[1] = obj731;
MapXml.Call obj733 = new MapXml.Call(); MapXml.Call obj733 = new MapXml.Call();
obj733.type = "ExceptionHelper"; obj733.type = "ExceptionHelper, ik.vm.net";
obj733.Name = "GetMessageFromCause"; obj733.Name = "GetMessageFromCause";
obj727[2] = obj733; obj727[2] = obj733;
MapXml.LdLoc obj736 = new MapXml.LdLoc(); MapXml.LdLoc obj736 = new MapXml.LdLoc();
@ -995,7 +995,7 @@ obj743.Sig = "()V";
obj743.Modifiers = (MapXml.MapModifiers)1; obj743.Modifiers = (MapXml.MapModifiers)1;
obj743.Type = "virtual"; obj743.Type = "virtual";
MapXml.Redirect obj748 = new MapXml.Redirect(); MapXml.Redirect obj748 = new MapXml.Redirect();
obj748.Class = "ExceptionHelper"; obj748.Class = "ExceptionHelper, ik.vm.net";
obj748.Sig = "(Ljava.lang.Throwable;)V"; obj748.Sig = "(Ljava.lang.Throwable;)V";
obj748.Type = "static"; obj748.Type = "static";
obj743.redirect = obj748; obj743.redirect = obj748;
@ -1006,7 +1006,7 @@ obj752.Sig = "(Ljava.io.PrintStream;)V";
obj752.Modifiers = (MapXml.MapModifiers)1; obj752.Modifiers = (MapXml.MapModifiers)1;
obj752.Type = "virtual"; obj752.Type = "virtual";
MapXml.Redirect obj757 = new MapXml.Redirect(); MapXml.Redirect obj757 = new MapXml.Redirect();
obj757.Class = "ExceptionHelper"; obj757.Class = "ExceptionHelper, ik.vm.net";
obj757.Sig = "(Ljava.lang.Throwable;Ljava.lang.Object;)V"; obj757.Sig = "(Ljava.lang.Throwable;Ljava.lang.Object;)V";
obj757.Type = "static"; obj757.Type = "static";
obj752.redirect = obj757; obj752.redirect = obj757;
@ -1017,7 +1017,7 @@ obj761.Sig = "(Ljava.io.PrintWriter;)V";
obj761.Modifiers = (MapXml.MapModifiers)1; obj761.Modifiers = (MapXml.MapModifiers)1;
obj761.Type = "virtual"; obj761.Type = "virtual";
MapXml.Redirect obj766 = new MapXml.Redirect(); MapXml.Redirect obj766 = new MapXml.Redirect();
obj766.Class = "ExceptionHelper"; obj766.Class = "ExceptionHelper, ik.vm.net";
obj766.Sig = "(Ljava.lang.Throwable;Ljava.lang.Object;)V"; obj766.Sig = "(Ljava.lang.Throwable;Ljava.lang.Object;)V";
obj766.Type = "static"; obj766.Type = "static";
obj761.redirect = obj766; obj761.redirect = obj766;
@ -1028,7 +1028,7 @@ obj770.Sig = "()Ljava.lang.String;";
obj770.Modifiers = (MapXml.MapModifiers)1; obj770.Modifiers = (MapXml.MapModifiers)1;
obj770.Type = "virtual"; obj770.Type = "virtual";
MapXml.Redirect obj775 = new MapXml.Redirect(); MapXml.Redirect obj775 = new MapXml.Redirect();
obj775.Class = "ExceptionHelper"; obj775.Class = "ExceptionHelper, ik.vm.net";
obj775.Sig = "(Ljava.lang.Throwable;)Ljava.lang.String;"; obj775.Sig = "(Ljava.lang.Throwable;)Ljava.lang.String;";
obj775.Type = "static"; obj775.Type = "static";
obj770.redirect = obj775; obj770.redirect = obj775;
@ -1039,7 +1039,7 @@ obj779.Sig = "()Ljava.lang.String;";
obj779.Modifiers = (MapXml.MapModifiers)1; obj779.Modifiers = (MapXml.MapModifiers)1;
obj779.Type = "virtual"; obj779.Type = "virtual";
MapXml.Redirect obj784 = new MapXml.Redirect(); MapXml.Redirect obj784 = new MapXml.Redirect();
obj784.Class = "ExceptionHelper"; obj784.Class = "ExceptionHelper, ik.vm.net";
obj784.Sig = "(Ljava.lang.Throwable;)Ljava.lang.String;"; obj784.Sig = "(Ljava.lang.Throwable;)Ljava.lang.String;";
obj784.Type = "static"; obj784.Type = "static";
obj779.redirect = obj784; obj779.redirect = obj784;
@ -1050,7 +1050,7 @@ obj788.Sig = "()Ljava.lang.Throwable;";
obj788.Modifiers = (MapXml.MapModifiers)1; obj788.Modifiers = (MapXml.MapModifiers)1;
obj788.Type = "virtual"; obj788.Type = "virtual";
MapXml.Redirect obj793 = new MapXml.Redirect(); MapXml.Redirect obj793 = new MapXml.Redirect();
obj793.Class = "ExceptionHelper"; obj793.Class = "ExceptionHelper, ik.vm.net";
obj793.Sig = "(Ljava.lang.Throwable;)Ljava.lang.Throwable;"; obj793.Sig = "(Ljava.lang.Throwable;)Ljava.lang.Throwable;";
obj793.Type = "static"; obj793.Type = "static";
obj788.redirect = obj793; obj788.redirect = obj793;
@ -1061,7 +1061,7 @@ obj797.Sig = "(Ljava.lang.Throwable;)Ljava.lang.Throwable;";
obj797.Modifiers = (MapXml.MapModifiers)1; obj797.Modifiers = (MapXml.MapModifiers)1;
obj797.Type = "virtual"; obj797.Type = "virtual";
MapXml.Redirect obj802 = new MapXml.Redirect(); MapXml.Redirect obj802 = new MapXml.Redirect();
obj802.Class = "ExceptionHelper"; obj802.Class = "ExceptionHelper, ik.vm.net";
obj802.Sig = "(Ljava.lang.Throwable;Ljava.lang.Throwable;)Ljava.lang.Throwable;"; obj802.Sig = "(Ljava.lang.Throwable;Ljava.lang.Throwable;)Ljava.lang.Throwable;";
obj802.Type = "static"; obj802.Type = "static";
obj797.redirect = obj802; obj797.redirect = obj802;
@ -1072,7 +1072,7 @@ obj806.Sig = "()Ljava.lang.Throwable;";
obj806.Modifiers = (MapXml.MapModifiers)1; obj806.Modifiers = (MapXml.MapModifiers)1;
obj806.Type = "virtual"; obj806.Type = "virtual";
MapXml.Redirect obj811 = new MapXml.Redirect(); MapXml.Redirect obj811 = new MapXml.Redirect();
obj811.Class = "ExceptionHelper"; obj811.Class = "ExceptionHelper, ik.vm.net";
obj811.Sig = "(Ljava.lang.Throwable;)Ljava.lang.Throwable;"; obj811.Sig = "(Ljava.lang.Throwable;)Ljava.lang.Throwable;";
obj811.Type = "static"; obj811.Type = "static";
obj806.redirect = obj811; obj806.redirect = obj811;
@ -1083,7 +1083,7 @@ obj815.Sig = "()[Ljava.lang.StackTraceElement;";
obj815.Modifiers = (MapXml.MapModifiers)1; obj815.Modifiers = (MapXml.MapModifiers)1;
obj815.Type = "virtual"; obj815.Type = "virtual";
MapXml.Redirect obj820 = new MapXml.Redirect(); MapXml.Redirect obj820 = new MapXml.Redirect();
obj820.Class = "ExceptionHelper"; obj820.Class = "ExceptionHelper, ik.vm.net";
obj820.Sig = "(Ljava.lang.Throwable;)[Ljava.lang.StackTraceElement;"; obj820.Sig = "(Ljava.lang.Throwable;)[Ljava.lang.StackTraceElement;";
obj820.Type = "static"; obj820.Type = "static";
obj815.redirect = obj820; obj815.redirect = obj820;
@ -1094,7 +1094,7 @@ obj824.Sig = "([Ljava.lang.StackTraceElement;)V";
obj824.Modifiers = (MapXml.MapModifiers)1; obj824.Modifiers = (MapXml.MapModifiers)1;
obj824.Type = "virtual"; obj824.Type = "virtual";
MapXml.Redirect obj829 = new MapXml.Redirect(); MapXml.Redirect obj829 = new MapXml.Redirect();
obj829.Class = "ExceptionHelper"; obj829.Class = "ExceptionHelper, ik.vm.net";
obj829.Sig = "(Ljava.lang.Throwable;[Ljava.lang.StackTraceElement;)V"; obj829.Sig = "(Ljava.lang.Throwable;[Ljava.lang.StackTraceElement;)V";
obj829.Type = "static"; obj829.Type = "static";
obj824.redirect = obj829; obj824.redirect = obj829;
@ -1105,7 +1105,7 @@ obj833.Sig = "()Ljava.lang.String;";
obj833.Modifiers = (MapXml.MapModifiers)1; obj833.Modifiers = (MapXml.MapModifiers)1;
obj833.Type = "virtual"; obj833.Type = "virtual";
MapXml.Redirect obj838 = new MapXml.Redirect(); MapXml.Redirect obj838 = new MapXml.Redirect();
obj838.Class = "ExceptionHelper"; obj838.Class = "ExceptionHelper, ik.vm.net";
obj838.Sig = "(Ljava.lang.Throwable;)Ljava.lang.String;"; obj838.Sig = "(Ljava.lang.Throwable;)Ljava.lang.String;";
obj838.Type = "static"; obj838.Type = "static";
obj833.redirect = obj838; obj833.redirect = obj838;
@ -1189,7 +1189,7 @@ obj860[7] = obj893;
obj856.Methods = obj860; obj856.Methods = obj860;
obj1[4] = obj856; obj1[4] = obj856;
obj0.remappings = obj1; obj0.remappings = obj1;
MapXml.Class[] obj899 = new MapXml.Class[3]; MapXml.Class[] obj899 = new MapXml.Class[4];
MapXml.Class obj900 = new MapXml.Class(); MapXml.Class obj900 = new MapXml.Class();
obj900.Name = "java.lang.Runtime"; obj900.Name = "java.lang.Runtime";
obj900.Modifiers = (MapXml.MapModifiers)0; obj900.Modifiers = (MapXml.MapModifiers)0;
@ -1260,6 +1260,34 @@ obj936.invoke = obj940;
obj935[0] = obj936; obj935[0] = obj936;
obj932.Methods = obj935; obj932.Methods = obj935;
obj899[2] = obj932; obj899[2] = obj932;
MapXml.Class obj946 = new MapXml.Class();
obj946.Name = "ikvm.lang.ByteArrayHack";
obj946.Modifiers = (MapXml.MapModifiers)0;
MapXml.Method[] obj949 = new MapXml.Method[2];
MapXml.Method obj950 = new MapXml.Method();
obj950.Name = "cast";
obj950.Sig = "([B)[Lcli.System.Byte;";
obj950.Modifiers = (MapXml.MapModifiers)0;
MapXml.Instruction[] obj954 = new MapXml.Instruction[2];
MapXml.LdArg_0 obj955 = new MapXml.LdArg_0();
obj954[0] = obj955;
MapXml.Ret obj956 = new MapXml.Ret();
obj954[1] = obj956;
obj950.invoke = obj954;
obj949[0] = obj950;
MapXml.Method obj957 = new MapXml.Method();
obj957.Name = "cast";
obj957.Sig = "([Lcli.System.Byte;)[B";
obj957.Modifiers = (MapXml.MapModifiers)0;
MapXml.Instruction[] obj961 = new MapXml.Instruction[2];
MapXml.LdArg_0 obj962 = new MapXml.LdArg_0();
obj961[0] = obj962;
MapXml.Ret obj963 = new MapXml.Ret();
obj961[1] = obj963;
obj957.invoke = obj961;
obj949[1] = obj957;
obj946.Methods = obj949;
obj899[3] = obj946;
obj0.nativeMethods = obj899; obj0.nativeMethods = obj899;
return obj0; return obj0;
} }

Просмотреть файл

@ -58,7 +58,7 @@ namespace MapXml
{ {
Debug.Assert(Class == null && type != null); Debug.Assert(Class == null && type != null);
Type[] argTypes = ClassLoaderWrapper.GetBootstrapClassLoader().ArgTypeListFromSig(Sig); Type[] argTypes = ClassLoaderWrapper.GetBootstrapClassLoader().ArgTypeListFromSig(Sig);
emitter = CodeEmitter.Create(opcode, ClassLoaderWrapper.GetType(type).GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, CallingConventions.Standard, argTypes, null)); emitter = CodeEmitter.Create(opcode, Type.GetType(type, true).GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, CallingConventions.Standard, argTypes, null));
} }
else else
{ {
@ -77,11 +77,11 @@ namespace MapXml
if(Sig != null) if(Sig != null)
{ {
Type[] argTypes = ClassLoaderWrapper.GetBootstrapClassLoader().ArgTypeListFromSig(Sig); Type[] argTypes = ClassLoaderWrapper.GetBootstrapClassLoader().ArgTypeListFromSig(Sig);
emitter = CodeEmitter.Create(opcode, ClassLoaderWrapper.GetType(type).GetMethod(Name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static, null, argTypes, null)); emitter = CodeEmitter.Create(opcode, Type.GetType(type, true).GetMethod(Name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static, null, argTypes, null));
} }
else else
{ {
emitter = CodeEmitter.Create(opcode, ClassLoaderWrapper.GetType(type).GetMethod(Name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)); emitter = CodeEmitter.Create(opcode, Type.GetType(type, true).GetMethod(Name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static));
} }
} }
} }
@ -168,7 +168,7 @@ namespace MapXml
} }
else else
{ {
typeType = ClassLoaderWrapper.GetType(type); typeType = Type.GetType(type, true);
} }
} }
ilgen.Emit(opcode, typeType != null ? typeType : typeWrapper.Type); ilgen.Emit(opcode, typeType != null ? typeType : typeWrapper.Type);
@ -296,7 +296,7 @@ namespace MapXml
Debug.Assert(Class == null ^ type == null); Debug.Assert(Class == null ^ type == null);
if(type != null) if(type != null)
{ {
typeType = ClassLoaderWrapper.GetType(type); typeType = Type.GetType(type, true);
} }
else else
{ {

Просмотреть файл

@ -29,6 +29,7 @@ using System.Collections;
using System.Xml; using System.Xml;
using System.Diagnostics; using System.Diagnostics;
using OpenSystem.Java; using OpenSystem.Java;
using System.Text.RegularExpressions;
public class JVM public class JVM
{ {
@ -145,7 +146,6 @@ public class JVM
private string assembly; private string assembly;
private string path; private string path;
private AssemblyBuilder assemblyBuilder; private AssemblyBuilder assemblyBuilder;
private ModuleBuilder moduleBuilder;
internal CompilerClassLoader(string path, string assembly, Hashtable classes) internal CompilerClassLoader(string path, string assembly, Hashtable classes)
: base(null) : base(null)
@ -157,26 +157,23 @@ public class JVM
protected override ModuleBuilder CreateModuleBuilder() protected override ModuleBuilder CreateModuleBuilder()
{ {
if(moduleBuilder == null) AssemblyName name = new AssemblyName();
name.Name = assembly;
assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.RunAndSave);
CustomAttributeBuilder ikvmAssemblyAttr = new CustomAttributeBuilder(typeof(JavaAssemblyAttribute).GetConstructor(Type.EmptyTypes), new object[0]);
assemblyBuilder.SetCustomAttribute(ikvmAssemblyAttr);
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(path, JVM.Debug);
if(JVM.Debug)
{ {
AssemblyName name = new AssemblyName(); CustomAttributeBuilder debugAttr = new CustomAttributeBuilder(typeof(DebuggableAttribute).GetConstructor(new Type[] { typeof(bool), typeof(bool) }), new object[] { true, true });
name.Name = assembly; moduleBuilder.SetCustomAttribute(debugAttr);
assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.RunAndSave);
CustomAttributeBuilder ikvmAssemblyAttr = new CustomAttributeBuilder(typeof(JavaAssemblyAttribute).GetConstructor(Type.EmptyTypes), new object[0]);
assemblyBuilder.SetCustomAttribute(ikvmAssemblyAttr);
moduleBuilder = assemblyBuilder.DefineDynamicModule(path, JVM.Debug);
if(JVM.Debug)
{
CustomAttributeBuilder debugAttr = new CustomAttributeBuilder(typeof(DebuggableAttribute).GetConstructor(new Type[] { typeof(bool), typeof(bool) }), new object[] { true, true });
moduleBuilder.SetCustomAttribute(debugAttr);
}
} }
return moduleBuilder; return moduleBuilder;
} }
internal override TypeWrapper GetBootstrapType(string name) internal override TypeWrapper GetTypeWrapperCompilerHook(string name)
{ {
TypeWrapper type = base.GetBootstrapType(name); TypeWrapper type = base.GetTypeWrapperCompilerHook(name);
if(type == null) if(type == null)
{ {
ClassFile f = (ClassFile)classes[name]; ClassFile f = (ClassFile)classes[name];
@ -201,11 +198,7 @@ public class JVM
internal void AddResources(Hashtable resources) internal void AddResources(Hashtable resources)
{ {
if(moduleBuilder == null) ModuleBuilder moduleBuilder = this.ModuleBuilder;
{
// this happens if the module contains no clases
CreateModuleBuilder();
}
foreach(DictionaryEntry d in resources) foreach(DictionaryEntry d in resources)
{ {
byte[] buf = (byte[])d.Value; byte[] buf = (byte[])d.Value;
@ -218,7 +211,7 @@ public class JVM
} }
} }
public static void Compile(string path, string assembly, string mainClass, PEFileKinds target, byte[][] classes, string[] references, bool nojni, Hashtable resources) public static void Compile(string path, string assembly, string mainClass, PEFileKinds target, byte[][] classes, string[] references, bool nojni, Hashtable resources, string[] classesToExclude)
{ {
isStaticCompiler = true; isStaticCompiler = true;
noJniStubs = nojni; noJniStubs = nojni;
@ -232,12 +225,29 @@ public class JVM
{ {
ClassFile f = new ClassFile(classes[i], 0, classes[i].Length, null); ClassFile f = new ClassFile(classes[i], 0, classes[i].Length, null);
string name = f.Name; string name = f.Name;
bool excluded = false;
for(int j = 0; j < classesToExclude.Length; j++)
{
if(Regex.IsMatch(name, classesToExclude[j]))
{
excluded = true;
//Console.WriteLine("Excluding: {0} on rule {1}", name, (String)classesToExclude[j]);
break;
}
}
// if (!excluded)
// Console.WriteLine("Adding: {0}", name);
// else
// Console.WriteLine("Not Adding: {0}", name);
if(h.ContainsKey(name)) if(h.ContainsKey(name))
{ {
Console.Error.WriteLine("Duplicate class name: {0}", name); Console.Error.WriteLine("Duplicate class name: {0}", name);
return; return;
} }
h[name] = f; if(!excluded)
{
h[name] = f;
}
} }
// make sure all inner classes have a reference to their outer class // make sure all inner classes have a reference to their outer class
@ -246,7 +256,7 @@ public class JVM
foreach(ClassFile classFile in h.Values) foreach(ClassFile classFile in h.Values)
{ {
// don't handle inner classes for NetExp types // don't handle inner classes for NetExp types
if(classFile.NetExpTypeAttribute == null) if(classFile.NetExpAssemblyAttribute == null)
{ {
ClassFile.InnerClass[] innerClasses = classFile.InnerClasses; ClassFile.InnerClass[] innerClasses = classFile.InnerClasses;
if(innerClasses != null) if(innerClasses != null)

Двоичные данные
classpath/System.Xml.jar

Двоичный файл не отображается.

Двоичные данные
classpath/System.jar

Двоичный файл не отображается.

Просмотреть файл

@ -24,8 +24,8 @@
package gnu.java.net.protocol.ikvmres; package gnu.java.net.protocol.ikvmres;
import system.io.*; import cli.System.IO.*;
import system.reflection.*; import cli.System.Reflection.*;
import java.net.*; import java.net.*;
import java.io.*; import java.io.*;
import java.io.IOException; import java.io.IOException;
@ -56,8 +56,8 @@ class IkvmresURLConnection extends URLConnection
{ {
throw new IOException("resource " + resource + " not found in assembly " + assembly); throw new IOException("resource " + resource + " not found in assembly " + assembly);
} }
byte[] b = new byte[system.runtime.interopservices.Marshal.SizeOf(fi.get_FieldType())]; byte[] b = new byte[cli.System.Runtime.InteropServices.Marshal.SizeOf(fi.get_FieldType())];
system.runtime.compilerservices.RuntimeHelpers.InitializeArray((system.Array)(Object)b, fi.get_FieldHandle()); cli.System.Runtime.CompilerServices.RuntimeHelpers.InitializeArray((cli.System.Array)(Object)b, fi.get_FieldHandle());
inputStream = new ByteArrayInputStream(b); inputStream = new ByteArrayInputStream(b);
connected = true; connected = true;
} }

Просмотреть файл

@ -0,0 +1,9 @@
package ikvm.lang;
public final class ByteArrayHack
{
private ByteArrayHack() {}
public static native cli.System.Byte[] cast(byte[] b);
public static native byte[] cast(cli.System.Byte[] b);
}

Просмотреть файл

@ -26,14 +26,14 @@ package ikvm.lang;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.File; import java.io.File;
import system.text.StringBuilder; import cli.System.Text.StringBuilder;
import system.diagnostics.ProcessStartInfo; import cli.System.Diagnostics.ProcessStartInfo;
public class DotNetProcess extends Process public class DotNetProcess extends Process
{ {
private system.diagnostics.Process proc; private cli.System.Diagnostics.Process proc;
private DotNetProcess(system.diagnostics.Process proc) private DotNetProcess(cli.System.Diagnostics.Process proc)
{ {
this.proc = proc; this.proc = proc;
} }
@ -72,10 +72,10 @@ public class DotNetProcess extends Process
{ {
try try
{ {
if(false) throw new system.InvalidOperationException(); if(false) throw new cli.System.InvalidOperationException();
proc.Kill(); proc.Kill();
} }
catch(system.InvalidOperationException x) catch(cli.System.InvalidOperationException x)
{ {
} }
} }
@ -119,6 +119,6 @@ public class DotNetProcess extends Process
} }
} }
// TODO map the exceptions // TODO map the exceptions
return new DotNetProcess(system.diagnostics.Process.Start(si)); return new DotNetProcess(cli.System.Diagnostics.Process.Start(si));
} }
} }

Просмотреть файл

@ -38,8 +38,9 @@ exception statement from your version. */
package java.io; package java.io;
import system.Console; import cli.System.Console;
import system.io.*; import cli.System.IO.*;
import ikvm.lang.ByteArrayHack;
/** /**
* This class represents an opaque file handle as a Java class. It should * This class represents an opaque file handle as a Java class. It should
@ -91,12 +92,12 @@ public final class FileDescriptor
} }
try try
{ {
if(false) throw new system.io.IOException(); if(false) throw new cli.System.IO.IOException();
stream.Flush(); stream.Flush();
} }
catch(system.io.IOException x) catch(cli.System.IO.IOException x)
{ {
throw new SyncFailedException(x.get_Message()); throw new SyncFailedException(x.getMessage());
} }
} }
@ -115,11 +116,11 @@ public final class FileDescriptor
try try
{ {
stream.Close(); stream.Close();
if(false) throw new system.io.IOException(); if(false) throw new cli.System.IO.IOException();
} }
catch(system.io.IOException x) catch(cli.System.IO.IOException x)
{ {
throw new IOException(x.get_Message()); throw new IOException(x.getMessage());
} }
} }
stream = null; stream = null;
@ -171,23 +172,23 @@ public final class FileDescriptor
default: default:
throw new IllegalArgumentException("Invalid mode value: " + mode); throw new IllegalArgumentException("Invalid mode value: " + mode);
} }
if(false) throw new system.io.IOException(); if(false) throw new cli.System.IO.IOException();
if(false) throw new system.security.SecurityException(); if(false) throw new cli.System.Security.SecurityException();
if(false) throw new system.UnauthorizedAccessException(); if(false) throw new cli.System.UnauthorizedAccessException();
stream = system.io.File.Open(demanglePath(path), fileMode, fileAccess, FileShare.ReadWrite); stream = cli.System.IO.File.Open(demanglePath(path), FileMode.wrap(fileMode), FileAccess.wrap(fileAccess), FileShare.wrap(FileShare.ReadWrite));
} }
catch(system.security.SecurityException x1) catch(cli.System.Security.SecurityException x1)
{ {
throw new SecurityException(x1.get_Message()); throw new SecurityException(x1.getMessage());
} }
catch(system.io.IOException x2) catch(cli.System.IO.IOException x2)
{ {
throw new FileNotFoundException(x2.get_Message()); throw new FileNotFoundException(x2.getMessage());
} }
catch(system.UnauthorizedAccessException x3) catch(cli.System.UnauthorizedAccessException x3)
{ {
// this is caused by "name" being a directory instead of a file // this is caused by "name" being a directory instead of a file
throw new FileNotFoundException(x3.get_Message()); throw new FileNotFoundException(x3.getMessage());
} }
// TODO map al the other exceptions as well... // TODO map al the other exceptions as well...
} }
@ -199,12 +200,12 @@ public final class FileDescriptor
try try
{ {
if(false) throw new system.io.IOException(); if(false) throw new cli.System.IO.IOException();
return stream.get_Position(); return stream.get_Position();
} }
catch(system.io.IOException x) catch(cli.System.IO.IOException x)
{ {
throw new IOException(x.get_Message()); throw new IOException(x.getMessage());
} }
// TODO map al the other exceptions as well... // TODO map al the other exceptions as well...
} }
@ -216,12 +217,12 @@ public final class FileDescriptor
try try
{ {
if(false) throw new system.io.IOException(); if(false) throw new cli.System.IO.IOException();
return stream.get_Length(); return stream.get_Length();
} }
catch(system.io.IOException x) catch(cli.System.IO.IOException x)
{ {
throw new IOException(x.get_Message()); throw new IOException(x.getMessage());
} }
// TODO map al the other exceptions as well... // TODO map al the other exceptions as well...
} }
@ -237,12 +238,12 @@ public final class FileDescriptor
try try
{ {
if(false) throw new system.io.IOException(); if(false) throw new cli.System.IO.IOException();
stream.SetLength(len); stream.SetLength(len);
} }
catch(system.io.IOException x) catch(cli.System.IO.IOException x)
{ {
throw new IOException(x.get_Message()); throw new IOException(x.getMessage());
} }
// TODO map al the other exceptions as well... // TODO map al the other exceptions as well...
} }
@ -257,17 +258,17 @@ public final class FileDescriptor
try try
{ {
if(false) throw new system.io.IOException(); if(false) throw new cli.System.IO.IOException();
long newpos = stream.Seek(offset, whence); long newpos = stream.Seek(offset, SeekOrigin.wrap(whence));
if(stopAtEof && newpos > stream.get_Length()) if(stopAtEof && newpos > stream.get_Length())
{ {
newpos = stream.Seek(0, SeekOrigin.End); newpos = stream.Seek(0, SeekOrigin.wrap(SeekOrigin.End));
} }
return newpos; return newpos;
} }
catch(system.io.IOException x) catch(cli.System.IO.IOException x)
{ {
throw new IOException(x.get_Message()); throw new IOException(x.getMessage());
} }
// TODO map al the other exceptions as well... // TODO map al the other exceptions as well...
} }
@ -279,12 +280,12 @@ public final class FileDescriptor
try try
{ {
if(false) throw new system.io.IOException(); if(false) throw new cli.System.IO.IOException();
return stream.ReadByte(); return stream.ReadByte();
} }
catch(system.io.IOException x) catch(cli.System.IO.IOException x)
{ {
throw new IOException(x.get_Message()); throw new IOException(x.getMessage());
} }
// TODO map al the other exceptions as well... // TODO map al the other exceptions as well...
} }
@ -305,37 +306,25 @@ public final class FileDescriptor
try try
{ {
if(false) throw new system.io.IOException(); if(false) throw new cli.System.IO.IOException();
int count = stream.Read(buf, offset, len); int count = stream.Read(ByteArrayHack.cast(buf), offset, len);
if(count == 0) if(count == 0)
{ {
count = -1; count = -1;
} }
return count; return count;
} }
catch(system.io.IOException x) catch(cli.System.IO.IOException x)
{ {
throw new IOException(x.get_Message()); throw new IOException(x.getMessage());
} }
// TODO map al the other exceptions as well... // TODO map al the other exceptions as well...
} }
synchronized void write(int b) throws IOException synchronized void write(int b) throws IOException
{ {
if(stream == null) // HACK we can't call WriteByte because it takes a cli.System.Byte
{ write(new byte[] { (byte)b }, 0, 1);
throw new IOException("Invalid FileDescriptor");
}
try
{
if(false) throw new system.io.IOException();
stream.WriteByte((byte)b);
}
catch(system.io.IOException x)
{
throw new IOException(x.get_Message());
}
// TODO map al the other exceptions as well...
} }
synchronized void write(byte[] buf, int offset, int len) throws IOException synchronized void write(byte[] buf, int offset, int len) throws IOException
@ -354,12 +343,12 @@ public final class FileDescriptor
try try
{ {
if(false) throw new system.io.IOException(); if(false) throw new cli.System.IO.IOException();
stream.Write(buf, offset, len); stream.Write(ByteArrayHack.cast(buf), offset, len);
} }
catch(system.io.IOException x) catch(cli.System.IO.IOException x)
{ {
throw new IOException(x.get_Message()); throw new IOException(x.getMessage());
} }
// TODO map al the other exceptions as well... // TODO map al the other exceptions as well...
} }
@ -371,17 +360,17 @@ public final class FileDescriptor
try try
{ {
if(false) throw new system.io.IOException(); if(false) throw new cli.System.IO.IOException();
if(false) throw new system.NotSupportedException(); if(false) throw new cli.System.NotSupportedException();
if(stream.get_CanSeek()) if(stream.get_CanSeek())
return (int)Math.min(Integer.MAX_VALUE, Math.max(0, stream.get_Length() - stream.get_Position())); return (int)Math.min(Integer.MAX_VALUE, Math.max(0, stream.get_Length() - stream.get_Position()));
return 0; return 0;
} }
catch(system.io.IOException x) catch(cli.System.IO.IOException x)
{ {
throw new IOException(x.get_Message()); throw new IOException(x.getMessage());
} }
catch(system.NotSupportedException x1) catch(cli.System.NotSupportedException x1)
{ {
// this means we have a broken Stream, because if CanSeek returns true, it must // this means we have a broken Stream, because if CanSeek returns true, it must
// support Length and Position // support Length and Position

Просмотреть файл

@ -44,12 +44,12 @@ public class ObjectHelper
} }
if(timeout == 0 && nanos == 0) if(timeout == 0 && nanos == 0)
{ {
system.threading.Monitor.Wait(o); cli.System.Threading.Monitor.Wait(o);
} }
else else
{ {
// TODO handle time span calculation overflow // TODO handle time span calculation overflow
system.threading.Monitor.Wait(o, new system.TimeSpan(timeout * 10000 + (nanos + 99) / 100)); cli.System.Threading.Monitor.Wait(o, new cli.System.TimeSpan(timeout * 10000 + (nanos + 99) / 100));
} }
} }

Просмотреть файл

@ -293,25 +293,24 @@ public final class StringHelper
public static String substring(String s, int off, int end) public static String substring(String s, int off, int end)
{ {
return ((system.String)(Object)s).Substring(off, end - off); return cli.System.String.Substring(s, off, end - off);
} }
public static boolean startsWith(String si, String prefix, int toffset) public static boolean startsWith(String s, String prefix, int toffset)
{ {
if(toffset < 0) if(toffset < 0)
{ {
return false; return false;
} }
system.String s = (system.String)(Object)si; s = cli.System.String.Substring(s, Math.min(s.length(), toffset));
s = (system.String)(Object)s.Substring(Math.min(s.get_Length(), toffset)); return cli.System.String.StartsWith(s, prefix);
return s.StartsWith(prefix);
} }
public static char charAt(String s, int index) public static char charAt(String s, int index)
{ {
try try
{ {
return ((system.String)(Object)s).get_Chars(index); return cli.System.String.get_Chars(s, index);
} }
// NOTE the System.IndexOutOfRangeException thrown by get_Chars, is translated by our // NOTE the System.IndexOutOfRangeException thrown by get_Chars, is translated by our
// exception handling code to an ArrayIndexOutOfBoundsException, so we catch that. // exception handling code to an ArrayIndexOutOfBoundsException, so we catch that.
@ -323,7 +322,7 @@ public final class StringHelper
public static void getChars(String s, int srcBegin, int srcEnd, char[] dst, int dstBegin) public static void getChars(String s, int srcBegin, int srcEnd, char[] dst, int dstBegin)
{ {
((system.String)(Object)s).CopyTo(srcBegin, dst, dstBegin, srcEnd - srcBegin); cli.System.String.CopyTo(s, srcBegin, dst, dstBegin, srcEnd - srcBegin);
} }
// this exposes the package accessible "count" field (for use by StringBuffer) // this exposes the package accessible "count" field (for use by StringBuffer)
@ -344,31 +343,28 @@ public final class StringHelper
return 0; return 0;
} }
public static int indexOf(String si, char ch, int fromIndex) public static int indexOf(String s, char ch, int fromIndex)
{ {
// Java allow fromIndex to both below zero or above the length of the string, .NET doesn't // Java allow fromIndex to both below zero or above the length of the string, .NET doesn't
system.String s = (system.String)(Object)si; return cli.System.String.IndexOf(s, ch, Math.max(0, Math.min(s.length(), fromIndex)));
return s.IndexOf(ch, Math.max(0, Math.min(s.get_Length(), fromIndex)));
} }
public static int indexOf(String si, String o, int fromIndex) public static int indexOf(String s, String o, int fromIndex)
{ {
// Java allow fromIndex to both below zero or above the length of the string, .NET doesn't // Java allow fromIndex to both below zero or above the length of the string, .NET doesn't
system.String s = (system.String)(Object)si; return cli.System.String.IndexOf(s, o, Math.max(0, Math.min(s.length(), fromIndex)));
return s.IndexOf(o, Math.max(0, Math.min(s.get_Length(), fromIndex)));
} }
public static int lastIndexOf(String si, char ch, int fromIndex) public static int lastIndexOf(String s, char ch, int fromIndex)
{ {
system.String s = (system.String)(Object)si;
// start by dereferencing s, to make sure we throw a NullPointerException if s is null // start by dereferencing s, to make sure we throw a NullPointerException if s is null
int len = s.get_Length(); int len = s.length();
if(fromIndex < 0) if(fromIndex < 0)
{ {
return -1; return -1;
} }
// Java allow fromIndex to be above the length of the string, .NET doesn't // Java allow fromIndex to be above the length of the string, .NET doesn't
return s.LastIndexOf(ch, Math.min(len - 1, fromIndex)); return cli.System.String.LastIndexOf(s, ch, Math.min(len - 1, fromIndex));
} }
public static int lastIndexOf(String s, String o) public static int lastIndexOf(String s, String o)
@ -376,11 +372,10 @@ public final class StringHelper
return lastIndexOf(s, o, s.length()); return lastIndexOf(s, o, s.length());
} }
public static int lastIndexOf(String si, String o, int fromIndex) public static int lastIndexOf(String s, String o, int fromIndex)
{ {
system.String s = (system.String)(Object)si;
// start by dereferencing s, to make sure we throw a NullPointerException if s is null // start by dereferencing s, to make sure we throw a NullPointerException if s is null
int len = s.get_Length(); int len = s.length();
if(fromIndex < 0) if(fromIndex < 0)
{ {
return -1; return -1;
@ -390,7 +385,7 @@ public final class StringHelper
return Math.min(len, fromIndex); return Math.min(len, fromIndex);
} }
// Java allow fromIndex to be above the length of the string, .NET doesn't // Java allow fromIndex to be above the length of the string, .NET doesn't
return s.LastIndexOf(o, Math.min(len - 1, fromIndex + o.length() - 1)); return cli.System.String.LastIndexOf(s, o, Math.min(len - 1, fromIndex + o.length() - 1));
} }
public static String concat(String s1, String s2) public static String concat(String s1, String s2)
@ -401,7 +396,7 @@ public final class StringHelper
{ {
return s1; return s1;
} }
return system.String.Concat(s1, s2); return cli.System.String.Concat(s1, s2);
} }
public static void getBytes(String s, int srcBegin, int srcEnd, byte dst[], int dstBegin) public static void getBytes(String s, int srcBegin, int srcEnd, byte dst[], int dstBegin)
@ -501,7 +496,7 @@ public final class StringHelper
public static String valueOf(char c) public static String valueOf(char c)
{ {
return new system.String(c, 1).ToString(); return cli.System.String.__new(c, 1);
} }
public static String valueOf(float f) public static String valueOf(float f)
@ -531,11 +526,11 @@ public final class StringHelper
public static int hashCode(String s) public static int hashCode(String s)
{ {
system.String ns = (system.String)(Object)s;
int h = 0; int h = 0;
for(int i = 0; i < ns.get_Length(); i++) int len = s.length();
for(int i = 0; i < len; i++)
{ {
h = h *31 + ns.get_Chars(i); h = h *31 + cli.System.String.get_Chars(s, i);
} }
return h; return h;
} }

Просмотреть файл

@ -40,8 +40,8 @@ package java.lang;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import system.*; import cli.System.*;
import system.reflection.*; import cli.System.Reflection.*;
/* /*
* This class is a reference version, mainly for compiling a class library * This class is a reference version, mainly for compiling a class library
@ -57,366 +57,345 @@ import system.reflection.*;
*/ */
final class VMClass final class VMClass
{ {
/** The .NET type */ private Object wrapper; // the corresponding TypeWrapper
private Type type;
private Object wrapper;
private Class clazz; private Class clazz;
public static native Class getClassFromType(Type t); // NOTE this is used in classpath.cs to go from a Class object to a TypeWrapper
private static native Type getTypeFromWrapper(Object clazz, Object wrapper); private static Object getWrapperFromClass(Class c)
private static native Object getWrapperFromType(Type t);
private static Type getTypeFromClass(Class c)
{ {
return c.vmClass.getType(); return c.vmClass.wrapper;
} }
private Type getType() private VMClass(Object wrapper)
{ {
if(type == null) this.wrapper = wrapper;
{ }
type = getTypeFromWrapper(clazz, wrapper);
}
return type;
}
private Object getWrapper()
{
if(wrapper == null)
{
wrapper = getWrapperFromType(type);
}
return wrapper;
}
private VMClass(Type type, Object wrapper) // HACK public because we want to create a delegate to call it
{ public static Object createClass(Object wrapper)
this.type = type; {
this.wrapper = wrapper; VMClass vmClass = new VMClass(wrapper);
} Class c = new Class(vmClass);
vmClass.clazz = c;
private static Class createClass(Type type, Object wrapper) return c;
{ }
VMClass vmClass = new VMClass(type, wrapper);
Class c = new Class(vmClass);
vmClass.clazz = c;
return c;
}
// HACK we need a way to call ClassLoader.loadClass() from C#, so we need this helper method // HACK we need a way to call ClassLoader.loadClass() from C#, so we need this helper method
public static Object __loadClassHelper(Object loader, String name) throws java.lang.ClassNotFoundException // and its public because we want to create a delegate to call it
public static Object loadClassHelper(Object loader, String name) throws java.lang.ClassNotFoundException
{ {
return ((ClassLoader)loader).loadClass(name).vmClass.getWrapper(); return ((ClassLoader)loader).loadClass(name).vmClass.wrapper;
} }
/** /**
* Discover whether an Object is an instance of this Class. Think of it * Discover whether an Object is an instance of this Class. Think of it
* as almost like <code>o instanceof (this class)</code>. * as almost like <code>o instanceof (this class)</code>.
* *
* @param o the Object to check * @param o the Object to check
* @return whether o is an instance of this class * @return whether o is an instance of this class
* @since 1.1 * @since 1.1
*/ */
boolean isInstance(Object o) boolean isInstance(Object o)
{ {
// TODO this needs to be implemented by the "native" code, because return o != null && clazz.isAssignableFrom(o.getClass());
// remapped types can appear to implement interfaces that they don't }
// actually implement
return getType().IsInstanceOfType(o);
}
/** /**
* Discover whether an instance of the Class parameter would be an * Discover whether an instance of the Class parameter would be an
* instance of this Class as well. Think of doing * instance of this Class as well. Think of doing
* <code>isInstance(c.newInstance())</code> or even * <code>isInstance(c.newInstance())</code> or even
* <code>c.newInstance() instanceof (this class)</code>. While this * <code>c.newInstance() instanceof (this class)</code>. While this
* checks widening conversions for objects, it must be exact for primitive * checks widening conversions for objects, it must be exact for primitive
* types. * types.
* *
* @param c the class to check * @param c the class to check
* @return whether an instance of c would be an instance of this class * @return whether an instance of c would be an instance of this class
* as well * as well
* @throws NullPointerException if c is null * @throws NullPointerException if c is null
* @since 1.1 * @since 1.1
*/ */
boolean isAssignableFrom(Class c) boolean isAssignableFrom(Class c)
{ {
// this needs to be implemented by the "native" code, because // this is implemented by the "native" code, because
// remapped types can appear to implement interfaces that they don't // remapped types can appear to implement interfaces that they don't
// actually implement // actually implement
return IsAssignableFrom(getWrapper(), c.vmClass.getWrapper()); return IsAssignableFrom(wrapper, c.vmClass.wrapper);
} }
private static native boolean IsAssignableFrom(Object w1, Object w2); private static native boolean IsAssignableFrom(Object w1, Object w2);
/** /**
* Check whether this class is an interface or not. Array types are not * Check whether this class is an interface or not. Array types are not
* interfaces. * interfaces.
* *
* @return whether this class is an interface or not * @return whether this class is an interface or not
*/ */
boolean isInterface() boolean isInterface()
{ {
return getType().get_IsInterface(); return IsInterface(wrapper);
} }
private static native boolean IsInterface(Object wrapper);
/** /**
* Return whether this class is a primitive type. A primitive type class * Return whether this class is a primitive type. A primitive type class
* is a class representing a kind of "placeholder" for the various * is a class representing a kind of "placeholder" for the various
* primitive types, or void. You can access the various primitive type * primitive types, or void. You can access the various primitive type
* classes through java.lang.Boolean.TYPE, java.lang.Integer.TYPE, etc., * classes through java.lang.Boolean.TYPE, java.lang.Integer.TYPE, etc.,
* or through boolean.class, int.class, etc. * or through boolean.class, int.class, etc.
* *
* @return whether this class is a primitive type * @return whether this class is a primitive type
* @see Boolean#TYPE * @see Boolean#TYPE
* @see Byte#TYPE * @see Byte#TYPE
* @see Character#TYPE * @see Character#TYPE
* @see Short#TYPE * @see Short#TYPE
* @see Integer#TYPE * @see Integer#TYPE
* @see Long#TYPE * @see Long#TYPE
* @see Float#TYPE * @see Float#TYPE
* @see Double#TYPE * @see Double#TYPE
* @see Void#TYPE * @see Void#TYPE
* @since 1.1 * @since 1.1
*/ */
boolean isPrimitive() boolean isPrimitive()
{ {
return clazz == boolean.class || return clazz == boolean.class ||
clazz == byte.class || clazz == byte.class ||
clazz == char.class || clazz == char.class ||
clazz == short.class || clazz == short.class ||
clazz == int.class || clazz == int.class ||
clazz == long.class || clazz == long.class ||
clazz == float.class || clazz == float.class ||
clazz == double.class || clazz == double.class ||
clazz == void.class; clazz == void.class;
} }
/** /**
* Get the name of this class, separated by dots for package separators. * Get the name of this class, separated by dots for package separators.
* Primitive types and arrays are encoded as: * Primitive types and arrays are encoded as:
* <pre> * <pre>
* boolean Z * boolean Z
* byte B * byte B
* char C * char C
* short S * short S
* int I * int I
* long J * long J
* float F * float F
* double D * double D
* void V * void V
* array type [<em>element type</em> * array type [<em>element type</em>
* class or interface, alone: &lt;dotted name&gt; * class or interface, alone: &lt;dotted name&gt;
* class or interface, as element type: L&lt;dotted name&gt;; * class or interface, as element type: L&lt;dotted name&gt;;
* *
* @return the name of this class * @return the name of this class
*/ */
String getName() String getName()
{ {
// getName() is used by the classloader, so it shouldn't trigger a resolve of the class // getName() is used by the classloader, so it shouldn't trigger a resolve of the class
return GetName(type, wrapper); return GetName(wrapper);
} }
private static native String GetName(Type type, Object wrapper); private static native String GetName(Object wrapper);
/** /**
* Get the direct superclass of this class. If this is an interface, * Get the direct superclass of this class. If this is an interface,
* Object, a primitive type, or void, it will return null. If this is an * Object, a primitive type, or void, it will return null. If this is an
* array type, it will return Object. * array type, it will return Object.
* *
* @return the direct superclass of this class * @return the direct superclass of this class
*/ */
Class getSuperclass() Class getSuperclass()
{ {
return (Class)GetSuperClassFromWrapper(getWrapper()); return (Class)GetSuperClassFromWrapper(wrapper);
} }
private native static Object GetSuperClassFromWrapper(Object wrapper); private native static Object GetSuperClassFromWrapper(Object wrapper);
/** /**
* Get the interfaces this class <EM>directly</EM> implements, in the * Get the interfaces this class <EM>directly</EM> implements, in the
* order that they were declared. This returns an empty array, not null, * order that they were declared. This returns an empty array, not null,
* for Object, primitives, void, and classes or interfaces with no direct * for Object, primitives, void, and classes or interfaces with no direct
* superinterface. Array types return Cloneable and Serializable. * superinterface. Array types return Cloneable and Serializable.
* *
* @return the interfaces this class directly implements * @return the interfaces this class directly implements
*/ */
Class[] getInterfaces() Class[] getInterfaces()
{ {
Object[] interfaces = GetInterfaces(type, wrapper); Object[] interfaces = GetInterfaces(wrapper);
Class[] interfacesClass = new Class[interfaces.length]; Class[] interfacesClass = new Class[interfaces.length];
System.arraycopy(interfaces, 0, interfacesClass, 0, interfaces.length); System.arraycopy(interfaces, 0, interfacesClass, 0, interfaces.length);
return interfacesClass; return interfacesClass;
} }
private static native Object[] GetInterfaces(Type type, Object wrapper); private static native Object[] GetInterfaces(Object wrapper);
/** /**
* If this is an array, get the Class representing the type of array. * If this is an array, get the Class representing the type of array.
* Examples: "[[Ljava.lang.String;" would return "[Ljava.lang.String;", and * Examples: "[[Ljava.lang.String;" would return "[Ljava.lang.String;", and
* calling getComponentType on that would give "java.lang.String". If * calling getComponentType on that would give "java.lang.String". If
* this is not an array, returns null. * this is not an array, returns null.
* *
* @return the array type of this class, or null * @return the array type of this class, or null
* @see Array * @see Array
* @since 1.1 * @since 1.1
*/ */
Class getComponentType() Class getComponentType()
{ {
// .NET array types can have unfinished element types, but we don't // .NET array types can have unfinished element types, but we don't
// want to expose those, so we may need to finish the type // want to expose those, so we may need to finish the type
return (Class)getComponentClassFromWrapper(getWrapper()); return (Class)getComponentClassFromWrapper(wrapper);
} }
private static native Object getComponentClassFromWrapper(Object wrapper); private static native Object getComponentClassFromWrapper(Object wrapper);
/** /**
* Get the modifiers of this class. These can be decoded using Modifier, * Get the modifiers of this class. These can be decoded using Modifier,
* and is limited to one of public, protected, or private, and any of * and is limited to one of public, protected, or private, and any of
* final, static, abstract, or interface. An array class has the same * final, static, abstract, or interface. An array class has the same
* public, protected, or private modifier as its component type, and is * public, protected, or private modifier as its component type, and is
* marked final but not an interface. Primitive types and void are marked * marked final but not an interface. Primitive types and void are marked
* public and final, but not an interface. * public and final, but not an interface.
* *
* @return the modifiers of this class * @return the modifiers of this class
* @see Modifer * @see Modifer
* @since 1.1 * @since 1.1
*/ */
int getModifiers() int getModifiers()
{ {
return GetModifiers(type, wrapper); return GetModifiers(wrapper);
} }
private static native int GetModifiers(Type type, Object wrapper); private static native int GetModifiers(Object wrapper);
/** /**
* If this is a nested or inner class, return the class that declared it. * If this is a nested or inner class, return the class that declared it.
* If not, return null. * If not, return null.
* *
* @return the declaring class of this class * @return the declaring class of this class
* @since 1.1 * @since 1.1
*/ */
Class getDeclaringClass() Class getDeclaringClass()
{ {
return (Class)GetDeclaringClass(type, wrapper); return (Class)GetDeclaringClass(wrapper);
} }
private native static Object GetDeclaringClass(Type type, Object wrapper); private native static Object GetDeclaringClass(Object wrapper);
/** /**
* Like <code>getDeclaredClasses()</code> but without the security checks. * Like <code>getDeclaredClasses()</code> but without the security checks.
* *
* @param pulicOnly Only public classes should be returned * @param pulicOnly Only public classes should be returned
*/ */
Class[] getDeclaredClasses(boolean publicOnly) Class[] getDeclaredClasses(boolean publicOnly)
{ {
Object[] classes = GetDeclaredClasses(type, wrapper, publicOnly); Object[] classes = GetDeclaredClasses(wrapper, publicOnly);
Class[] classesClass = new Class[classes.length]; Class[] classesClass = new Class[classes.length];
System.arraycopy(classes, 0, classesClass, 0, classes.length); System.arraycopy(classes, 0, classesClass, 0, classes.length);
return classesClass; return classesClass;
} }
private static native Object[] GetDeclaredClasses(Type type, Object wrapper, boolean publicOnly); private static native Object[] GetDeclaredClasses(Object wrapper, boolean publicOnly);
/** /**
* Like <code>getDeclaredFields()</code> but without the security checks. * Like <code>getDeclaredFields()</code> but without the security checks.
* *
* @param pulicOnly Only public fields should be returned * @param pulicOnly Only public fields should be returned
*/ */
Field[] getDeclaredFields(boolean publicOnly) Field[] getDeclaredFields(boolean publicOnly)
{
Object[] fieldCookies = GetDeclaredFields(wrapper, publicOnly);
Field[] fields = new Field[fieldCookies.length];
for(int i = 0; i < fields.length; i++)
{ {
Object[] fieldCookies = GetDeclaredFields(type, wrapper, publicOnly); fields[i] = new Field(clazz, fieldCookies[i]);
Field[] fields = new Field[fieldCookies.length];
for(int i = 0; i < fields.length; i++)
{
fields[i] = new Field(clazz, fieldCookies[i]);
}
return fields;
} }
private static native Object[] GetDeclaredFields(Type type, Object wrapper, boolean publicOnly); return fields;
}
private static native Object[] GetDeclaredFields(Object wrapper, boolean publicOnly);
/** /**
* Like <code>getDeclaredMethods()</code> but without the security checks. * Like <code>getDeclaredMethods()</code> but without the security checks.
* *
* @param pulicOnly Only public methods should be returned * @param pulicOnly Only public methods should be returned
*/ */
Method[] getDeclaredMethods(boolean publicOnly) Method[] getDeclaredMethods(boolean publicOnly)
{
Object[] methodCookies = GetDeclaredMethods(wrapper, true, publicOnly);
Method[] methods = new Method[methodCookies.length];
for(int i = 0; i < methodCookies.length; i++)
{ {
Object[] methodCookies = GetDeclaredMethods(type, wrapper, true, publicOnly); methods[i] = new Method(clazz, methodCookies[i]);
Method[] methods = new Method[methodCookies.length];
for(int i = 0; i < methodCookies.length; i++)
{
methods[i] = new Method(clazz, methodCookies[i]);
}
return methods;
} }
private static native Object[] GetDeclaredMethods(Type type, Object wrapper, boolean methods, boolean publicOnly); return methods;
}
private static native Object[] GetDeclaredMethods(Object wrapper, boolean methods, boolean publicOnly);
/** /**
* Like <code>getDeclaredConstructors()</code> but without * Like <code>getDeclaredConstructors()</code> but without
* the security checks. * the security checks.
* *
* @param pulicOnly Only public constructors should be returned * @param pulicOnly Only public constructors should be returned
*/ */
Constructor[] getDeclaredConstructors(boolean publicOnly) Constructor[] getDeclaredConstructors(boolean publicOnly)
{
Object[] methodCookies = GetDeclaredMethods(wrapper, false, publicOnly);
Constructor[] constructors = new Constructor[methodCookies.length];
for(int i = 0; i < methodCookies.length; i++)
{ {
Object[] methodCookies = GetDeclaredMethods(type, wrapper, false, publicOnly); constructors[i] = new Constructor(clazz, methodCookies[i]);
Constructor[] constructors = new Constructor[methodCookies.length];
for(int i = 0; i < methodCookies.length; i++)
{
constructors[i] = new Constructor(clazz, methodCookies[i]);
}
return constructors;
} }
return constructors;
}
/** /**
* Return the class loader of this class. * Return the class loader of this class.
* *
* @return the class loader * @return the class loader
*/ */
ClassLoader getClassLoader() ClassLoader getClassLoader()
{ {
// getClassLoader() can be used by the classloader, so it shouldn't trigger a resolve of the class // getClassLoader() can be used by the classloader, so it shouldn't trigger a resolve of the class
return getClassLoader0(type, wrapper); return getClassLoader0(wrapper);
} }
private static native ClassLoader getClassLoader0(Type type, Object wrapper); private static native ClassLoader getClassLoader0(Object wrapper);
/** /**
* VM implementors are free to make this method a noop if * VM implementors are free to make this method a noop if
* the default implementation is acceptable. * the default implementation is acceptable.
* *
* @param name the name of the class to find * @param name the name of the class to find
* @return the Class object representing the class or null for noop * @return the Class object representing the class or null for noop
* @throws ClassNotFoundException if the class was not found by the * @throws ClassNotFoundException if the class was not found by the
* classloader * classloader
* @throws LinkageError if linking the class fails * @throws LinkageError if linking the class fails
* @throws ExceptionInInitializerError if the class loads, but an exception * @throws ExceptionInInitializerError if the class loads, but an exception
* occurs during initialization * occurs during initialization
*/ */
static Class forName(String name) throws ClassNotFoundException static Class forName(String name) throws ClassNotFoundException
{
// if we ever get back to using a separate assembly for each class loader, it
// might be faster to use Assembly.GetCallingAssembly here...
cli.System.Diagnostics.StackFrame frame = new cli.System.Diagnostics.StackFrame(1);
// HACK a lame way to deal with potential inlining of this method (or Class.forName)
if(frame.GetMethod().get_Name().equals("forName"))
{ {
// if we ever get back to using a separate assembly for each class loader, it frame = new cli.System.Diagnostics.StackFrame(2);
// might be faster to use Assembly.GetCallingAssembly here...
system.diagnostics.StackFrame frame = new system.diagnostics.StackFrame(1);
// HACK a lame way to deal with potential inlining of this method (or Class.forName)
if(frame.GetMethod().get_Name().equals("forName"))
{
frame = new system.diagnostics.StackFrame(2);
}
ClassLoader cl = getClassLoader0(frame.GetMethod().get_DeclaringType(), null);
return Class.forName(name, true, cl);
} }
ClassLoader cl = getClassLoaderFromType(frame.GetMethod().get_DeclaringType());
return Class.forName(name, true, cl);
}
private static native ClassLoader getClassLoaderFromType(Type type);
void initialize() void initialize()
{ {
initializeType(getType()); initialize(wrapper);
} }
private static native void initialize(Object wrapper);
static native Class loadArrayClass(String name, Object classLoader); static native Class loadArrayClass(String name, Object classLoader);
static native Class loadBootstrapClass(String name, boolean initialize); static native Class loadBootstrapClass(String name, boolean initialize);
private static native void initializeType(Type type);
static native void throwException(Throwable t); static native void throwException(Throwable t);
/** /**
* Return whether this class is an array type. * Return whether this class is an array type.
* *
* @return 1 if this class is an array type, 0 otherwise, -1 if unsupported * @return 1 if this class is an array type, 0 otherwise, -1 if unsupported
* operation * operation
*/ */
int isArray() int isArray()
{ {
return getType().get_IsArray() ? 1 : 0; return IsArray(wrapper) ? 1 : 0;
} }
} // class VMClass private static native boolean IsArray(Object wrapper);
}

Просмотреть файл

@ -46,8 +46,8 @@ import java.util.Map;
import java.util.HashMap; import java.util.HashMap;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import gnu.java.lang.SystemClassLoader; import gnu.java.lang.SystemClassLoader;
import system.*; import cli.System.*;
import system.reflection.*; import cli.System.Reflection.*;
/** /**
* java.lang.VMClassLoader is a package-private helper for VMs to implement * java.lang.VMClassLoader is a package-private helper for VMs to implement
@ -217,12 +217,7 @@ final class VMClassLoader
* @param type the primitive type * @param type the primitive type
* @return a "bogus" class representing the primitive type * @return a "bogus" class representing the primitive type
*/ */
static final Class getPrimitiveClass(char type) static native Class getPrimitiveClass(char type);
{
return VMClass.getClassFromType(getPrimitiveType(type));
}
private static native system.Type getPrimitiveType(char type);
/** /**
* The system default for assertion status. This is used for all system * The system default for assertion status. This is used for all system

Просмотреть файл

@ -28,7 +28,7 @@ final class VMDouble
{ {
static double longBitsToDouble(long v) static double longBitsToDouble(long v)
{ {
return system.BitConverter.Int64BitsToDouble(v); return cli.System.BitConverter.Int64BitsToDouble(v);
} }
static long doubleToLongBits(double v) static long doubleToLongBits(double v)
@ -37,11 +37,11 @@ final class VMDouble
{ {
return 0x7ff8000000000000L; return 0x7ff8000000000000L;
} }
return system.BitConverter.DoubleToInt64Bits(v); return cli.System.BitConverter.DoubleToInt64Bits(v);
} }
static long doubleToRawLongBits(double v) static long doubleToRawLongBits(double v)
{ {
return system.BitConverter.DoubleToInt64Bits(v); return cli.System.BitConverter.DoubleToInt64Bits(v);
} }
} }

Просмотреть файл

@ -28,7 +28,7 @@ final class VMFloat
{ {
static float intBitsToFloat(int v) static float intBitsToFloat(int v)
{ {
return system.BitConverter.ToSingle(system.BitConverter.GetBytes(v), 0); return cli.System.BitConverter.ToSingle(cli.System.BitConverter.GetBytes(v), 0);
} }
static int floatToIntBits(float v) static int floatToIntBits(float v)
@ -37,11 +37,11 @@ final class VMFloat
{ {
return 0x7fc00000; return 0x7fc00000;
} }
return system.BitConverter.ToInt32(system.BitConverter.GetBytes(v), 0); return cli.System.BitConverter.ToInt32(cli.System.BitConverter.GetBytes(v), 0);
} }
static int floatToRawIntBits(float v) static int floatToRawIntBits(float v)
{ {
return system.BitConverter.ToInt32(system.BitConverter.GetBytes(v), 0); return cli.System.BitConverter.ToInt32(cli.System.BitConverter.GetBytes(v), 0);
} }
} }

Просмотреть файл

@ -115,21 +115,21 @@ final class VMThread
thread.stillborn = t; thread.stillborn = t;
} }
private static system.LocalDataStoreSlot localDataStoreSlot = system.threading.Thread.AllocateDataSlot(); private static cli.System.LocalDataStoreSlot localDataStoreSlot = cli.System.Threading.Thread.AllocateDataSlot();
private system.threading.Thread nativeThread; private cli.System.Threading.Thread nativeThread;
/*native*/ void start(long stacksize) /*native*/ void start(long stacksize)
{ {
system.threading.ThreadStart starter = new system.threading.ThreadStart( cli.System.Threading.ThreadStart starter = new cli.System.Threading.ThreadStart(
new system.threading.ThreadStart.Method() new cli.System.Threading.ThreadStart.Method()
{ {
public void Invoke() public void Invoke()
{ {
system.threading.Thread.SetData(localDataStoreSlot, thread); cli.System.Threading.Thread.SetData(localDataStoreSlot, thread);
run(); run();
} }
}); });
nativeThread = new system.threading.Thread(starter); nativeThread = new cli.System.Threading.Thread(starter);
nativeThread.set_Name(thread.name); nativeThread.set_Name(thread.name);
nativeThread.set_IsBackground(thread.daemon); nativeThread.set_IsBackground(thread.daemon);
nativeSetPriority(thread.priority); nativeSetPriority(thread.priority);
@ -149,7 +149,7 @@ final class VMThread
try try
{ {
if(false) throw new InterruptedException(); if(false) throw new InterruptedException();
system.threading.Thread.Sleep(0); cli.System.Threading.Thread.Sleep(0);
return false; return false;
} }
catch(InterruptedException x) catch(InterruptedException x)
@ -179,23 +179,23 @@ final class VMThread
{ {
if(priority == Thread.MIN_PRIORITY) if(priority == Thread.MIN_PRIORITY)
{ {
nativeThread.set_Priority(system.threading.ThreadPriority.Lowest); nativeThread.set_Priority(cli.System.Threading.ThreadPriority.wrap(cli.System.Threading.ThreadPriority.Lowest));
} }
else if(priority > Thread.MIN_PRIORITY && priority < Thread.NORM_PRIORITY) else if(priority > Thread.MIN_PRIORITY && priority < Thread.NORM_PRIORITY)
{ {
nativeThread.set_Priority(system.threading.ThreadPriority.BelowNormal); nativeThread.set_Priority(cli.System.Threading.ThreadPriority.wrap(cli.System.Threading.ThreadPriority.BelowNormal));
} }
else if(priority == Thread.NORM_PRIORITY) else if(priority == Thread.NORM_PRIORITY)
{ {
nativeThread.set_Priority(system.threading.ThreadPriority.Normal); nativeThread.set_Priority(cli.System.Threading.ThreadPriority.wrap(cli.System.Threading.ThreadPriority.Normal));
} }
else if(priority > Thread.NORM_PRIORITY && priority < Thread.MAX_PRIORITY) else if(priority > Thread.NORM_PRIORITY && priority < Thread.MAX_PRIORITY)
{ {
nativeThread.set_Priority(system.threading.ThreadPriority.AboveNormal); nativeThread.set_Priority(cli.System.Threading.ThreadPriority.wrap(cli.System.Threading.ThreadPriority.AboveNormal));
} }
else if(priority == Thread.MAX_PRIORITY) else if(priority == Thread.MAX_PRIORITY)
{ {
nativeThread.set_Priority(system.threading.ThreadPriority.Highest); nativeThread.set_Priority(cli.System.Threading.ThreadPriority.wrap(cli.System.Threading.ThreadPriority.Highest));
} }
} }
@ -206,37 +206,37 @@ final class VMThread
/*native*/ static Thread currentThread() /*native*/ static Thread currentThread()
{ {
Thread javaThread = (Thread)system.threading.Thread.GetData(localDataStoreSlot); Thread javaThread = (Thread)cli.System.Threading.Thread.GetData(localDataStoreSlot);
if(javaThread == null) if(javaThread == null)
{ {
// threads created outside of Java always run in the root thread group // threads created outside of Java always run in the root thread group
// TODO if the thread dies, it needs to be removed from the root ThreadGroup // TODO if the thread dies, it needs to be removed from the root ThreadGroup
// and any other threads waiting to join it, should be released. // and any other threads waiting to join it, should be released.
system.threading.Thread nativeThread = system.threading.Thread.get_CurrentThread(); cli.System.Threading.Thread nativeThread = cli.System.Threading.Thread.get_CurrentThread();
VMThread vmThread = new VMThread(null); VMThread vmThread = new VMThread(null);
vmThread.nativeThread = nativeThread; vmThread.nativeThread = nativeThread;
int priority = Thread.NORM_PRIORITY; int priority = Thread.NORM_PRIORITY;
switch(nativeThread.get_Priority()) switch(nativeThread.get_Priority().Value)
{ {
case system.threading.ThreadPriority.Lowest: case cli.System.Threading.ThreadPriority.Lowest:
priority = Thread.MIN_PRIORITY; priority = Thread.MIN_PRIORITY;
break; break;
case system.threading.ThreadPriority.BelowNormal: case cli.System.Threading.ThreadPriority.BelowNormal:
priority = 3; priority = 3;
break; break;
case system.threading.ThreadPriority.Normal: case cli.System.Threading.ThreadPriority.Normal:
priority = Thread.NORM_PRIORITY; priority = Thread.NORM_PRIORITY;
break; break;
case system.threading.ThreadPriority.AboveNormal: case cli.System.Threading.ThreadPriority.AboveNormal:
priority = 7; priority = 7;
break; break;
case system.threading.ThreadPriority.Highest: case cli.System.Threading.ThreadPriority.Highest:
priority = Thread.MAX_PRIORITY; priority = Thread.MAX_PRIORITY;
break; break;
} }
javaThread = new Thread(vmThread, nativeThread.get_Name(), priority, nativeThread.get_IsBackground()); javaThread = new Thread(vmThread, nativeThread.get_Name(), priority, nativeThread.get_IsBackground());
vmThread.thread = javaThread; vmThread.thread = javaThread;
system.threading.Thread.SetData(localDataStoreSlot, javaThread); cli.System.Threading.Thread.SetData(localDataStoreSlot, javaThread);
javaThread.group = ThreadGroup.root; javaThread.group = ThreadGroup.root;
javaThread.group.addThread(javaThread); javaThread.group.addThread(javaThread);
InheritableThreadLocal.newChildThread(javaThread); InheritableThreadLocal.newChildThread(javaThread);
@ -246,20 +246,20 @@ final class VMThread
static /*native*/ void yield() static /*native*/ void yield()
{ {
system.threading.Thread.Sleep(0); cli.System.Threading.Thread.Sleep(0);
} }
static /*native*/ void sleep(long ms, int ns) throws InterruptedException static /*native*/ void sleep(long ms, int ns) throws InterruptedException
{ {
try try
{ {
if(false) throw new system.threading.ThreadInterruptedException(); if(false) throw new cli.System.Threading.ThreadInterruptedException();
// TODO guard against ms and ns overflowing // TODO guard against ms and ns overflowing
system.threading.Thread.Sleep(new system.TimeSpan(ms * 10000 + (ns + 99) / 100)); cli.System.Threading.Thread.Sleep(new cli.System.TimeSpan(ms * 10000 + (ns + 99) / 100));
} }
catch(system.threading.ThreadInterruptedException x) catch(cli.System.Threading.ThreadInterruptedException x)
{ {
throw new InterruptedException(x.get_Message()); throw new InterruptedException(x.getMessage());
} }
} }
@ -270,7 +270,7 @@ final class VMThread
synchronized(currentThread()) synchronized(currentThread())
{ {
if(false) throw new InterruptedException(); if(false) throw new InterruptedException();
system.threading.Thread.Sleep(0); cli.System.Threading.Thread.Sleep(0);
} }
return false; return false;
} }
@ -292,7 +292,7 @@ final class VMThread
// NOTE Wait causes the lock to be released temporarily, which isn't what we want // NOTE Wait causes the lock to be released temporarily, which isn't what we want
if(false) throw new IllegalMonitorStateException(); if(false) throw new IllegalMonitorStateException();
if(false) throw new InterruptedException(); if(false) throw new InterruptedException();
system.threading.Monitor.Wait(obj, 0); cli.System.Threading.Monitor.Wait(obj, 0);
return true; return true;
} }
catch(IllegalMonitorStateException x) catch(IllegalMonitorStateException x)
@ -302,7 +302,7 @@ final class VMThread
catch(InterruptedException x1) catch(InterruptedException x1)
{ {
// Since we "consumed" the interrupt, we have to interrupt ourself again // Since we "consumed" the interrupt, we have to interrupt ourself again
system.threading.Thread.get_CurrentThread().Interrupt(); cli.System.Threading.Thread.get_CurrentThread().Interrupt();
return true; return true;
} }
} }

Просмотреть файл

@ -38,8 +38,6 @@ exception statement from your version. */
package java.lang.reflect; package java.lang.reflect;
import system.reflection.*;
/** /**
* The Constructor class represents a constructor of a class. It also allows * The Constructor class represents a constructor of a class. It also allows
* dynamic creation of an object, via reflection. Invocation on Constructor * dynamic creation of an object, via reflection. Invocation on Constructor
@ -162,7 +160,7 @@ public final class Constructor
*/ */
public boolean equals(Object o) public boolean equals(Object o)
{ {
if(o instanceof ConstructorInfo) if(o instanceof Constructor)
{ {
return methodCookie == ((Constructor)o).methodCookie; return methodCookie == ((Constructor)o).methodCookie;
} }

Просмотреть файл

@ -38,8 +38,6 @@ exception statement from your version. */
package java.lang.reflect; package java.lang.reflect;
import system.reflection.*;
/** /**
* The Method class represents a member method of a class. It also allows * The Method class represents a member method of a class. It also allows
* dynamic invocation, via reflection. This works for both static and * dynamic invocation, via reflection. This works for both static and

Просмотреть файл

@ -39,9 +39,10 @@ exception statement from your version. */
package java.net; package java.net;
import java.io.IOException; import java.io.IOException;
import system.net.*; import cli.System.Net.*;
import system.net.sockets.*; import cli.System.Net.Sockets.*;
import ikvm.lang.CIL; import ikvm.lang.CIL;
import ikvm.lang.ByteArrayHack;
/** /**
* This is the default socket implementation for datagram sockets. * This is the default socket implementation for datagram sockets.
@ -70,12 +71,12 @@ public class PlainDatagramSocketImpl extends DatagramSocketImpl
private static class MyUdpClient extends UdpClient private static class MyUdpClient extends UdpClient
{ {
MyUdpClient(system.net.IPEndPoint ep) MyUdpClient(cli.System.Net.IPEndPoint ep)
{ {
super(ep); super(ep);
} }
system.net.sockets.Socket getSocket() cli.System.Net.Sockets.Socket getSocket()
{ {
return super.get_Client(); return super.get_Client();
} }
@ -153,7 +154,7 @@ public class PlainDatagramSocketImpl extends DatagramSocketImpl
{ {
// TODO error handling // TODO error handling
int len = packet.getLength(); int len = packet.getLength();
if(socket.Send(packet.getData(), len, new IPEndPoint(PlainSocketImpl.getAddressFromInetAddress(packet.getAddress()), packet.getPort())) != len) if(socket.Send(ByteArrayHack.cast(packet.getData()), len, new IPEndPoint(PlainSocketImpl.getAddressFromInetAddress(packet.getAddress()), packet.getPort())) != len)
{ {
// TODO // TODO
throw new IOException(); throw new IOException();
@ -183,13 +184,13 @@ public class PlainDatagramSocketImpl extends DatagramSocketImpl
{ {
try try
{ {
if(false) throw new system.net.sockets.SocketException(); if(false) throw new cli.System.Net.Sockets.SocketException();
byte[] data = packet.getData(); byte[] data = packet.getData();
int length = packet.getLength(); int length = packet.getLength();
system.net.IPEndPoint[] remoteEP = new system.net.IPEndPoint[] { cli.System.Net.IPEndPoint[] remoteEP = new cli.System.Net.IPEndPoint[] {
new system.net.IPEndPoint(0, 0) new cli.System.Net.IPEndPoint(0, 0)
}; };
byte[] buf = socket.Receive(remoteEP); byte[] buf = ByteArrayHack.cast(socket.Receive(remoteEP));
System.arraycopy(buf, 0, data, 0, Math.min(length, buf.length)); System.arraycopy(buf, 0, data, 0, Math.min(length, buf.length));
// I think the spec says that the Length property of DatagramPacket // I think the spec says that the Length property of DatagramPacket
// contains the number of bytes in the network packet (even if // contains the number of bytes in the network packet (even if
@ -201,10 +202,10 @@ public class PlainDatagramSocketImpl extends DatagramSocketImpl
packet.setAddress(remoteAddress); packet.setAddress(remoteAddress);
packet.setPort(remoteEP[0].get_Port()); packet.setPort(remoteEP[0].get_Port());
} }
catch(system.net.sockets.SocketException x) catch(cli.System.Net.Sockets.SocketException x)
{ {
// TODO error handling // TODO error handling
throw new IOException(x.get_Message()); throw new IOException(x.getMessage());
} }
} }
@ -221,13 +222,13 @@ public class PlainDatagramSocketImpl extends DatagramSocketImpl
{ {
try try
{ {
if(false) throw new system.net.sockets.SocketException(); if(false) throw new cli.System.Net.Sockets.SocketException();
socket.JoinMulticastGroup(new system.net.IPAddress(PlainSocketImpl.getAddressFromInetAddress(addr))); socket.JoinMulticastGroup(new cli.System.Net.IPAddress(PlainSocketImpl.getAddressFromInetAddress(addr)));
} }
catch(system.net.sockets.SocketException x) catch(cli.System.Net.Sockets.SocketException x)
{ {
// TODO error handling // TODO error handling
throw new IOException(x.get_Message()); throw new IOException(x.getMessage());
} }
} }
@ -244,13 +245,13 @@ public class PlainDatagramSocketImpl extends DatagramSocketImpl
{ {
try try
{ {
if(false) throw new system.net.sockets.SocketException(); if(false) throw new cli.System.Net.Sockets.SocketException();
socket.DropMulticastGroup(new system.net.IPAddress(PlainSocketImpl.getAddressFromInetAddress(addr))); socket.DropMulticastGroup(new cli.System.Net.IPAddress(PlainSocketImpl.getAddressFromInetAddress(addr)));
} }
catch(system.net.sockets.SocketException x) catch(cli.System.Net.Sockets.SocketException x)
{ {
// TODO error handling // TODO error handling
throw new IOException(x.get_Message()); throw new IOException(x.getMessage());
} }
} }
@ -335,20 +336,20 @@ public class PlainDatagramSocketImpl extends DatagramSocketImpl
{ {
try try
{ {
if(false) throw new system.net.sockets.SocketException(); if(false) throw new cli.System.Net.Sockets.SocketException();
switch(option_id) switch(option_id)
{ {
case IP_TTL: case IP_TTL:
return new Integer(CIL.unbox_int(socket.getSocket().GetSocketOption(SocketOptionLevel.IP, SocketOptionName.IpTimeToLive))); return new Integer(CIL.unbox_int(socket.getSocket().GetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.IP), SocketOptionName.wrap(SocketOptionName.IpTimeToLive))));
case SocketOptions.SO_TIMEOUT: case SocketOptions.SO_TIMEOUT:
return new Integer(CIL.unbox_int(socket.getSocket().GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout))); return new Integer(CIL.unbox_int(socket.getSocket().GetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.ReceiveTimeout))));
default: default:
throw new Error("getOption(" + option_id + ") not implemented"); throw new Error("getOption(" + option_id + ") not implemented");
} }
} }
catch(system.net.sockets.SocketException x) catch(cli.System.Net.Sockets.SocketException x)
{ {
throw new SocketException(x.get_Message()); throw new SocketException(x.getMessage());
} }
} }
@ -366,26 +367,26 @@ public class PlainDatagramSocketImpl extends DatagramSocketImpl
{ {
try try
{ {
if(false) throw new system.net.sockets.SocketException(); if(false) throw new cli.System.Net.Sockets.SocketException();
switch(option_id) switch(option_id)
{ {
case IP_TTL: case IP_TTL:
socket.getSocket().SetSocketOption(SocketOptionLevel.IP, SocketOptionName.IpTimeToLive, ((Integer)val).intValue()); socket.getSocket().SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.IP), SocketOptionName.wrap(SocketOptionName.IpTimeToLive), ((Integer)val).intValue());
break; break;
case SocketOptions.SO_TIMEOUT: case SocketOptions.SO_TIMEOUT:
socket.getSocket().SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, ((Integer)val).intValue()); socket.getSocket().SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.ReceiveTimeout), ((Integer)val).intValue());
socket.getSocket().SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, ((Integer)val).intValue()); socket.getSocket().SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.SendTimeout), ((Integer)val).intValue());
break; break;
case SocketOptions.SO_REUSEADDR: case SocketOptions.SO_REUSEADDR:
socket.getSocket().SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, ((Boolean)val).booleanValue() ? 1 : 0); socket.getSocket().SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.ReuseAddress), ((Boolean)val).booleanValue() ? 1 : 0);
break; break;
default: default:
throw new Error("setOption(" + option_id + ") not implemented"); throw new Error("setOption(" + option_id + ") not implemented");
} }
} }
catch(system.net.sockets.SocketException x) catch(cli.System.Net.Sockets.SocketException x)
{ {
throw new SocketException(x.get_Message()); throw new SocketException(x.getMessage());
} }
} }

Просмотреть файл

@ -41,9 +41,10 @@ package java.net;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.IOException; import java.io.IOException;
import system.net.*; import cli.System.Net.*;
import system.net.sockets.*; import cli.System.Net.Sockets.*;
import ikvm.lang.CIL; import ikvm.lang.CIL;
import ikvm.lang.ByteArrayHack;
/** /**
* Unless the application installs its own SocketImplFactory, this is the * Unless the application installs its own SocketImplFactory, this is the
@ -60,7 +61,7 @@ class PlainSocketImpl extends SocketImpl
/** /**
* This is the native file descriptor for this socket * This is the native file descriptor for this socket
*/ */
private system.net.sockets.Socket socket; private cli.System.Net.Sockets.Socket socket;
/** /**
@ -80,8 +81,8 @@ class PlainSocketImpl extends SocketImpl
{ {
try try
{ {
if(false) throw new system.net.sockets.SocketException(); if(false) throw new cli.System.Net.Sockets.SocketException();
system.net.sockets.Socket accept = socket.Accept(); cli.System.Net.Sockets.Socket accept = socket.Accept();
((PlainSocketImpl)impl).socket = accept; ((PlainSocketImpl)impl).socket = accept;
IPEndPoint remoteEndPoint = ((IPEndPoint)accept.get_RemoteEndPoint()); IPEndPoint remoteEndPoint = ((IPEndPoint)accept.get_RemoteEndPoint());
long remoteIP = remoteEndPoint.get_Address().get_Address(); long remoteIP = remoteEndPoint.get_Address().get_Address();
@ -90,10 +91,10 @@ class PlainSocketImpl extends SocketImpl
impl.port = remoteEndPoint.get_Port(); impl.port = remoteEndPoint.get_Port();
impl.localport = ((IPEndPoint)accept.get_LocalEndPoint()).get_Port(); impl.localport = ((IPEndPoint)accept.get_LocalEndPoint()).get_Port();
} }
catch(system.net.sockets.SocketException x) catch(cli.System.Net.Sockets.SocketException x)
{ {
// TODO error handling // TODO error handling
throw new IOException(x.get_Message()); throw new IOException(x.getMessage());
} }
} }
@ -109,13 +110,13 @@ class PlainSocketImpl extends SocketImpl
{ {
try try
{ {
if(false) throw new system.net.sockets.SocketException(); if(false) throw new cli.System.Net.Sockets.SocketException();
return socket.get_Available(); return socket.get_Available();
} }
catch(system.net.sockets.SocketException x) catch(cli.System.Net.Sockets.SocketException x)
{ {
// TODO error handling // TODO error handling
throw new IOException(x.get_Message()); throw new IOException(x.getMessage());
} }
} }
@ -132,14 +133,14 @@ class PlainSocketImpl extends SocketImpl
{ {
try try
{ {
if(false) throw new system.net.sockets.SocketException(); if(false) throw new cli.System.Net.Sockets.SocketException();
socket.Bind(new IPEndPoint(getAddressFromInetAddress(addr), port)); socket.Bind(new IPEndPoint(getAddressFromInetAddress(addr), port));
this.address = addr; this.address = addr;
} }
catch(system.net.sockets.SocketException x) catch(cli.System.Net.Sockets.SocketException x)
{ {
// TODO error handling // TODO error handling
throw new IOException(x.get_Message()); throw new IOException(x.getMessage());
} }
} }
@ -162,13 +163,13 @@ class PlainSocketImpl extends SocketImpl
{ {
try try
{ {
if(false) throw new system.net.sockets.SocketException(); if(false) throw new cli.System.Net.Sockets.SocketException();
socket.Close(); socket.Close();
} }
catch(system.net.sockets.SocketException x) catch(cli.System.Net.Sockets.SocketException x)
{ {
// TODO error handling // TODO error handling
throw new IOException(x.get_Message()); throw new IOException(x.getMessage());
} }
} }
@ -184,16 +185,16 @@ class PlainSocketImpl extends SocketImpl
{ {
try try
{ {
if(false) throw new system.net.sockets.SocketException(); if(false) throw new cli.System.Net.Sockets.SocketException();
socket.Connect(new IPEndPoint(getAddressFromInetAddress(addr), port)); socket.Connect(new IPEndPoint(getAddressFromInetAddress(addr), port));
this.address = addr; this.address = addr;
this.port = port; this.port = port;
this.localport = ((IPEndPoint)socket.get_LocalEndPoint()).get_Port(); this.localport = ((IPEndPoint)socket.get_LocalEndPoint()).get_Port();
} }
catch(system.net.sockets.SocketException x) catch(cli.System.Net.Sockets.SocketException x)
{ {
// TODO error handling // TODO error handling
throw new IOException(x.get_Message()); throw new IOException(x.getMessage());
} }
} }
@ -229,13 +230,13 @@ class PlainSocketImpl extends SocketImpl
} }
try try
{ {
if(false) throw new system.net.sockets.SocketException(); if(false) throw new cli.System.Net.Sockets.SocketException();
socket = new system.net.sockets.Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); socket = new cli.System.Net.Sockets.Socket(AddressFamily.wrap(AddressFamily.InterNetwork), SocketType.wrap(SocketType.Stream), ProtocolType.wrap(ProtocolType.Tcp));
} }
catch(system.net.sockets.SocketException x) catch(cli.System.Net.Sockets.SocketException x)
{ {
// TODO error handling // TODO error handling
throw new IOException(x.get_Message()); throw new IOException(x.getMessage());
} }
} }
@ -253,14 +254,14 @@ class PlainSocketImpl extends SocketImpl
{ {
try try
{ {
if(false) throw new system.net.sockets.SocketException(); if(false) throw new cli.System.Net.Sockets.SocketException();
socket.Listen(queuelen); socket.Listen(queuelen);
localport = ((IPEndPoint)socket.get_LocalEndPoint()).get_Port(); localport = ((IPEndPoint)socket.get_LocalEndPoint()).get_Port();
} }
catch(system.net.sockets.SocketException x) catch(cli.System.Net.Sockets.SocketException x)
{ {
// TODO error handling // TODO error handling
throw new IOException(x.get_Message()); throw new IOException(x.getMessage());
} }
} }
@ -277,13 +278,13 @@ class PlainSocketImpl extends SocketImpl
{ {
try try
{ {
if(false) throw new system.net.sockets.SocketException(); if(false) throw new cli.System.Net.Sockets.SocketException();
return socket.Receive(buf, offset, len, SocketFlags.None); return socket.Receive(ByteArrayHack.cast(buf), offset, len, SocketFlags.wrap(SocketFlags.None));
} }
catch(system.net.sockets.SocketException x) catch(cli.System.Net.Sockets.SocketException x)
{ {
// TODO error handling // TODO error handling
throw new IOException(x.get_Message()); throw new IOException(x.getMessage());
} }
} }
@ -298,13 +299,13 @@ class PlainSocketImpl extends SocketImpl
{ {
try try
{ {
if(false) throw new system.net.sockets.SocketException(); if(false) throw new cli.System.Net.Sockets.SocketException();
socket.Send(buf, offset, len, SocketFlags.None); socket.Send(ByteArrayHack.cast(buf), offset, len, SocketFlags.wrap(SocketFlags.None));
} }
catch(system.net.sockets.SocketException x) catch(cli.System.Net.Sockets.SocketException x)
{ {
// TODO error handling // TODO error handling
throw new IOException(x.get_Message()); throw new IOException(x.getMessage());
} }
} }
@ -323,56 +324,56 @@ class PlainSocketImpl extends SocketImpl
{ {
try try
{ {
if(false) throw new system.net.sockets.SocketException(); if(false) throw new cli.System.Net.Sockets.SocketException();
switch(option_id) switch(option_id)
{ {
case SocketOptions.TCP_NODELAY: case SocketOptions.TCP_NODELAY:
socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, ((Boolean)val).booleanValue() ? 1 : 0); socket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Tcp), SocketOptionName.wrap(SocketOptionName.NoDelay), ((Boolean)val).booleanValue() ? 1 : 0);
break; break;
case SocketOptions.SO_KEEPALIVE: case SocketOptions.SO_KEEPALIVE:
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, ((Boolean)val).booleanValue() ? 1 : 0); socket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.KeepAlive), ((Boolean)val).booleanValue() ? 1 : 0);
break; break;
case SocketOptions.SO_TIMEOUT: case SocketOptions.SO_TIMEOUT:
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, ((Integer)val).intValue()); socket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.ReceiveTimeout), ((Integer)val).intValue());
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, ((Integer)val).intValue()); socket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.SendTimeout), ((Integer)val).intValue());
break; break;
case SocketOptions.SO_LINGER: case SocketOptions.SO_LINGER:
{ {
system.net.sockets.LingerOption linger; cli.System.Net.Sockets.LingerOption linger;
if(val instanceof Boolean) if(val instanceof Boolean)
{ {
linger = new system.net.sockets.LingerOption(false, 0); linger = new cli.System.Net.Sockets.LingerOption(false, 0);
} }
else else
{ {
linger = new system.net.sockets.LingerOption(true, ((Integer)val).intValue()); linger = new cli.System.Net.Sockets.LingerOption(true, ((Integer)val).intValue());
} }
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, linger); socket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.Linger), linger);
break; break;
} }
case SocketOptions.SO_OOBINLINE: case SocketOptions.SO_OOBINLINE:
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.OutOfBandInline, ((Boolean)val).booleanValue() ? 1 : 0); socket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.OutOfBandInline), ((Boolean)val).booleanValue() ? 1 : 0);
break; break;
case SocketOptions.SO_SNDBUF: case SocketOptions.SO_SNDBUF:
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendBuffer, ((Integer)val).intValue()); socket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.SendBuffer), ((Integer)val).intValue());
break; break;
case SocketOptions.SO_RCVBUF: case SocketOptions.SO_RCVBUF:
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer, ((Integer)val).intValue()); socket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.ReceiveBuffer), ((Integer)val).intValue());
break; break;
case SocketOptions.SO_REUSEADDR: case SocketOptions.SO_REUSEADDR:
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, ((Boolean)val).booleanValue() ? 1 : 0); socket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.ReuseAddress), ((Boolean)val).booleanValue() ? 1 : 0);
break; break;
case SocketOptions.IP_TOS: case SocketOptions.IP_TOS:
socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.TypeOfService, ((Integer)val).intValue()); socket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.IP), SocketOptionName.wrap(SocketOptionName.TypeOfService), ((Integer)val).intValue());
break; break;
default: default:
throw new Error("Socket.setOption(" + option_id + ") not implemented"); throw new Error("Socket.setOption(" + option_id + ") not implemented");
} }
} }
catch(system.net.sockets.SocketException x) catch(cli.System.Net.Sockets.SocketException x)
{ {
// TODO error handling // TODO error handling
throw new SocketException(x.get_Message()); throw new SocketException(x.getMessage());
} }
} }
@ -391,7 +392,7 @@ class PlainSocketImpl extends SocketImpl
{ {
try try
{ {
if(false) throw new system.net.sockets.SocketException(); if(false) throw new cli.System.Net.Sockets.SocketException();
switch(option_id) switch(option_id)
{ {
case SocketOptions.SO_BINDADDR: case SocketOptions.SO_BINDADDR:
@ -404,14 +405,14 @@ class PlainSocketImpl extends SocketImpl
throw new SocketException(x.getMessage()); throw new SocketException(x.getMessage());
} }
case SocketOptions.TCP_NODELAY: case SocketOptions.TCP_NODELAY:
return new Boolean(CIL.unbox_int(socket.GetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay)) != 0); return new Boolean(CIL.unbox_int(socket.GetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Tcp), SocketOptionName.wrap(SocketOptionName.NoDelay))) != 0);
case SocketOptions.SO_KEEPALIVE: case SocketOptions.SO_KEEPALIVE:
return new Boolean(CIL.unbox_int(socket.GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive)) != 0); return new Boolean(CIL.unbox_int(socket.GetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.KeepAlive))) != 0);
case SocketOptions.SO_TIMEOUT: case SocketOptions.SO_TIMEOUT:
return new Integer(CIL.unbox_int(socket.GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout))); return new Integer(CIL.unbox_int(socket.GetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.ReceiveTimeout))));
case SocketOptions.SO_LINGER: case SocketOptions.SO_LINGER:
{ {
system.net.sockets.LingerOption linger = (system.net.sockets.LingerOption)socket.GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger); cli.System.Net.Sockets.LingerOption linger = (cli.System.Net.Sockets.LingerOption)socket.GetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.Linger));
if(linger.get_Enabled()) if(linger.get_Enabled())
{ {
return new Integer(linger.get_LingerTime()); return new Integer(linger.get_LingerTime());
@ -419,29 +420,29 @@ class PlainSocketImpl extends SocketImpl
return Boolean.FALSE; return Boolean.FALSE;
} }
case SocketOptions.SO_OOBINLINE: case SocketOptions.SO_OOBINLINE:
return new Integer(CIL.unbox_int(socket.GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.OutOfBandInline))); return new Integer(CIL.unbox_int(socket.GetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.OutOfBandInline))));
case SocketOptions.SO_SNDBUF: case SocketOptions.SO_SNDBUF:
return new Integer(CIL.unbox_int(socket.GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendBuffer))); return new Integer(CIL.unbox_int(socket.GetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.SendBuffer))));
case SocketOptions.SO_RCVBUF: case SocketOptions.SO_RCVBUF:
return new Integer(CIL.unbox_int(socket.GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer))); return new Integer(CIL.unbox_int(socket.GetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.ReceiveBuffer))));
case SocketOptions.SO_REUSEADDR: case SocketOptions.SO_REUSEADDR:
return new Boolean(CIL.unbox_int(socket.GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress)) != 0); return new Boolean(CIL.unbox_int(socket.GetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.ReuseAddress))) != 0);
case SocketOptions.IP_TOS: case SocketOptions.IP_TOS:
return new Integer(CIL.unbox_int(socket.GetSocketOption(SocketOptionLevel.IP, SocketOptionName.TypeOfService))); return new Integer(CIL.unbox_int(socket.GetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.IP), SocketOptionName.wrap(SocketOptionName.TypeOfService))));
default: default:
throw new Error("Socket.getOption(" + option_id + ") not implemented"); throw new Error("Socket.getOption(" + option_id + ") not implemented");
} }
} }
catch(system.net.sockets.SocketException x) catch(cli.System.Net.Sockets.SocketException x)
{ {
// TODO error handling // TODO error handling
throw new SocketException(x.get_Message()); throw new SocketException(x.getMessage());
} }
} }
private static byte[] getLocalAddress(system.net.sockets.Socket socket) private static byte[] getLocalAddress(cli.System.Net.Sockets.Socket socket)
{ {
int address = (int)((system.net.IPEndPoint)socket.get_LocalEndPoint()).get_Address().get_Address(); int address = (int)((cli.System.Net.IPEndPoint)socket.get_LocalEndPoint()).get_Address().get_Address();
return new byte[] { (byte)address, (byte)(address >> 8), (byte)(address >> 16), (byte)(address >> 24) }; return new byte[] { (byte)address, (byte)(address >> 8), (byte)(address >> 16), (byte)(address >> 24) };
} }

Двоичные данные
classpath/mscorlib.jar

Двоичный файл не отображается.

Просмотреть файл

@ -24,7 +24,7 @@
package sun.misc; package sun.misc;
import system.WeakReference; import cli.System.WeakReference;
public abstract class Ref public abstract class Ref
{ {

Просмотреть файл

@ -4,10 +4,10 @@
<nant buildfile="OpenSystem.Java/OpenSystem.Java.build" /> <nant buildfile="OpenSystem.Java/OpenSystem.Java.build" />
<nant buildfile="IK.VM.NET/ik.vm.net.build" /> <nant buildfile="IK.VM.NET/ik.vm.net.build" />
<nant buildfile="IK.VM.JNI/ik.vm.jni.build" /> <nant buildfile="IK.VM.JNI/ik.vm.jni.build" />
<nant buildfile="netexp/netexp.build" />
<nant buildfile="ikvmc/ikvmc.build" /> <nant buildfile="ikvmc/ikvmc.build" />
<nant buildfile="classpath/classpath.build" /> <nant buildfile="classpath/classpath.build" />
<nant buildfile="ikvm/ikvm.build" /> <nant buildfile="ikvm/ikvm.build" />
<nant buildfile="awt/awt.build" /> <nant buildfile="awt/awt.build" />
<nant buildfile="netexp/netexp.build" />
</target> </target>
</project> </project>

Просмотреть файл

@ -60,6 +60,7 @@ class Compiler
string outputfile = null; string outputfile = null;
string main = null; string main = null;
bool nojni = false; bool nojni = false;
ArrayList classesToExclude = new ArrayList();
ArrayList references = new ArrayList(); ArrayList references = new ArrayList();
ArrayList arglist = GetArgs(args); ArrayList arglist = GetArgs(args);
if(arglist.Count == 0) if(arglist.Count == 0)
@ -77,6 +78,8 @@ class Compiler
Console.Error.WriteLine(" -recurse:<filespec> Recurse directory and include matching files"); Console.Error.WriteLine(" -recurse:<filespec> Recurse directory and include matching files");
Console.Error.WriteLine(" -nojni Do not generate JNI stub for native methods"); Console.Error.WriteLine(" -nojni Do not generate JNI stub for native methods");
Console.Error.WriteLine(" -resource:<name>=<path> Include file as Java resource"); Console.Error.WriteLine(" -resource:<name>=<path> Include file as Java resource");
Console.Error.WriteLine(" -exclude:<filename> A file containing a list of classes to exclude");
Console.Error.WriteLine(" -debug Creates debugging information for the output file");
return 1; return 1;
} }
ArrayList classes = new ArrayList(); ArrayList classes = new ArrayList();
@ -151,6 +154,14 @@ class Compiler
{ {
nojni = true; nojni = true;
} }
else if(s.StartsWith("-exclude:"))
{
ProcessExclusionFile(classesToExclude, s.Substring(9));
}
else if(s == "-debug")
{
JVM.Debug = true;
}
else else
{ {
Console.Error.WriteLine("Warning: Unrecognized option: {0}", s); Console.Error.WriteLine("Warning: Unrecognized option: {0}", s);
@ -190,7 +201,7 @@ class Compiler
} }
try try
{ {
JVM.Compile(outputfile, assemblyname, main, target, (byte[][])classes.ToArray(typeof(byte[])), (string[])references.ToArray(typeof(string)), nojni, resources); JVM.Compile(outputfile, assemblyname, main, target, (byte[][])classes.ToArray(typeof(byte[])), (string[])references.ToArray(typeof(string)), nojni, resources, (string[])classesToExclude.ToArray(typeof(string)));
return 0; return 0;
} }
catch(Exception x) catch(Exception x)
@ -263,14 +274,21 @@ class Compiler
else else
{ {
// include as resource // include as resource
using(FileStream fs = new FileStream(file, FileMode.Open)) try
{ {
byte[] b = new byte[fs.Length]; using(FileStream fs = new FileStream(file, FileMode.Open))
fs.Read(b, 0, b.Length); {
// HACK very lame way to extract the resource name (by chopping off the base directory) byte[] b = new byte[fs.Length];
string name = file.Substring(baseDir.FullName.Length + 1); fs.Read(b, 0, b.Length);
name = name.Replace('\\', '/'); // HACK very lame way to extract the resource name (by chopping off the base directory)
resources.Add(name, b); string name = file.Substring(baseDir.FullName.Length + 1);
name = name.Replace('\\', '/');
resources.Add(name, b);
}
}
catch(UnauthorizedAccessException)
{
Console.Error.WriteLine("Warning: Error reading file {0}: Access Denied", file);
} }
} }
break; break;
@ -289,4 +307,28 @@ class Compiler
Recurse(classes, resources, baseDir, sub, spec); Recurse(classes, resources, baseDir, sub, spec);
} }
} }
//This processes an exclusion file with a single regular expression per line
private static void ProcessExclusionFile(ArrayList classesToExclude, String filename)
{
try
{
using(StreamReader file = new StreamReader(filename))
{
String line;
while((line = file.ReadLine()) != null)
{
line = line.Trim();
if(!line.StartsWith("//") && line.Length != 0)
{
classesToExclude.Add(line);
}
}
}
}
catch(FileNotFoundException)
{
Console.Error.WriteLine("Warning: Could not find exclusion file '{0}'", filename);
}
}
} }

Просмотреть файл

@ -568,7 +568,23 @@ class ClassFileWriter
if(constantValue != null) if(constantValue != null)
{ {
ushort constantValueIndex; ushort constantValueIndex;
if(constantValue is int) if(constantValue is sbyte)
{
constantValueIndex = AddInt((sbyte)constantValue);
}
else if(constantValue is bool)
{
constantValueIndex = AddInt((bool)constantValue ? 1 : 0);
}
else if(constantValue is short)
{
constantValueIndex = AddInt((short)constantValue);
}
else if(constantValue is char)
{
constantValueIndex = AddInt((char)constantValue);
}
else if(constantValue is int)
{ {
constantValueIndex = AddInt((int)constantValue); constantValueIndex = AddInt((int)constantValue);
} }

Просмотреть файл

@ -25,8 +25,9 @@ using System;
using System.Reflection; using System.Reflection;
using System.IO; using System.IO;
using System.Text; using System.Text;
using System.Collections;
using ICSharpCode.SharpZipLib.Zip; using ICSharpCode.SharpZipLib.Zip;
using java.lang;
using java.lang.reflect;
public class NetExp public class NetExp
{ {
@ -39,6 +40,10 @@ public class NetExp
{ {
assembly = Assembly.LoadFrom(args[0]); assembly = Assembly.LoadFrom(args[0]);
} }
else
{
assembly = Assembly.LoadWithPartialName(args[0]);
}
if(assembly == null) if(assembly == null)
{ {
Console.Error.WriteLine("Error: Assembly \"{0}\" not found", args[0]); Console.Error.WriteLine("Error: Assembly \"{0}\" not found", args[0]);
@ -46,299 +51,19 @@ public class NetExp
else else
{ {
zipFile = new ZipOutputStream(new FileStream(assembly.GetName().Name + ".jar", FileMode.Create)); zipFile = new ZipOutputStream(new FileStream(assembly.GetName().Name + ".jar", FileMode.Create));
// HACK if we're doing the "classpath" assembly, also include the remapped types
// java.lang.Object and java.lang.Throwable are automatic, because of the $OverrideStub
if(args[0] == "classpath")
{
ProcessClass(assembly.FullName, Class.forName("java.lang.String"), null);
ProcessClass(assembly.FullName, Class.forName("java.lang.Comparable"), null);
}
ProcessAssembly(assembly); ProcessAssembly(assembly);
zipFile.Close(); zipFile.Close();
} }
} // HACK if we run on the "classpath" assembly, the awt thread gets started,
// so we force an exit here
private static void ProcessAssembly(Assembly assembly) Environment.Exit(0);
{
object[] attribs = assembly.GetCustomAttributes(typeof(CLSCompliantAttribute), false);
bool assemblyIsCLSCompliant = true;
if(attribs.Length != 1)
{
assemblyIsCLSCompliant = false;
Console.Error.WriteLine("Warning: assembly has no (or multiple) CLS compliance attribute");
}
else if(!((CLSCompliantAttribute)attribs[0]).IsCompliant)
{
assemblyIsCLSCompliant = false;
Console.Error.WriteLine("Warning: assembly is marked as non-CLS compliant");
}
foreach(Type t in assembly.GetTypes())
{
bool typeIsCLSCompliant = true;
if(assemblyIsCLSCompliant)
{
attribs = t.GetCustomAttributes(typeof(CLSCompliantAttribute), false);
if(attribs.Length == 1)
{
typeIsCLSCompliant = ((CLSCompliantAttribute)attribs[0]).IsCompliant;
}
}
if(t.IsPublic && typeIsCLSCompliant)
{
ProcessType(t);
}
}
}
private static object UnwrapEnum(object o)
{
// is there a way to generically convert a boxed enum to its boxed underlying value?
Type underlyingType = Enum.GetUnderlyingType(o.GetType());
if (underlyingType == typeof(long))
{
o = (long)o;
}
else if(underlyingType == typeof(int))
{
o = (int)o;
}
else if(underlyingType == typeof(short))
{
o = (short)o;
}
else if (underlyingType == typeof(sbyte))
{
o = (sbyte)o;
}
else if (underlyingType == typeof(ulong))
{
o = (ulong)o;
}
else if (underlyingType == typeof(uint))
{
o = (uint)o;
}
else if (underlyingType == typeof(ushort))
{
o = (ushort)o;
}
else if (underlyingType == typeof(byte))
{
o = (byte)o;
}
else
{
throw new NotImplementedException(o.GetType().Name);
}
return o;
}
private static string ClassName(Type t)
{
if(t == typeof(object))
{
return "java/lang/Object";
}
else if(t == typeof(string))
{
return "java/lang/String";
}
string name = t.FullName;
int lastDot = name.LastIndexOf('.');
if(lastDot > 0)
{
name = name.Substring(0, lastDot).ToLower() + name.Substring(lastDot);
}
return name.Replace('.', '/');
}
// returns the mapped type in signature format (e.g. Ljava/lang/String;)
private static string SigType(Type t)
{
if(t.IsByRef)
{
return "[" + SigType(t.GetElementType());
}
if(t.IsEnum)
{
t = Enum.GetUnderlyingType(t);
}
if(t == typeof(void))
{
return "V";
}
else if(t == typeof(byte) || t == typeof(sbyte))
{
return "B";
}
else if(t == typeof(bool))
{
return "Z";
}
else if(t == typeof(short) || t == typeof(ushort))
{
return "S";
}
else if(t == typeof(char))
{
return "C";
}
else if(t == typeof(int) || t == typeof(uint))
{
return "I";
}
else if(t == typeof(long) || t == typeof(ulong))
{
return "J";
}
else if(t == typeof(float))
{
return "F";
}
else if(t == typeof(double))
{
return "D";
}
else if(t == typeof(IntPtr))
{
// HACK
return "I";
}
else if(t.IsArray)
{
StringBuilder sb = new StringBuilder();
while(t.IsArray)
{
sb.Append('[');
t = t.GetElementType();
}
sb.Append(SigType(t));
return sb.ToString();
}
else if(!t.IsPrimitive)
{
return "L" + ClassName(t) + ";";
}
else
{
throw new NotImplementedException(t.FullName);
}
}
private static void ProcessType(Type type)
{
if(type == typeof(object))// || type == typeof(string))
{
// special case for System.Object & System.String, don't emit those
return;
}
string name = ClassName(type);
if(type == typeof(string))
{
name = "system/String";
}
string super;
if(type.BaseType == null)
{
// in .NET interfaces don't have a baseType, but in Java they "extend" java/lang/Object
super = "java/lang/Object";
}
else
{
if(type == typeof(Exception))
{
super = "java/lang/Throwable";
}
else
{
super = ClassName(type.BaseType);
}
}
Modifiers mods = Modifiers.Public | Modifiers.Super;
if(type.IsInterface)
{
mods |= Modifiers.Interface;
}
if(type.IsSealed)
{
mods |= Modifiers.Final;
}
if(type.IsAbstract)
{
mods |= Modifiers.Abstract;
}
ClassFileWriter f = new ClassFileWriter(mods, name, super);
f.AddStringAttribute("IK.VM.NET.Type", type.AssemblyQualifiedName);
FieldInfo[] fields = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
Hashtable clashtable = new Hashtable();
for(int i = 0; i < fields.Length; i++)
{
if(fields[i].IsPublic || fields[i].IsFamily)
{
object[] attribs = fields[i].GetCustomAttributes(typeof(CLSCompliantAttribute), false);
if(attribs.Length == 1 && !((CLSCompliantAttribute)attribs[0]).IsCompliant)
{
// skip non-CLS compliant field
}
else
{
ProcessField(type, f, fields[i], clashtable);
}
}
}
clashtable.Clear();
ConstructorInfo[] constructors = type.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
for(int i = 0; i < constructors.Length; i++)
{
if(constructors[i].IsPublic || constructors[i].IsFamily)
{
object[] attribs = constructors[i].GetCustomAttributes(typeof(CLSCompliantAttribute), false);
if(attribs.Length == 1 && !((CLSCompliantAttribute)attribs[0]).IsCompliant)
{
// skip non-CLS compliant constructor
}
else
{
ProcessMethod(type, f, constructors[i], clashtable);
}
}
}
MethodInfo[] methods = type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly);
for(int i = 0; i < methods.Length; i++)
{
if(methods[i].IsPublic || methods[i].IsFamily)
{
object[] attribs = methods[i].GetCustomAttributes(typeof(CLSCompliantAttribute), false);
if(attribs.Length == 1 && !((CLSCompliantAttribute)attribs[0]).IsCompliant)
{
// skip non-CLS compliant method
}
else
{
ProcessMethod(type, f, methods[i], clashtable);
}
}
}
// for delegates we have to construct the inner interface
if(type.IsSubclassOf(typeof(MulticastDelegate)))
{
InnerClassesAttribute innerclasses = new InnerClassesAttribute(f);
string outer = ClassName(type);
innerclasses.Add(outer + "$Method", outer, "Method", 0x609);
f.AddAttribute(innerclasses);
// now we construct the inner interface type
ClassFileWriter iface = new ClassFileWriter(Modifiers.Interface | Modifiers.Public | Modifiers.Abstract, outer + "$Method", "java/lang/Object");
MethodInfo invoke = type.GetMethod("Invoke");
StringBuilder sb = new StringBuilder();
sb.Append('(');
ParameterInfo[] parameters = invoke.GetParameters();
for(int i = 0; i < parameters.Length; i++)
{
sb.Append(SigType(parameters[i].ParameterType));
}
sb.Append(')');
sb.Append(SigType(invoke.ReturnType));
// TODO IK.VM.NET.Sig must be set here as well
iface.AddMethod(Modifiers.Public | Modifiers.Abstract, "Invoke", sb.ToString());
innerclasses = new InnerClassesAttribute(iface);
innerclasses.Add(outer + "$Method", outer, "Method", 0x609);
iface.AddAttribute(innerclasses);
WriteClass(outer + "$Method.class", iface);
}
WriteClass(name + ".class", f);
} }
private static void WriteClass(string name, ClassFileWriter c) private static void WriteClass(string name, ClassFileWriter c)
@ -347,164 +72,219 @@ public class NetExp
c.Write(zipFile); c.Write(zipFile);
} }
private static void ProcessField(Type type, ClassFileWriter f, FieldInfo fi, Hashtable clashtable) private class MyClassLoader : ClassLoader
{ {
Modifiers access; public Class loadClass(Type type)
if(fi.IsPublic)
{ {
access = Modifiers.Public; return base.loadClass(type.AssemblyQualifiedName);
}
else
{
access = Modifiers.Protected;
}
object v = null;
if(fi.IsLiteral)
{
v = fi.GetValue(null);
if(v is Enum)
{
v = UnwrapEnum(v);
}
if(v is byte)
{
v = (int)(byte)v;
}
else if (v is sbyte)
{
v = (int)(sbyte)v;
}
else if(v is char)
{
v = (int)(char)v;
}
else if(v is short)
{
v = (int)(short)v;
}
else if(v is ushort)
{
v = (int)(ushort)v;
}
else if(v is bool)
{
v = ((bool)v) ? 1 : 0;
}
else if(v is int || v is uint || v is ulong || v is long || v is float || v is double || v is string)
{
}
else
{
throw new NotImplementedException(v.GetType().FullName);
}
access |= Modifiers.Static | Modifiers.Final;
}
else
{
if(fi.IsInitOnly)
{
access |= Modifiers.Final;
}
if(fi.IsStatic)
{
access |= Modifiers.Static;
}
if(type.IsEnum)
{
// we don't want the value__ field
return;
}
}
string sig = SigType(fi.FieldType);
string key = fi.Name + sig;
if(clashtable.ContainsKey(key))
{
// TODO instead of skipping, we should mangle the name
Console.Error.WriteLine("Skipping field " + type.FullName + "." + fi.Name + " (type " + sig + ") because it clashes");
}
else
{
clashtable.Add(key, key);
f.AddField(access, fi.Name, sig, v);
} }
} }
private static void ProcessMethod(Type type, ClassFileWriter f, MethodBase mb, Hashtable clashtable) private static void ProcessAssembly(Assembly assembly)
{ {
Modifiers access = 0; // HACK we use our own class loader to prevent class initialization
if(!mb.IsAbstract) MyClassLoader loader = new MyClassLoader();
foreach(Type t in assembly.GetTypes())
{ {
access = Modifiers.Native; if(t.IsPublic)
{
ProcessClass(assembly.FullName, loader.loadClass(t), null);
}
} }
if(mb.IsPublic) }
private static void ProcessClass(string assemblyName, Class c, Class outer)
{
string name = c.getName().Replace('.', '/');
//Console.WriteLine(name);
string super = null;
if(c.getSuperclass() != null)
{ {
access |= Modifiers.Public; super = c.getSuperclass().getName().Replace('.', '/');
} }
else if(c.isInterface())
{ {
access |= Modifiers.Protected; super = "java/lang/Object";
} }
if(mb.IsFinal || !mb.IsVirtual) ClassFileWriter f = new ClassFileWriter((Modifiers)c.getModifiers(), name, super);
f.AddStringAttribute("IKVM.NET.Assembly", assemblyName);
InnerClassesAttribute innerClassesAttribute = null;
if(outer != null)
{ {
access |= Modifiers.Final; innerClassesAttribute = new InnerClassesAttribute(f);
innerClassesAttribute.Add(name, outer.getName().Replace('.', '/'), null, (ushort)Modifiers.Public);
} }
if(mb.IsStatic) Class[] innerClasses = c.getDeclaredClasses();
for(int i = 0; i < innerClasses.Length; i++)
{ {
access |= Modifiers.Static; Modifiers mods = (Modifiers)innerClasses[i].getModifiers();
if((mods & (Modifiers.Public | Modifiers.Protected)) != 0)
{
if(innerClassesAttribute == null)
{
innerClassesAttribute = new InnerClassesAttribute(f);
}
string namePart = innerClasses[i].getName();
namePart = namePart.Substring(namePart.LastIndexOf('$') + 1);
innerClassesAttribute.Add(innerClasses[i].getName().Replace('.', '/'), name, namePart, (ushort)innerClasses[i].getModifiers());
ProcessClass(assemblyName, innerClasses[i], c);
}
} }
if(mb.IsAbstract) Constructor[] constructors = c.getDeclaredConstructors();
for(int i = 0; i < constructors.Length; i++)
{ {
access |= Modifiers.Abstract; Modifiers mods = (Modifiers)constructors[i].getModifiers();
if((mods & (Modifiers.Public | Modifiers.Protected)) != 0)
{
f.AddMethod(mods | Modifiers.Native, "<init>", MakeSig(constructors[i].getParameterTypes(), java.lang.Void.TYPE));
}
} }
// special case for delegate constructors! Method[] methods = c.getDeclaredMethods();
if(mb.IsConstructor && type.IsSubclassOf(typeof(MulticastDelegate))) for(int i = 0; i < methods.Length; i++)
{ {
access &= ~Modifiers.Final; Modifiers mods = (Modifiers)methods[i].getModifiers();
f.AddMethod(access, "<init>", "(L" + ClassName(type) + "$Method;)V"); if((mods & (Modifiers.Public | Modifiers.Protected)) != 0)
return; {
if((mods & Modifiers.Abstract) == 0)
{
mods |= Modifiers.Native;
}
f.AddMethod(mods, methods[i].getName(), MakeSig(methods[i].getParameterTypes(), methods[i].getReturnType()));
}
} }
// HACK the native signature is really is very lame way of storing the signature Field[] fields = c.getDeclaredFields();
// TODO only store it when it doesn't match the Java sig and split it into parts (instead of one giant string) for(int i = 0; i < fields.Length; i++)
StringBuilder nativesig = new StringBuilder(); {
Modifiers mods = (Modifiers)fields[i].getModifiers();
if((mods & (Modifiers.Public | Modifiers.Protected)) != 0)
{
object constantValue = null;
// HACK we only look for constants on static final fields, to trigger less static initializers
if((mods & (Modifiers.Final | Modifiers.Static)) == (Modifiers.Final | Modifiers.Static))
{
// HACK we use a non-standard API to get constant value
// NOTE we can't use Field.get() because that will run the static initializer and
// also won't allow us to see the difference between constants and blank final fields.
constantValue = NativeCode.java.lang.reflect.Field.getConstant(fields[i]);
if(constantValue != null)
{
if(constantValue is java.lang.Boolean)
{
constantValue = ((java.lang.Boolean)constantValue).booleanValue();
}
else if(constantValue is java.lang.Byte)
{
constantValue = ((java.lang.Byte)constantValue).byteValue();
}
else if(constantValue is java.lang.Short)
{
constantValue = ((java.lang.Short)constantValue).shortValue();
}
else if(constantValue is java.lang.Character)
{
constantValue = ((java.lang.Character)constantValue).charValue();
}
else if(constantValue is java.lang.Integer)
{
constantValue = ((java.lang.Integer)constantValue).intValue();
}
else if(constantValue is java.lang.Long)
{
constantValue = ((java.lang.Long)constantValue).longValue();
}
else if(constantValue is java.lang.Float)
{
constantValue = ((java.lang.Float)constantValue).floatValue();
}
else if(constantValue is java.lang.Double)
{
constantValue = ((java.lang.Double)constantValue).doubleValue();
}
else if(constantValue is string)
{
// no conversion needed
}
else
{
throw new InvalidOperationException();
}
}
}
f.AddField(mods, fields[i].getName(), ClassToSig(fields[i].getType()), constantValue);
}
}
if(innerClassesAttribute != null)
{
f.AddAttribute(innerClassesAttribute);
}
WriteClass(name + ".class", f);
}
private static string MakeSig(Class[] args, Class ret)
{
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.Append('('); sb.Append('(');
ParameterInfo[] parameters = mb.GetParameters(); for(int i = 0; i < args.Length; i++)
string sep = "";
for(int i = 0; i < parameters.Length; i++)
{ {
if(parameters[i].ParameterType.IsPointer) sb.Append(ClassToSig(args[i]));
{
// Java doesn't support pointer parameters
return;
}
sb.Append(SigType(parameters[i].ParameterType));
nativesig.Append(sep).Append(parameters[i].ParameterType.AssemblyQualifiedName);
sep = "|";
} }
sb.Append(')'); sb.Append(')');
if(mb.IsConstructor) sb.Append(ClassToSig(ret));
return sb.ToString();
}
private static string ClassToSig(Class c)
{
if(c.isPrimitive())
{ {
// HACK constructors may not be final in Java if(c == java.lang.Void.TYPE)
access &= ~Modifiers.Final; {
sb.Append('V'); return "V";
}
else if(c == java.lang.Byte.TYPE)
{
return "B";
}
else if(c == java.lang.Boolean.TYPE)
{
return "Z";
}
else if(c == java.lang.Short.TYPE)
{
return "S";
}
else if(c == java.lang.Character.TYPE)
{
return "C";
}
else if(c == java.lang.Integer.TYPE)
{
return "I";
}
else if(c == java.lang.Long.TYPE)
{
return "J";
}
else if(c == java.lang.Float.TYPE)
{
return "F";
}
else if(c == java.lang.Double.TYPE)
{
return "D";
}
else
{
throw new InvalidOperationException();
}
}
else if(c.isArray())
{
return "[" + ClassToSig(c.getComponentType());
} }
else else
{ {
sb.Append(SigType(((MethodInfo)mb).ReturnType)); return "L" + c.getName().Replace('.', '/') + ";";
}
string name = mb.IsConstructor ? "<init>" : mb.Name;
string sig = sb.ToString();
string key = name + sig;
if(clashtable.ContainsKey(key))
{
// TODO instead of skipping, we should mangle the name
Console.Error.WriteLine("Skipping method " + type.FullName + "." + name + sig + " because it clashes");
}
else
{
clashtable.Add(key, key);
f.AddMethod(access, name, sig)
.AddAttribute(new StringAttribute(f.AddUtf8("IK.VM.NET.Sig"), f.AddUtf8(nativesig.ToString())));
} }
} }
} }

Просмотреть файл

@ -6,6 +6,9 @@
<includes name="*.cs" /> <includes name="*.cs" />
</sources> </sources>
<references> <references>
<includes name="../bin/classpath.dll" asis="true" />
<includes name="../bin/ik.vm.net.dll" asis="true" />
<includes name="../bin/OpenSystem.Java.dll" asis="true" />
<includes name="../bin/SharpZipLib.dll" asis="true" /> <includes name="../bin/SharpZipLib.dll" asis="true" />
</references> </references>
</csc> </csc>

Просмотреть файл

@ -84,6 +84,21 @@
AssemblyName = "SharpZipLib" AssemblyName = "SharpZipLib"
HintPath = "..\bin\SharpZipLib.dll" HintPath = "..\bin\SharpZipLib.dll"
/> />
<Reference
Name = "IK.VM.NET"
Project = "{F5C7B588-0403-4AF2-A4DE-5697DE21BC2C}"
Package = "{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"
/>
<Reference
Name = "OpenSystem.Java"
Project = "{13A5BB9F-D5FB-4061-BB0C-A111BE84A978}"
Package = "{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"
/>
<Reference
Name = "classpath"
AssemblyName = "classpath"
HintPath = "..\bin\classpath.dll"
/>
</References> </References>
</Build> </Build>
<Files> <Files>