25using System.Collections.Generic;
26using System.Diagnostics;
33#if IMPORTER || EXPORTER
39using System.Reflection;
40using System.Reflection.Emit;
49 sealed partial class RuntimeManagedJavaType : RuntimeJavaType
52 const string NamePrefix =
"cli.";
54 internal const string DelegateInterfaceSuffix =
"$Method";
55 internal const string AttributeAnnotationSuffix =
"$Annotation";
56 internal const string AttributeAnnotationReturnValueSuffix =
"$__ReturnValue";
57 internal const string AttributeAnnotationMultipleSuffix =
"$__Multiple";
58 internal const string EnumEnumSuffix =
"$__Enum";
59 internal const string GenericEnumEnumTypeName =
"ikvm.internal.EnumEnum`1";
60 internal const string GenericDelegateInterfaceTypeName =
"ikvm.internal.DelegateInterface`1";
61 internal const string GenericAttributeAnnotationTypeName =
"ikvm.internal.AttributeAnnotation`1";
62 internal const string GenericAttributeAnnotationReturnValueTypeName =
"ikvm.internal.AttributeAnnotationReturnValue`1";
63 internal const string GenericAttributeAnnotationMultipleTypeName =
"ikvm.internal.AttributeAnnotationMultiple`1";
66 RuntimeJavaType baseTypeWrapper;
67 RuntimeJavaType[] innerClasses;
68 RuntimeJavaType outerClass;
69 RuntimeJavaType[] interfaces;
78 else if (type.IsNestedPublic)
86 else if (type.IsNestedPrivate)
88 modifiers |= Modifiers.Private |
Modifiers.Static;
90 else if (type.IsNestedFamily || type.IsNestedFamORAssem)
92 modifiers |= Modifiers.Protected |
Modifiers.Static;
94 else if (type.IsNestedAssembly || type.IsNestedFamANDAssem)
103 else if (type.IsAbstract)
107 if (type.IsInterface)
117 internal static string GetName(RuntimeContext context,
Type type)
119 Debug.Assert(!type.Name.EndsWith(
"[]") && !context.AttributeHelper.IsJavaModule(type.Module));
121 var name = type.FullName;
128 if (type.IsGenericType && !type.ContainsGenericParameters)
130 var sb =
new ValueStringBuilder();
131 sb.Append(MangleTypeName(type.GetGenericTypeDefinition().FullName));
134 foreach (var t1
in type.GetGenericArguments())
147 while (ReflectUtil.IsVector(t))
149 t = t.GetElementType();
153 if (RuntimePrimitiveJavaType.IsPrimitiveType(context, t))
155 sb.Append(context.ClassLoaderFactory.GetJavaTypeFromType(t).SigName);
160 if (context.ClassLoaderFactory.IsRemappedType(t) || context.AttributeHelper.IsJavaModule(t.Module))
161 s = context.ClassLoaderFactory.GetJavaTypeFromType(t).Name;
163 s = RuntimeManagedJavaType.GetName(context, t);
167 if (s.IndexOf(
"_$$$_") == -1)
169 s = s.Replace(
"__",
"$$005F$$005F");
170 s = s.Replace(
".",
"__");
181 return sb.ToString();
184 if (context.AttributeHelper.IsNoPackagePrefix(type) && name.IndexOf(
'$') == -1)
185 return name.Replace(
'+',
'$');
187 return MangleTypeName(name);
190 static string MangleTypeName(
string name)
192 var sb =
new ValueStringBuilder(NamePrefix.Length + name.Length);
193 sb.Append(NamePrefix);
197 for (
int i = 0; i < name.Length; i++)
200 if (c ==
'+' && !escape && (sb.Length == 0 || sb[sb.Length - 1] !=
'$'))
205 else if (
"_0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".IndexOf(c) != -1 || (c ==
'.' && !escape && !nested))
212 sb.Append(
string.Format(
"{0:X4}", (
int)c));
224 return sb.ToString();
232 internal static string DemangleTypeName(
string name)
234 if (name.StartsWith(NamePrefix, StringComparison.Ordinal) ==
false)
235 return name.Replace(
'$',
'+');
237 var sb =
new ValueStringBuilder(name.Length - NamePrefix.Length);
238 for (
int i = NamePrefix.Length; i < name.Length; i++)
243 if (i + 1 < name.Length && name[i + 1] !=
'$')
250 if (i + 5 > name.Length)
253 int digit0 =
"0123456789ABCDEF".IndexOf(name[++i]);
254 int digit1 =
"0123456789ABCDEF".IndexOf(name[++i]);
255 int digit2 =
"0123456789ABCDEF".IndexOf(name[++i]);
256 int digit3 =
"0123456789ABCDEF".IndexOf(name[++i]);
257 if (digit0 == -1 || digit1 == -1 || digit2 == -1 || digit3 == -1)
260 sb.Append((
char)((digit0 << 12) + (digit1 << 8) + (digit2 << 4) + digit3));
269 return sb.ToString();
274 internal static bool IsAllowedOutside(
Type type)
279#if !FIRST_PASS && !IMPORTER && !EXPORTER
280 if (type.Assembly == typeof(RuntimeManagedJavaType).
Assembly)
287 internal static RuntimeJavaType Create(RuntimeContext context,
Type type,
string name)
289 if (type.ContainsGenericParameters)
291 return new OpenGenericJavaType(context, type, name);
295 return new RuntimeManagedJavaType(context, type, name);
305 RuntimeManagedJavaType(RuntimeContext context,
Type type,
string name) :
308 Debug.Assert(!type.IsByRef, type.FullName);
309 Debug.Assert(!type.IsPointer, type.FullName);
310 Debug.Assert(!type.Name.EndsWith(
"[]"), type.FullName);
311 Debug.Assert(type is not TypeBuilder, type.FullName);
317 internal override RuntimeJavaType BaseTypeWrapper => baseTypeWrapper ??= Context.ManagedJavaTypeFactory.GetBaseJavaType(type);
319 internal override RuntimeClassLoader ClassLoader => type.IsGenericType ? Context.ClassLoaderFactory.GetGenericClassLoader(
this) : Context.AssemblyClassLoaderFactory.FromAssembly(type.Assembly);
321 internal static string GetDelegateInvokeStubName(
Type delegateType)
323 var delegateInvoke = delegateType.GetMethod(
"Invoke");
324 var parameters = delegateInvoke.GetParameters();
327 for (
int i = 0; i < parameters.Length; i++)
328 if (parameters[i].ParameterType.IsByRef)
329 name = (name ??
"<Invoke>") +
"_" + i;
331 return name ??
"Invoke";
340 Type javaUnderlyingType;
359 javaUnderlyingType = underlyingType;
363 var fields = type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Static);
364 var fieldsList =
new List<RuntimeJavaField>();
365 for (
int i = 0; i < fields.Length; i++)
367 if (fields[i].FieldType == type)
369 var name = fields[i].Name;
372 else if (name.StartsWith(
"_") && name.EndsWith(
"Value"))
375 var val =
EnumHelper.GetPrimitiveValue(Context, underlyingType, fields[i].GetRawConstantValue());
379 fieldsList.Add(
new EnumValueJavaField(
this, fieldType));
380 SetFields(fieldsList.ToArray());
385 var fieldsList =
new List<RuntimeJavaField>();
386 var fields = type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance);
387 for (
int i = 0; i < fields.Length; i++)
390 if (fields[i].FieldType.IsPointer)
397 fieldsList.Add(CreateFieldWrapperDotNet(Context.
AttributeHelper.GetModifiers(fields[i],
true).Modifiers, fields[i].Name, fields[i].FieldType, fields[i]));
400 SetFields(fieldsList.ToArray());
402 var methodsList =
new Dictionary<string, RuntimeJavaMethod>();
405 if (IsDelegate(Context, type))
407 var iface = InnerClasses[0];
408 var mw =
new DelegateJavaMethod(
this, (DelegateInnerClassJavaType)iface);
409 methodsList.Add(mw.Name + mw.Signature, mw);
414 methodsList.Add(
"<init>()V",
new MulticastDelegateCtorJavaMethod(
this));
416 var constructors = type.GetConstructors(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance);
417 for (
int i = 0; i < constructors.Length; i++)
419 if (MakeMethodDescriptor(constructors[i], out var name, out var sig, out var args, out var ret))
421 var mw = CreateMethodWrapper(name, sig, args, ret, constructors[i],
false);
422 var key = mw.Name + mw.Signature;
423 if (methodsList.ContainsKey(key) ==
false)
424 methodsList.Add(key, mw);
428 if (type.IsValueType && !methodsList.ContainsKey(
"<init>()V"))
431 methodsList.Add(
"<init>()V",
new ValueTypeDefaultCtorJavaMethod(
this));
434 var methods = type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance);
435 for (
int i = 0; i < methods.Length; i++)
437 if (methods[i].IsStatic && type.IsInterface)
443 if (MakeMethodDescriptor(methods[i], out var name, out var sig, out var args, out var ret))
445 if (!methods[i].IsStatic && !methods[i].IsPrivate && BaseTypeWrapper !=
null)
447 var baseMethod = BaseTypeWrapper.GetMethod(name, sig,
true);
448 if (baseMethod !=
null && baseMethod.IsFinal && !baseMethod.IsStatic && !baseMethod.IsPrivate)
452 var mw = CreateMethodWrapper(name, sig, args, ret, methods[i],
false);
453 var key = mw.Name + mw.Signature;
454 methodsList.TryGetValue(key, out var existing);
456 if (existing ==
null || existing is ByRefJavaMethod)
457 methodsList[key] = mw;
459 else if (methods[i].IsAbstract)
461 SetHasUnsupportedAbstractMethods();
468 if (!type.IsInterface)
470 var interfaces = type.GetInterfaces();
471 for (
int i = 0; i < interfaces.Length; i++)
475 if (interfaces[i].IsVisible)
480 foreach (var mw
in tw.GetMethods())
484 InterfaceMethodStubHelper(methodsList, mw.GetMethod(), mw.Name, mw.Signature, mw.GetParameters(), mw.ReturnType);
488 var map = type.GetInterfaceMap(interfaces[i]);
489 for (
int j = 0; j < map.InterfaceMethods.Length; j++)
491 if (map.TargetMethods[j] ==
null || ((!map.TargetMethods[j].IsPublic || map.TargetMethods[j].Name != map.InterfaceMethods[j].Name) && map.TargetMethods[j].DeclaringType == type))
493 if (MakeMethodDescriptor(map.InterfaceMethods[j], out var name, out var sig, out var args, out var ret))
495 InterfaceMethodStubHelper(methodsList, map.InterfaceMethods[j], name, sig, args, ret);
506 if (Context.
ClassLoaderFactory.IsRemappedType(type) && !type.IsSealed && !type.IsInterface)
508 var baseTypeWrapper = BaseTypeWrapper;
510 while (baseTypeWrapper !=
null)
512 foreach (var m
in baseTypeWrapper.GetMethods())
514 if (!m.IsStatic && !m.IsFinal && (m.IsPublic || m.IsProtected) && m.Name !=
"<init>")
516 var key = m.Name + m.Signature;
517 if (!methodsList.ContainsKey(key))
521 if (m.Name ==
"finalize" && m.Signature ==
"()V")
523 methodsList.Add(key,
new FinalizeJavaMethod(
this));
525 else if (m.Name ==
"clone" && m.Signature ==
"()Ljava.lang.Object;")
527 methodsList.Add(key,
new CloneJavaMethod(
this));
532 throw new InvalidOperationException(
"Missing protected method support for " + baseTypeWrapper.Name +
"::" + m.Name + m.Signature);
537 methodsList.Add(key,
new BaseFinalJavaMethod(
this, m));
543 baseTypeWrapper = baseTypeWrapper.BaseTypeWrapper;
547#if !IMPORTER && !EXPORTER && !FIRST_PASS
550 if (typeof(Exception).IsAssignableFrom(type) && !typeof(
java.io.Serializable.__Interface).IsAssignableFrom(type) && !methodsList.ContainsKey(
"writeReplace()Ljava.lang.Object;"))
552 methodsList.Add(
"writeReplace()Ljava.lang.Object;",
new ExceptionWriteReplaceJavaMethod(
this));
558 methodsList.Values.CopyTo(methodArray, 0);
559 SetMethods(methodArray);
563 void InterfaceMethodStubHelper(Dictionary<string, RuntimeJavaMethod> methodsList,
MethodBase method,
string name,
string sig, RuntimeJavaType[] args, RuntimeJavaType ret)
565 var key = name + sig;
566 methodsList.TryGetValue(key, out var existing);
567 if (existing ==
null && BaseTypeWrapper !=
null)
569 var baseMethod = BaseTypeWrapper.GetMethod(name, sig,
true);
570 if (baseMethod !=
null && !baseMethod.IsStatic && baseMethod.IsPublic)
574 if (existing ==
null || existing is ByRefJavaMethod || existing.IsStatic || !existing.IsPublic)
579 methodsList[key] = CreateMethodWrapper(name, sig, args, ret, method,
true);
583 internal static bool IsUnsupportedAbstractMethod(
MethodBase mb)
588 if (mi.ReturnType.IsByRef || IsPointerType(mi.ReturnType) || mb.IsGenericMethodDefinition)
591 foreach (var p
in mi.GetParameters())
592 if (p.ParameterType.IsByRef || IsPointerType(p.ParameterType))
599 static bool IsPointerType(
Type type)
601 while (type.HasElementType)
606 type = type.GetElementType();
609#if IMPORTER || EXPORTER
610 return type.IsFunctionPointer;
613 return type.IsFunctionPointer;
620 bool MakeMethodDescriptor(
MethodBase mb, out
string name, out
string sig, out RuntimeJavaType[] args, out RuntimeJavaType ret)
622 if (mb.IsGenericMethodDefinition)
631 var sb =
new ValueStringBuilder();
633 var parameters = mb.GetParameters();
634 args =
new RuntimeJavaType[parameters.Length];
635 for (
int i = 0; i < parameters.Length; i++)
637 var type = parameters[i].ParameterType;
638 if (IsPointerType(type))
649 type = RuntimeArrayJavaType.MakeArrayType(type.GetElementType(), 1);
664 sb.Append(tw.SigName);
670 name = mb.IsStatic ?
"<clinit>" :
"<init>";
671 sb.Append(ret.SigName);
678 if (IsPointerType(type) || type.IsByRef)
686 sb.Append(ret.SigName);
693 internal override RuntimeJavaType[] Interfaces => interfaces ??= GetImplementedInterfacesAsTypeWrappers(Context, type);
695 static bool IsAttribute(RuntimeContext context,
Type type)
697 if (!type.IsAbstract && type.IsSubclassOf(context.Types.Attribute) && type.IsVisible)
712 AttributeAnnotationJavaType.GetConstructors(context, type, out var defCtor, out var singleOneArgCtor);
713 return defCtor !=
null || singleOneArgCtor !=
null;
719 static bool IsDelegate(RuntimeContext context,
Type type)
725 if (!type.IsAbstract && type.IsSubclassOf(context.Types.MulticastDelegate) && type.IsVisible)
727 var invoke = type.GetMethod(
"Invoke");
730 foreach (var p
in invoke.GetParameters())
733 if (IsPointerType(p.ParameterType))
737 return !IsPointerType(invoke.ReturnType);
744 internal override RuntimeJavaType[] InnerClasses => innerClasses ??= GetInnerClasses();
746 RuntimeJavaType[] GetInnerClasses()
748 var nestedTypes = type.GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic);
749 var list =
new List<RuntimeJavaType>(nestedTypes.Length);
750 for (
int i = 0; i < nestedTypes.Length; i++)
751 if (!nestedTypes[i].IsGenericTypeDefinition)
754 if (IsDelegate(Context, type))
755 list.Add(ClassLoader.RegisterInitiatingLoader(
new DelegateInnerClassJavaType(Context,
Name + DelegateInterfaceSuffix, type)));
757 if (IsAttribute(Context, type))
758 list.Add(ClassLoader.RegisterInitiatingLoader(
new AttributeAnnotationJavaType(Context,
Name + AttributeAnnotationSuffix, type)));
760 if (type.IsEnum && type.IsVisible)
761 list.Add(ClassLoader.RegisterInitiatingLoader(
new EnumEnumJavaType(Context,
Name + EnumEnumSuffix, type)));
763 return list.ToArray();
766 internal override bool IsFakeTypeContainer => IsDelegate(Context, type) || IsAttribute(Context, type) || (type.IsEnum && type.IsVisible);
768 internal override RuntimeJavaType DeclaringTypeWrapper
772 if (outerClass ==
null)
774 var outer = type.DeclaringType;
775 if (outer !=
null && !type.IsGenericType)
785 RuntimeJavaField CreateFieldWrapperDotNet(
Modifiers modifiers,
string name,
Type fieldType,
FieldInfo field)
789 return new RuntimeConstantJavaField(
this, type, name, type.SigName, modifiers, field,
null,
MemberFlags.None);
791 return RuntimeJavaField.Create(
this, type, field, name, type.SigName,
new ExModifiers(modifiers,
false));
799 static bool IsRemappedImplDerived(RuntimeContext context,
Type type)
801 for (; type !=
null; type = type.BaseType)
802 if (!context.ClassLoaderFactory.IsRemappedType(type) && context.ClassLoaderFactory.GetJavaTypeFromType(type).IsRemapped)
808 RuntimeJavaMethod CreateMethodWrapper(
string name,
string sig, RuntimeJavaType[] argTypeWrappers, RuntimeJavaType retTypeWrapper,
MethodBase mb,
bool privateInterfaceImplHack)
811 var mods = exmods.Modifiers;
813 if (name ==
"Finalize" && sig ==
"()V" && !mb.IsStatic && IsRemappedImplDerived(Context, TypeAsBaseType))
817 mw.SetDeclaredExceptions([
"java.lang.Throwable"]);
821 var parameters = mb.GetParameters();
822 var args =
new Type[parameters.Length];
823 var hasByRefArgs =
false;
824 bool[] byrefs =
null;
826 for (
int i = 0; i < parameters.Length; i++)
828 args[i] = parameters[i].ParameterType;
829 if (parameters[i].ParameterType.IsByRef)
831 byrefs ??=
new bool[args.Length];
837 if (privateInterfaceImplHack)
848 return new ByRefJavaMethod(args, byrefs,
this, name, sig, mb, retTypeWrapper, argTypeWrappers, mods,
false);
852 return new RuntimeTypicalJavaMethod(
this, name, sig, mb, retTypeWrapper, argTypeWrappers, mods,
MemberFlags.None);
856 internal override Type TypeAsTBD => type;
858 internal override bool IsRemapped => Context.ClassLoaderFactory.IsRemappedType(type);
862 internal override void EmitInstanceOf(CodeEmitter ilgen)
867 var method = shadow.TypeAsBaseType.GetMethod(
"__<instanceof>");
870 ilgen.Emit(OpCodes.Call, method);
875 ilgen.Emit_instanceof(type);
878 internal override void EmitCheckcast(CodeEmitter ilgen)
883 var method = shadow.TypeAsBaseType.GetMethod(
"__<checkcast>");
886 ilgen.Emit(OpCodes.Call, method);
890 ilgen.EmitCastclass(type);
895 internal override MethodParametersEntry[] GetMethodParameters(RuntimeJavaMethod mw)
897 var mb = mw.GetMethod();
901 var parameters = mb.GetParameters();
902 if (parameters.Length == 0)
905 var mp =
new MethodParametersEntry[parameters.Length];
907 for (
int i = 0; i < mp.Length; i++)
909 var name = parameters[i].Name;
910 var empty =
string.IsNullOrEmpty(name);
923#if !IMPORTER && !EXPORTER
925 internal override object[] GetDeclaredAnnotations()
927 return type.GetCustomAttributes(
false);
930 internal override object[] GetFieldAnnotations(RuntimeJavaField fw)
932 var fi = fw.GetField();
936 return fi.GetCustomAttributes(
false);
939 internal override object[] GetMethodAnnotations(RuntimeJavaMethod mw)
941 var mb = mw.GetMethod();
945 return mb.GetCustomAttributes(
false);
948 internal override object[][] GetParameterAnnotations(RuntimeJavaMethod mw)
950 var mb = mw.GetMethod();
954 var parameters = mb.GetParameters();
955 var attribs =
new object[parameters.Length][];
956 for (
int i = 0; i < parameters.Length; i++)
957 attribs[i] = parameters[i].GetCustomAttributes(
false);
963 internal override bool IsFastClassLiteralSafe => type != Context.Types.Void && !type.IsPrimitive && !IsRemapped;
965#if !IMPORTER && !EXPORTER
970 internal override bool IsPackageAccessibleFrom(RuntimeJavaType wrapper)
972 if (wrapper == DeclaringTypeWrapper)
975 if (!base.IsPackageAccessibleFrom(wrapper))
979 for (
Type type = TypeAsTBD; type.IsNested; type = type.DeclaringType)
982 if (!type.IsNestedAssembly && !type.IsNestedFamORAssem && !type.IsNestedPublic)
IKVM.Reflection.Type Type
IKVM.Reflection.Assembly Assembly
IKVM.Reflection.ConstructorInfo ConstructorInfo
IKVM.Reflection.FieldInfo FieldInfo
IKVM.Reflection.MethodInfo MethodInfo
IKVM.Reflection.MethodBase MethodBase
global::java.lang.invoke.LambdaForm.Name Name
AttributeHelper AttributeHelper
Gets the AttributeHelper associated with this instance of the runtime.
Types Types
Gets the Types associated with this instance of the runtime.
RuntimeManagedJavaTypeFactory ManagedJavaTypeFactory
Gets the RuntimeManagedJavaTypeFactory associated with this instance of the runtime.
RuntimePrimitiveJavaTypeFactory PrimitiveJavaTypeFactory
Gets the RuntimePrimitiveJavaTypeFactory associated with this instance of the runtime.
RuntimeClassLoaderFactory ClassLoaderFactory
Gets the RuntimeClassLoaderFactory associated with this instance of the runtime.
RuntimeJavaType GetJavaTypeFromManagedType(Type type)
Gets the RuntimeJavaType associated with the specified managed type, or creates one on demand.
override void LazyPublishMembers()
override string ToString()
MemberFlags
Describes various options applied to a member.