IKVM11  11
Java SE 11 Virtual Machine for .NET
Loading...
Searching...
No Matches
RuntimeJavaType.cs
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2015 Jeroen Frijters
3
4 This software is provided 'as-is', without any express or implied
5 warranty. In no event will the authors be held liable for any damages
6 arising from the use of this software.
7
8 Permission is granted to anyone to use this software for any purpose,
9 including commercial applications, and to alter it and redistribute it
10 freely, subject to the following restrictions:
11
12 1. The origin of this software must not be misrepresented; you must not
13 claim that you wrote the original software. If you use this software
14 in a product, an acknowledgment in the product documentation would be
15 appreciated but is not required.
16 2. Altered source versions must be plainly marked as such, and must not be
17 misrepresented as being the original software.
18 3. This notice may not be removed or altered from any source distribution.
19
20 Jeroen Frijters
21 jeroen@frijters.net
22
23*/
24using System;
25using System.Collections.Generic;
26using System.Diagnostics;
27
28using IKVM.Attributes;
31
32
33#if IMPORTER || EXPORTER
34using IKVM.Reflection;
36
37using Type = IKVM.Reflection.Type;
38#else
39using System.Reflection;
40using System.Reflection.Emit;
41#endif
42
43#if IMPORTER
45#endif
46
47namespace IKVM.Runtime
48{
49
53 internal abstract class RuntimeJavaType
54 {
55
56 internal const Modifiers UnloadableModifiersHack = Modifiers.Final | Modifiers.Interface | Modifiers.Private;
57 internal const Modifiers VerifierTypeModifiersHack = Modifiers.Final | Modifiers.Interface;
58
59 static readonly object flagsLock = new object();
60
61 readonly RuntimeContext context;
62 readonly string name; // java name (e.g. java.lang.Object)
63 readonly Modifiers modifiers;
64 TypeFlags flags;
65 RuntimeJavaMethod[] methods;
66 RuntimeJavaField[] fields;
67#if !IMPORTER && !EXPORTER
68 java.lang.Class classObject;
69#endif
70
79 internal RuntimeJavaType(RuntimeContext context, TypeFlags flags, Modifiers modifiers, string name)
80 {
81 Profiler.Count("TypeWrapper");
82
83 this.context = context ?? throw new ArgumentNullException(nameof(context));
84 this.flags = flags;
85 this.modifiers = modifiers;
86 this.name = name == null ? null : string.Intern(name);
87 }
88
92 public RuntimeContext Context => context;
93
97 public virtual IDiagnosticHandler Diagnostics => Context.Diagnostics;
98
99#if EMITTERS
100
101 internal void EmitClassLiteral(CodeEmitter ilgen)
102 {
103 Debug.Assert(!this.IsPrimitive);
104
105 var type = GetClassLiteralType();
106
107 // note that this has to be the same check as in LazyInitClass
108 if (!this.IsFastClassLiteralSafe || IsForbiddenTypeParameterType(type))
109 {
110 int rank = 0;
111 while (ReflectUtil.IsVector(type))
112 {
113 rank++;
114 type = type.GetElementType();
115 }
116 if (rank == 0)
117 {
118 ilgen.Emit(OpCodes.Ldtoken, type);
119 context.CompilerFactory.GetClassFromTypeHandle.EmitCall(ilgen);
120 }
121 else
122 {
123 ilgen.Emit(OpCodes.Ldtoken, type);
124 ilgen.EmitLdc_I4(rank);
125 context.CompilerFactory.GetClassFromTypeHandle2.EmitCall(ilgen);
126 }
127 }
128 else
129 {
130 var classLiteralType = Context.Resolver.ResolveRuntimeType("IKVM.Runtime.ClassLiteral`1").AsReflection().MakeGenericType(type);
131 ilgen.Emit(OpCodes.Call, classLiteralType.GetProperty("Value").GetMethod);
132 }
133 }
134
135#endif
136
137 private Type GetClassLiteralType()
138 {
139 Debug.Assert(!this.IsPrimitive);
140
141 RuntimeJavaType tw = this;
142 if (tw.IsGhostArray)
143 {
144 var rank = tw.ArrayRank;
145 while (tw.IsArray)
146 tw = tw.ElementTypeWrapper;
147
148 return RuntimeArrayJavaType.MakeArrayType(tw.TypeAsTBD, rank);
149 }
150 else
151 {
152 return tw.IsRemapped ? tw.TypeAsBaseType : tw.TypeAsTBD;
153 }
154 }
155
156 bool IsForbiddenTypeParameterType(Type type)
157 {
158 // these are the types that may not be used as a type argument when instantiating a generic type
159 return type == context.Types.Void
160#if NETFRAMEWORK
161 || type == context.Resolver.ResolveCoreType(typeof(ArgIterator).FullName).AsReflection()
162#endif
163 || type == context.Resolver.ResolveCoreType(typeof(RuntimeArgumentHandle).FullName).AsReflection()
164 || type == context.Resolver.ResolveCoreType(typeof(TypedReference).FullName).AsReflection()
165 || type.ContainsGenericParameters
166 || type.IsByRef;
167 }
168
169 internal virtual bool IsFastClassLiteralSafe
170 {
171 get { return false; }
172 }
173
174#if !IMPORTER && !EXPORTER
175
176 internal void SetClassObject(java.lang.Class classObject)
177 {
178 this.classObject = classObject;
179 }
180
181 internal java.lang.Class ClassObject
182 {
183 get
184 {
185 Debug.Assert(!IsUnloadable && !IsVerifierType);
186
187 if (classObject == null)
188 LazyInitClass();
189
190 return classObject;
191 }
192 }
193
194#if !FIRST_PASS
195
196 private java.lang.Class GetPrimitiveClass()
197 {
198 if (this == context.PrimitiveJavaTypeFactory.BYTE)
199 {
200 return java.lang.Byte.TYPE;
201 }
202 else if (this == context.PrimitiveJavaTypeFactory.CHAR)
203 {
204 return java.lang.Character.TYPE;
205 }
206 else if (this == context.PrimitiveJavaTypeFactory.DOUBLE)
207 {
208 return java.lang.Double.TYPE;
209 }
210 else if (this == context.PrimitiveJavaTypeFactory.FLOAT)
211 {
212 return java.lang.Float.TYPE;
213 }
214 else if (this == context.PrimitiveJavaTypeFactory.INT)
215 {
216 return java.lang.Integer.TYPE;
217 }
218 else if (this == context.PrimitiveJavaTypeFactory.LONG)
219 {
220 return java.lang.Long.TYPE;
221 }
222 else if (this == context.PrimitiveJavaTypeFactory.SHORT)
223 {
224 return java.lang.Short.TYPE;
225 }
226 else if (this == context.PrimitiveJavaTypeFactory.BOOLEAN)
227 {
228 return java.lang.Boolean.TYPE;
229 }
230 else if (this == context.PrimitiveJavaTypeFactory.VOID)
231 {
232 return java.lang.Void.TYPE;
233 }
234 else
235 {
236 throw new InvalidOperationException();
237 }
238 }
239#endif
240
241 private void LazyInitClass()
242 {
243 lock (this)
244 {
245 if (classObject == null)
246 {
247 // DynamicTypeWrapper should haved already had SetClassObject explicitly
248 Debug.Assert(!IsDynamic);
249#if !FIRST_PASS
250 java.lang.Class clazz;
251 // note that this has to be the same check as in EmitClassLiteral
252 if (!this.IsFastClassLiteralSafe)
253 {
254 if (this.IsPrimitive)
255 {
256 clazz = GetPrimitiveClass();
257 }
258 else
259 {
260 clazz = new java.lang.Class((java.lang.ClassLoader)null);
261 }
262 }
263 else
264 {
265 Type type = GetClassLiteralType();
266 if (IsForbiddenTypeParameterType(type))
267 {
268 clazz = new java.lang.Class(type);
269 }
270 else
271 {
272 clazz = (java.lang.Class)typeof(ClassLiteral<>).MakeGenericType(type).GetProperty("Value").GetGetMethod().Invoke(null, Array.Empty<object>());
273 }
274 }
275 clazz.typeWrapper = this;
276
277 // MONOBUG Interlocked.Exchange is broken on Mono, so we use CompareExchange
278 System.Threading.Interlocked.CompareExchange(ref classObject, clazz, null);
279#endif
280 }
281 }
282 }
283
284#if __MonoCS__
285 // MONOBUG this method is to work around an mcs bug
286 internal static void SetTypeWrapperHack(object clazz, TypeWrapper type)
287 {
288#if !FIRST_PASS
289 typeof(java.lang.Class).GetField("typeWrapper", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(clazz, type);
290#endif
291 }
292#endif
293
294#if !FIRST_PASS
295
296 private static void ResolvePrimitiveTypeWrapperClasses(RuntimeContext context)
297 {
298 // note that we're evaluating all ClassObject properties for the side effect
299 // (to initialize and associate the ClassObject with the TypeWrapper)
300 if (context.PrimitiveJavaTypeFactory.BYTE.ClassObject == null
301 || context.PrimitiveJavaTypeFactory.CHAR.ClassObject == null
302 || context.PrimitiveJavaTypeFactory.DOUBLE.ClassObject == null
303 || context.PrimitiveJavaTypeFactory.FLOAT.ClassObject == null
304 || context.PrimitiveJavaTypeFactory.INT.ClassObject == null
305 || context.PrimitiveJavaTypeFactory.LONG.ClassObject == null
306 || context.PrimitiveJavaTypeFactory.SHORT.ClassObject == null
307 || context.PrimitiveJavaTypeFactory.BOOLEAN.ClassObject == null
308 || context.PrimitiveJavaTypeFactory.VOID.ClassObject == null)
309 {
310 throw new InvalidOperationException();
311 }
312 }
313#endif
314
315 internal static RuntimeJavaType FromClass(java.lang.Class clazz)
316 {
317#if FIRST_PASS
318 throw new NotImplementedException();
319#else
320 // MONOBUG redundant cast to workaround mcs bug
321 var tw = (RuntimeJavaType)(object)clazz.typeWrapper;
322 if (tw == null)
323 {
324 var type = clazz.type;
325 if (type == null)
326 {
327 ResolvePrimitiveTypeWrapperClasses(JVM.Context);
328 return FromClass(clazz);
329 }
330
331 if (type == typeof(void) || type.IsPrimitive || JVM.Context.ClassLoaderFactory.IsRemappedType(type))
332 tw = JVM.Context.ManagedJavaTypeFactory.GetJavaTypeFromManagedType(type);
333 else
334 tw = JVM.Context.ClassLoaderFactory.GetJavaTypeFromType(type);
335
336 clazz.typeWrapper = tw;
337 }
338
339 return tw;
340#endif
341 }
342
343#endif // !IMPORTER && !EXPORTER
344
345 public override string ToString()
346 {
347 return GetType().Name + "[" + name + "]";
348 }
349
350 // For UnloadableTypeWrapper it tries to load the type through the specified loader
351 // and if that fails it throw a NoClassDefFoundError (not a java.lang.NoClassDefFoundError),
352 // for all other types this is a no-op.
353 internal virtual RuntimeJavaType EnsureLoadable(RuntimeClassLoader loader)
354 {
355 return this;
356 }
357
358 private void SetTypeFlag(TypeFlags flag)
359 {
360 // we use a global lock object, since the chance of contention is very small
361 lock (flagsLock)
362 {
363 flags |= flag;
364 }
365 }
366
367 internal bool HasIncompleteInterfaceImplementation
368 {
369 get
370 {
371 RuntimeJavaType baseWrapper = this.BaseTypeWrapper;
372 return (flags & TypeFlags.HasIncompleteInterfaceImplementation) != 0 || (baseWrapper != null && baseWrapper.HasIncompleteInterfaceImplementation);
373 }
374 }
375
376 internal void SetHasIncompleteInterfaceImplementation()
377 {
378 SetTypeFlag(TypeFlags.HasIncompleteInterfaceImplementation);
379 }
380
381 internal bool HasUnsupportedAbstractMethods
382 {
383 get
384 {
385 foreach (var iface in this.Interfaces)
386 if (iface.HasUnsupportedAbstractMethods)
387 return true;
388
389 var baseWrapper = this.BaseTypeWrapper;
390 return (flags & TypeFlags.HasUnsupportedAbstractMethods) != 0 || (baseWrapper != null && baseWrapper.HasUnsupportedAbstractMethods);
391 }
392 }
393
394 internal void SetHasUnsupportedAbstractMethods()
395 {
396 SetTypeFlag(TypeFlags.HasUnsupportedAbstractMethods);
397 }
398
399 internal virtual bool HasStaticInitializer
400 {
401 get
402 {
403 return (flags & TypeFlags.HasStaticInitializer) != 0;
404 }
405 }
406
407 internal void SetHasStaticInitializer()
408 {
409 SetTypeFlag(TypeFlags.HasStaticInitializer);
410 }
411
412 internal bool HasVerifyError
413 {
414 get
415 {
416 return (flags & TypeFlags.VerifyError) != 0;
417 }
418 }
419
420 internal void SetHasVerifyError()
421 {
422 SetTypeFlag(TypeFlags.VerifyError);
423 }
424
425 internal bool HasClassFormatError
426 {
427 get
428 {
429 return (flags & TypeFlags.ClassFormatError) != 0;
430 }
431 }
432
433 internal void SetHasClassFormatError()
434 {
435 SetTypeFlag(TypeFlags.ClassFormatError);
436 }
437
438 internal virtual bool IsFakeTypeContainer
439 {
440 get
441 {
442 return false;
443 }
444 }
445
446 internal virtual bool IsFakeNestedType
447 {
448 get
449 {
450 return false;
451 }
452 }
453
454 // is this an anonymous class (in the sense of Unsafe.defineAnonymousClass(), not the JLS)
455 internal bool IsUnsafeAnonymous
456 {
457 get { return (flags & TypeFlags.Anonymous) != 0; }
458 }
459
460 // a ghost is an interface that appears to be implemented by a .NET type
461 // (e.g. System.String (aka java.lang.String) appears to implement java.lang.CharSequence,
462 // so java.lang.CharSequence is a ghost)
463 internal virtual bool IsGhost
464 {
465 get
466 {
467 return false;
468 }
469 }
470
471 // is this an array type of which the ultimate element type is a ghost?
472 internal bool IsGhostArray
473 {
474 get
475 {
476 return !IsUnloadable && IsArray && (ElementTypeWrapper.IsGhost || ElementTypeWrapper.IsGhostArray);
477 }
478 }
479
480 internal virtual FieldInfo GhostRefField
481 {
482 get
483 {
484 throw new InvalidOperationException();
485 }
486 }
487
488 internal virtual bool IsRemapped
489 {
490 get
491 {
492 return false;
493 }
494 }
495
496 internal bool IsArray
497 {
498 get
499 {
500 return name != null && name[0] == '[';
501 }
502 }
503
504 // NOTE for non-array types this returns 0
505 internal int ArrayRank
506 {
507 get
508 {
509 int i = 0;
510 if (name != null)
511 {
512 while (name[i] == '[')
513 {
514 i++;
515 }
516 }
517 return i;
518 }
519 }
520
521 internal virtual RuntimeJavaType GetUltimateElementTypeWrapper()
522 {
523 throw new InvalidOperationException();
524 }
525
526 internal bool IsNonPrimitiveValueType
527 {
528 get
529 {
530 return this != context.VerifierJavaTypeFactory.Null && !IsPrimitive && !IsGhost && TypeAsTBD.IsValueType;
531 }
532 }
533
534 internal bool IsPrimitive
535 {
536 get
537 {
538 return name == null;
539 }
540 }
541
542 internal bool IsWidePrimitive
543 {
544 get
545 {
546 return this == context.PrimitiveJavaTypeFactory.LONG || this == context.PrimitiveJavaTypeFactory.DOUBLE;
547 }
548 }
549
550 internal bool IsIntOnStackPrimitive
551 {
552 get
553 {
554 return name == null &&
555 (this == context.PrimitiveJavaTypeFactory.BOOLEAN ||
556 this == context.PrimitiveJavaTypeFactory.BYTE ||
557 this == context.PrimitiveJavaTypeFactory.CHAR ||
558 this == context.PrimitiveJavaTypeFactory.SHORT ||
559 this == context.PrimitiveJavaTypeFactory.INT);
560 }
561 }
562
563 private static bool IsJavaPrimitive(RuntimeContext context, Type type)
564 {
565 return type == context.PrimitiveJavaTypeFactory.BOOLEAN.TypeAsTBD
566 || type == context.PrimitiveJavaTypeFactory.BYTE.TypeAsTBD
567 || type == context.PrimitiveJavaTypeFactory.CHAR.TypeAsTBD
568 || type == context.PrimitiveJavaTypeFactory.DOUBLE.TypeAsTBD
569 || type == context.PrimitiveJavaTypeFactory.FLOAT.TypeAsTBD
570 || type == context.PrimitiveJavaTypeFactory.INT.TypeAsTBD
571 || type == context.PrimitiveJavaTypeFactory.LONG.TypeAsTBD
572 || type == context.PrimitiveJavaTypeFactory.SHORT.TypeAsTBD
573 || type == context.PrimitiveJavaTypeFactory.VOID.TypeAsTBD;
574 }
575
576 internal bool IsBoxedPrimitive
577 {
578 get
579 {
580 return !IsPrimitive && IsJavaPrimitive(Context, TypeAsSignatureType);
581 }
582 }
583
584 internal bool IsErasedOrBoxedPrimitiveOrRemapped
585 {
586 get
587 {
588 bool erased = IsUnloadable || IsGhostArray;
589 return erased || IsBoxedPrimitive || (IsRemapped && this is RuntimeManagedJavaType);
590 }
591 }
592
593 internal bool IsUnloadable
594 {
595 get
596 {
597 // NOTE we abuse modifiers to note unloadable classes
598 return modifiers == UnloadableModifiersHack;
599 }
600 }
601
602 internal bool IsVerifierType
603 {
604 get
605 {
606 // NOTE we abuse modifiers to note verifier types
607 return modifiers == VerifierTypeModifiersHack;
608 }
609 }
610
611 internal virtual bool IsMapUnsafeException
612 {
613 get
614 {
615 return false;
616 }
617 }
618
619 internal Modifiers Modifiers
620 {
621 get
622 {
623 return modifiers;
624 }
625 }
626
627 // since for inner classes, the modifiers returned by Class.getModifiers are different from the actual
628 // modifiers (as used by the VM access control mechanism), we have this additional property
629 internal virtual Modifiers ReflectiveModifiers
630 {
631 get
632 {
633 return modifiers;
634 }
635 }
636
637 internal bool IsInternal
638 {
639 get
640 {
641 return (flags & TypeFlags.InternalAccess) != 0;
642 }
643 }
644
645 internal bool IsPublic
646 {
647 get
648 {
649 return (modifiers & Modifiers.Public) != 0;
650 }
651 }
652
653 internal bool IsAbstract
654 {
655 get
656 {
657 // interfaces don't need to marked abstract explicitly (and javac 1.1 didn't do it)
658 return (modifiers & (Modifiers.Abstract | Modifiers.Interface)) != 0;
659 }
660 }
661
662 internal bool IsFinal
663 {
664 get
665 {
666 return (modifiers & Modifiers.Final) != 0;
667 }
668 }
669
670 internal bool IsInterface
671 {
672 get
673 {
674 Debug.Assert(!IsUnloadable && !IsVerifierType);
675 return (modifiers & Modifiers.Interface) != 0;
676 }
677 }
678
679 // this exists because interfaces and arrays of interfaces are treated specially
680 // by the verifier, interfaces don't have a common base (other than java.lang.Object)
681 // so any object reference or object array reference can be used where an interface
682 // or interface array reference is expected (the compiler will insert the required casts).
683 internal bool IsInterfaceOrInterfaceArray
684 {
685 get
686 {
687 RuntimeJavaType tw = this;
688 while (tw.IsArray)
689 {
690 tw = tw.ElementTypeWrapper;
691 }
692 return tw.IsInterface;
693 }
694 }
695
699 internal abstract RuntimeClassLoader ClassLoader { get; }
700
707 internal RuntimeJavaField GetFieldWrapper(string fieldName, string fieldSig)
708 {
709 foreach (var fw in GetFields())
710 if (fw.Name == fieldName && fw.Signature == fieldSig)
711 return fw;
712
713 foreach (var iface in Interfaces)
714 {
715 var fw = iface.GetFieldWrapper(fieldName, fieldSig);
716 if (fw != null)
717 return fw;
718 }
719
720 var baseWrapper = BaseTypeWrapper;
721 if (baseWrapper != null)
722 return baseWrapper.GetFieldWrapper(fieldName, fieldSig);
723
724 return null;
725 }
726
727 protected virtual void LazyPublishMembers()
728 {
729 methods ??= Array.Empty<RuntimeJavaMethod>();
730 fields ??= Array.Empty<RuntimeJavaField>();
731 }
732
733 protected virtual void LazyPublishMethods()
734 {
735 LazyPublishMembers();
736 }
737
738 protected virtual void LazyPublishFields()
739 {
740 LazyPublishMembers();
741 }
742
747 internal RuntimeJavaMethod[] GetMethods()
748 {
749 if (methods == null)
750 {
751 lock (this)
752 {
753 if (methods == null)
754 {
755#if IMPORTER
756 if (IsUnloadable || !CheckMissingBaseTypes(Context, TypeAsBaseType))
757 return methods = Array.Empty<RuntimeJavaMethod>();
758#endif
759 LazyPublishMethods();
760 }
761 }
762 }
763
764 return methods;
765 }
766
771 internal RuntimeJavaField[] GetFields()
772 {
773 if (fields == null)
774 {
775 lock (this)
776 {
777 if (fields == null)
778 {
779#if IMPORTER
780 if (IsUnloadable || !CheckMissingBaseTypes(Context, TypeAsBaseType))
781 return fields = Array.Empty<RuntimeJavaField>();
782#endif
783
784 LazyPublishFields();
785 }
786 }
787 }
788
789 return fields;
790 }
791
792#if IMPORTER
793
794 private static bool CheckMissingBaseTypes(RuntimeContext context, Type type)
795 {
796 while (type != null)
797 {
798 if (type.__ContainsMissingType)
799 {
800 context.StaticCompiler.IssueMissingTypeMessage(type);
801 return false;
802 }
803 bool ok = true;
804 foreach (Type iface in type.__GetDeclaredInterfaces())
805 {
806 ok &= CheckMissingBaseTypes(context, iface);
807 }
808 if (!ok)
809 {
810 return false;
811 }
812 type = type.BaseType;
813 }
814 return true;
815 }
816
817#endif
818
826 internal RuntimeJavaMethod GetMethod(string name, string desc, bool inherit)
827 {
828 // ensure params are interned
829 name = string.Intern(name);
830 desc = string.Intern(desc);
831
832 // scan for method with matching name and descriptor
833 foreach (var method in GetMethods())
834 if (ReferenceEquals(method.Name, name) && ReferenceEquals(method.Signature, desc))
835 return method;
836
837 var baseWrapper = BaseTypeWrapper;
838 if (inherit && baseWrapper != null)
839 return baseWrapper.GetMethod(name, desc, inherit);
840
841 return null;
842 }
843
844 internal RuntimeJavaMethod GetInterfaceMethod(string name, string sig)
845 {
846 var method = GetMethod(name, sig, false);
847 if (method != null)
848 {
849 return method;
850 }
851
852 var interfaces = Interfaces;
853 for (int i = 0; i < interfaces.Length; i++)
854 {
855 method = interfaces[i].GetInterfaceMethod(name, sig);
856 if (method != null)
857 {
858 return method;
859 }
860 }
861
862 return null;
863 }
864
865 internal void SetMethods(RuntimeJavaMethod[] methods)
866 {
867 Debug.Assert(methods != null);
868 System.Threading.Thread.MemoryBarrier();
869 this.methods = methods;
870 }
871
872 internal void SetFields(RuntimeJavaField[] fields)
873 {
874 Debug.Assert(fields != null);
875 System.Threading.Thread.MemoryBarrier();
876 this.fields = fields;
877 }
878
879 internal string Name => name;
880
884 internal virtual string SigName => "L" + Name + ";";
885
886 // returns true iff wrapper is allowed to access us
887 internal bool IsAccessibleFrom(RuntimeJavaType wrapper)
888 {
889 return IsPublic
890 || (IsInternal && InternalsVisibleTo(wrapper))
891 || IsPackageAccessibleFrom(wrapper);
892 }
893
894 internal bool InternalsVisibleTo(RuntimeJavaType wrapper)
895 {
896 return ClassLoader.InternalsVisibleToImpl(this, wrapper);
897 }
898
899 internal virtual bool IsPackageAccessibleFrom(RuntimeJavaType wrapper)
900 {
901 if (MatchingPackageNames(name, wrapper.name))
902 {
903#if IMPORTER
904 ImportClassLoader ccl = ClassLoader as ImportClassLoader;
905 if (ccl != null)
906 {
907 // this is a hack for multi target -sharedclassloader compilation
908 // (during compilation we have multiple CompilerClassLoader instances to represent the single shared runtime class loader)
909 return ccl.IsEquivalentTo(wrapper.ClassLoader);
910 }
911#endif
912 return ClassLoader == wrapper.ClassLoader;
913 }
914 else
915 {
916 return false;
917 }
918 }
919
920 static bool MatchingPackageNames(string name1, string name2)
921 {
922 int index1 = name1.LastIndexOf('.');
923 int index2 = name2.LastIndexOf('.');
924 if (index1 == -1 && index2 == -1)
925 return true;
926
927 // for array types we need to skip the brackets
928 int skip1 = 0;
929 int skip2 = 0;
930 while (name1[skip1] == '[')
931 {
932 skip1++;
933 }
934 while (name2[skip2] == '[')
935 {
936 skip2++;
937 }
938 if (skip1 > 0)
939 {
940 // skip over the L that follows the brackets
941 skip1++;
942 }
943 if (skip2 > 0)
944 {
945 // skip over the L that follows the brackets
946 skip2++;
947 }
948 if ((index1 - skip1) != (index2 - skip2))
949 {
950 return false;
951 }
952
953 return string.CompareOrdinal(name1, skip1, name2, skip2, index1 - skip1) == 0;
954 }
955
956 internal abstract Type TypeAsTBD
957 {
958 get;
959 }
960
961 internal Type TypeAsSignatureType
962 {
963 get
964 {
965 if (IsUnloadable)
966 return ((RuntimeUnloadableJavaType)this).MissingType ?? context.Types.Object;
967
968 if (IsGhostArray)
969 return RuntimeArrayJavaType.MakeArrayType(context.Types.Object, ArrayRank);
970
971 return TypeAsTBD;
972 }
973 }
974
975 internal Type TypeAsPublicSignatureType => (IsPublic ? this : GetPublicBaseTypeWrapper()).TypeAsSignatureType;
976
977 internal virtual Type TypeAsBaseType => TypeAsTBD;
978
979 internal Type TypeAsLocalOrStackType
980 {
981 get
982 {
983 if (IsUnloadable || IsGhost)
984 return context.Types.Object;
985
986 if (IsNonPrimitiveValueType)
987 {
988 // return either System.ValueType or System.Enum
989 return TypeAsTBD.BaseType;
990 }
991
992 if (IsGhostArray)
993 return RuntimeArrayJavaType.MakeArrayType(context.Types.Object, ArrayRank);
994
995 return TypeAsTBD;
996 }
997 }
998
1000 internal Type TypeAsArrayType
1001 {
1002 get
1003 {
1004 if (IsUnloadable || IsGhost)
1005 return context.Types.Object;
1006
1007 if (IsGhostArray)
1008 return RuntimeArrayJavaType.MakeArrayType(context.Types.Object, ArrayRank);
1009
1010 return TypeAsTBD;
1011 }
1012 }
1013
1014 internal Type TypeAsExceptionType
1015 {
1016 get
1017 {
1018 if (IsUnloadable)
1019 return context.Types.Exception;
1020
1021 return TypeAsTBD;
1022 }
1023 }
1024
1025 internal abstract RuntimeJavaType BaseTypeWrapper
1026 {
1027 get;
1028 }
1029
1030 internal RuntimeJavaType ElementTypeWrapper
1031 {
1032 get
1033 {
1034 Debug.Assert(IsUnloadable == false);
1035 Debug.Assert(this == context.VerifierJavaTypeFactory.Null || IsArray);
1036
1037 if (this == context.VerifierJavaTypeFactory.Null)
1038 {
1039 return context.VerifierJavaTypeFactory.Null;
1040 }
1041
1042 // TODO consider caching the element type
1043 switch (name[1])
1044 {
1045 case '[':
1046 // NOTE this call to LoadClassByDottedNameFast can never fail and will not trigger a class load
1047 // (because the ultimate element type was already loaded when this type was created)
1048 return ClassLoader.TryLoadClassByName(name.Substring(1));
1049 case 'L':
1050 // NOTE this call to LoadClassByDottedNameFast can never fail and will not trigger a class load
1051 // (because the ultimate element type was already loaded when this type was created)
1052 return ClassLoader.TryLoadClassByName(name.Substring(2, name.Length - 3));
1053 case 'Z':
1054 return context.PrimitiveJavaTypeFactory.BOOLEAN;
1055 case 'B':
1056 return context.PrimitiveJavaTypeFactory.BYTE;
1057 case 'S':
1058 return context.PrimitiveJavaTypeFactory.SHORT;
1059 case 'C':
1060 return context.PrimitiveJavaTypeFactory.CHAR;
1061 case 'I':
1062 return context.PrimitiveJavaTypeFactory.INT;
1063 case 'J':
1064 return context.PrimitiveJavaTypeFactory.LONG;
1065 case 'F':
1066 return context.PrimitiveJavaTypeFactory.FLOAT;
1067 case 'D':
1068 return context.PrimitiveJavaTypeFactory.DOUBLE;
1069 default:
1070 throw new InvalidOperationException(name);
1071 }
1072 }
1073 }
1074
1075 internal RuntimeJavaType MakeArrayType(int rank)
1076 {
1077 Debug.Assert(rank != 0);
1078 // NOTE this call to LoadClassByDottedNameFast can never fail and will not trigger a class load
1079 return ClassLoader.TryLoadClassByName(new String('[', rank) + this.SigName);
1080 }
1081
1087 internal bool ImplementsInterface(RuntimeJavaType iface)
1088 {
1089 var self = this;
1090
1091 while (self != null)
1092 {
1093 var interfaces = self.Interfaces;
1094
1095 for (int i = 0; i < interfaces.Length; i++)
1096 {
1097 if (interfaces[i] == iface)
1098 return true;
1099
1100 if (interfaces[i].ImplementsInterface(iface))
1101 return true;
1102 }
1103
1104 self = self.BaseTypeWrapper;
1105 }
1106
1107 return false;
1108 }
1109
1110 internal bool IsSubTypeOf(RuntimeJavaType baseType)
1111 {
1112 // make sure IsSubTypeOf isn't used on primitives
1113 Debug.Assert(!this.IsPrimitive);
1114 Debug.Assert(!baseType.IsPrimitive);
1115 // can't be used on Unloadable
1116 Debug.Assert(!this.IsUnloadable);
1117 Debug.Assert(!baseType.IsUnloadable);
1118
1119 if (baseType.IsInterface)
1120 {
1121 if (baseType == this)
1122 {
1123 return true;
1124 }
1125 return ImplementsInterface(baseType);
1126 }
1127 // NOTE this isn't just an optimization, it is also required when this is an interface
1128 if (baseType == Context.JavaBase.TypeOfJavaLangObject)
1129 {
1130 return true;
1131 }
1132 RuntimeJavaType subType = this;
1133 while (subType != baseType)
1134 {
1135 subType = subType.BaseTypeWrapper;
1136 if (subType == null)
1137 {
1138 return false;
1139 }
1140 }
1141 return true;
1142 }
1143
1144 internal bool IsAssignableTo(RuntimeJavaType wrapper)
1145 {
1146 if (this == wrapper)
1147 {
1148 return true;
1149 }
1150 if (this.IsPrimitive || wrapper.IsPrimitive)
1151 {
1152 return false;
1153 }
1154 if (this == context.VerifierJavaTypeFactory.Null)
1155 {
1156 return true;
1157 }
1158 if (wrapper.IsInterface)
1159 {
1160 return ImplementsInterface(wrapper);
1161 }
1162 int rank1 = this.ArrayRank;
1163 int rank2 = wrapper.ArrayRank;
1164 if (rank1 > 0 && rank2 > 0)
1165 {
1166 rank1--;
1167 rank2--;
1168 RuntimeJavaType elem1 = this.ElementTypeWrapper;
1169 RuntimeJavaType elem2 = wrapper.ElementTypeWrapper;
1170 while (rank1 != 0 && rank2 != 0)
1171 {
1172 elem1 = elem1.ElementTypeWrapper;
1173 elem2 = elem2.ElementTypeWrapper;
1174 rank1--;
1175 rank2--;
1176 }
1177 if (elem1.IsPrimitive || elem2.IsPrimitive)
1178 {
1179 return false;
1180 }
1181 return (!elem1.IsNonPrimitiveValueType && elem1.IsSubTypeOf(elem2));
1182 }
1183 return this.IsSubTypeOf(wrapper);
1184 }
1185
1186#if !IMPORTER && !EXPORTER
1187 internal bool IsInstance(object obj)
1188 {
1189 if (obj != null)
1190 {
1191 RuntimeJavaType thisWrapper = this;
1192 RuntimeJavaType objWrapper = IKVM.Java.Externs.ikvm.runtime.Util.GetTypeWrapperFromObject(Context, obj);
1193 return objWrapper.IsAssignableTo(thisWrapper);
1194 }
1195 return false;
1196 }
1197#endif
1198
1199 internal virtual RuntimeJavaType[] Interfaces => Array.Empty<RuntimeJavaType>();
1200
1201 // NOTE this property can only be called for finished types!
1202 internal virtual RuntimeJavaType[] InnerClasses => Array.Empty<RuntimeJavaType>();
1203
1204 // NOTE this property can only be called for finished types!
1205 internal virtual RuntimeJavaType DeclaringTypeWrapper => null;
1206
1207 internal virtual void Finish()
1208 {
1209
1210 }
1211
1212 internal void LinkAll()
1213 {
1214 if ((flags & TypeFlags.Linked) == 0)
1215 {
1216 RuntimeJavaType tw = BaseTypeWrapper;
1217 if (tw != null)
1218 {
1219 tw.LinkAll();
1220 }
1221 foreach (RuntimeJavaType iface in Interfaces)
1222 {
1223 iface.LinkAll();
1224 }
1225 foreach (RuntimeJavaMethod mw in GetMethods())
1226 {
1227 mw.Link();
1228 }
1229 foreach (RuntimeJavaField fw in GetFields())
1230 {
1231 fw.Link();
1232 }
1233 SetTypeFlag(TypeFlags.Linked);
1234 }
1235 }
1236
1237#if !IMPORTER
1238 [Conditional("DEBUG")]
1239 internal static void AssertFinished(Type type)
1240 {
1241 if (type != null)
1242 {
1243 while (type.HasElementType)
1244 {
1245 type = type.GetElementType();
1246 }
1247 Debug.Assert(!(type is TypeBuilder));
1248 }
1249 }
1250#endif
1251
1252#if !IMPORTER && !EXPORTER
1253
1254 internal void RunClassInit()
1255 {
1256 Type t = IsRemapped ? TypeAsBaseType : TypeAsTBD;
1257 if (t != null)
1258 {
1259 System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(t.TypeHandle);
1260 }
1261 }
1262
1263#endif
1264
1265#if EMITTERS
1266
1267 internal void EmitUnbox(CodeEmitter ilgen)
1268 {
1269 Debug.Assert(this.IsNonPrimitiveValueType);
1270
1271 ilgen.EmitUnboxSpecial(this.TypeAsTBD);
1272 }
1273
1274 internal void EmitBox(CodeEmitter ilgen)
1275 {
1276 Debug.Assert(this.IsNonPrimitiveValueType);
1277
1278 ilgen.Emit(OpCodes.Box, this.TypeAsTBD);
1279 }
1280
1281 internal void EmitConvSignatureTypeToStackType(CodeEmitter ilgen)
1282 {
1283 if (IsUnloadable)
1284 {
1285 }
1286 else if (this == context.PrimitiveJavaTypeFactory.BYTE)
1287 {
1288 ilgen.Emit(OpCodes.Conv_I1);
1289 }
1290 else if (IsNonPrimitiveValueType)
1291 {
1292 EmitBox(ilgen);
1293 }
1294 else if (IsGhost)
1295 {
1296 CodeEmitterLocal local = ilgen.DeclareLocal(TypeAsSignatureType);
1297 ilgen.Emit(OpCodes.Stloc, local);
1298 ilgen.Emit(OpCodes.Ldloca, local);
1299 ilgen.Emit(OpCodes.Ldfld, GhostRefField);
1300 }
1301 }
1302
1303 // NOTE sourceType is optional and only used for interfaces,
1304 // it is *not* used to automatically downcast
1305 internal void EmitConvStackTypeToSignatureType(CodeEmitter ilgen, RuntimeJavaType sourceType)
1306 {
1307 if (!IsUnloadable)
1308 {
1309 if (IsGhost)
1310 {
1311 CodeEmitterLocal local1 = ilgen.DeclareLocal(TypeAsLocalOrStackType);
1312 ilgen.Emit(OpCodes.Stloc, local1);
1313 CodeEmitterLocal local2 = ilgen.DeclareLocal(TypeAsSignatureType);
1314 ilgen.Emit(OpCodes.Ldloca, local2);
1315 ilgen.Emit(OpCodes.Ldloc, local1);
1316 ilgen.Emit(OpCodes.Stfld, GhostRefField);
1317 ilgen.Emit(OpCodes.Ldloca, local2);
1318 ilgen.Emit(OpCodes.Ldobj, TypeAsSignatureType);
1319 }
1320 // because of the way interface merging works, any reference is valid
1321 // for any interface reference
1322 else if (IsInterfaceOrInterfaceArray && (sourceType == null || sourceType.IsUnloadable || !sourceType.IsAssignableTo(this)))
1323 {
1324 ilgen.EmitAssertType(TypeAsTBD);
1325 Profiler.Count("InterfaceDownCast");
1326 }
1327 else if (IsNonPrimitiveValueType)
1328 {
1329 EmitUnbox(ilgen);
1330 }
1331 else if (sourceType != null && sourceType.IsUnloadable)
1332 {
1333 ilgen.Emit(OpCodes.Castclass, TypeAsSignatureType);
1334 }
1335 }
1336 }
1337
1338 internal virtual void EmitCheckcast(CodeEmitter ilgen)
1339 {
1340 if (IsGhost)
1341 {
1342 ilgen.Emit(OpCodes.Dup);
1343 // TODO make sure we get the right "Cast" method and cache it
1344 // NOTE for dynamic ghosts we don't end up here because AotTypeWrapper overrides this method,
1345 // so we're safe to call GetMethod on TypeAsTBD (because it has to be a compiled type, if we're here)
1346 ilgen.Emit(OpCodes.Call, TypeAsTBD.GetMethod("Cast"));
1347 ilgen.Emit(OpCodes.Pop);
1348 }
1349 else if (IsGhostArray)
1350 {
1351 ilgen.Emit(OpCodes.Dup);
1352 // TODO make sure we get the right "CastArray" method and cache it
1353 // NOTE for dynamic ghosts we don't end up here because AotTypeWrapper overrides this method,
1354 // so we're safe to call GetMethod on TypeAsTBD (because it has to be a compiled type, if we're here)
1355 RuntimeJavaType tw = this;
1356 int rank = 0;
1357 while (tw.IsArray)
1358 {
1359 rank++;
1360 tw = tw.ElementTypeWrapper;
1361 }
1362 ilgen.EmitLdc_I4(rank);
1363 ilgen.Emit(OpCodes.Call, tw.TypeAsTBD.GetMethod("CastArray"));
1364 ilgen.Emit(OpCodes.Castclass, RuntimeArrayJavaType.MakeArrayType(context.Types.Object, rank));
1365 }
1366 else
1367 {
1368 ilgen.EmitCastclass(TypeAsTBD);
1369 }
1370 }
1371
1372 internal virtual void EmitInstanceOf(CodeEmitter ilgen)
1373 {
1374 if (IsGhost)
1375 {
1376 // TODO make sure we get the right "IsInstance" method and cache it
1377 // NOTE for dynamic ghosts we don't end up here because DynamicTypeWrapper overrides this method,
1378 // so we're safe to call GetMethod on TypeAsTBD (because it has to be a compiled type, if we're here)
1379 ilgen.Emit(OpCodes.Call, TypeAsTBD.GetMethod("IsInstance"));
1380 }
1381 else if (IsGhostArray)
1382 {
1383 // TODO make sure we get the right "IsInstanceArray" method and cache it
1384 // NOTE for dynamic ghosts we don't end up here because DynamicTypeWrapper overrides this method,
1385 // so we're safe to call GetMethod on TypeAsTBD (because it has to be a compiled type, if we're here)
1386 RuntimeJavaType tw = this;
1387 int rank = 0;
1388 while (tw.IsArray)
1389 {
1390 rank++;
1391 tw = tw.ElementTypeWrapper;
1392 }
1393 ilgen.EmitLdc_I4(rank);
1394 ilgen.Emit(OpCodes.Call, tw.TypeAsTBD.GetMethod("IsInstanceArray"));
1395 }
1396 else
1397 {
1398 ilgen.Emit_instanceof(TypeAsTBD);
1399 }
1400 }
1401
1406 internal virtual void EmitLdind(CodeEmitter il)
1407 {
1408 if (this == context.PrimitiveJavaTypeFactory.BOOLEAN)
1409 il.Emit(OpCodes.Ldind_U1);
1410 else if (this == context.PrimitiveJavaTypeFactory.BYTE)
1411 il.Emit(OpCodes.Ldind_U1);
1412 else if (this == context.PrimitiveJavaTypeFactory.CHAR)
1413 il.Emit(OpCodes.Ldind_U2);
1414 else if (this == context.PrimitiveJavaTypeFactory.SHORT)
1415 il.Emit(OpCodes.Ldind_I2);
1416 else if (this == context.PrimitiveJavaTypeFactory.INT)
1417 il.Emit(OpCodes.Ldind_I4);
1418 else if (this == context.PrimitiveJavaTypeFactory.LONG)
1419 il.Emit(OpCodes.Ldind_I8);
1420 else if (this == context.PrimitiveJavaTypeFactory.FLOAT)
1421 il.Emit(OpCodes.Ldind_R4);
1422 else if (this == context.PrimitiveJavaTypeFactory.DOUBLE)
1423 il.Emit(OpCodes.Ldind_R8);
1424 else
1425 il.Emit(OpCodes.Ldind_Ref);
1426 }
1427
1432 internal virtual void EmitStind(CodeEmitter il)
1433 {
1434 if (this == context.PrimitiveJavaTypeFactory.BOOLEAN)
1435 il.Emit(OpCodes.Stind_I1);
1436 else if (this == context.PrimitiveJavaTypeFactory.BYTE)
1437 il.Emit(OpCodes.Stind_I1);
1438 else if (this == context.PrimitiveJavaTypeFactory.CHAR)
1439 il.Emit(OpCodes.Stind_I2);
1440 else if (this == context.PrimitiveJavaTypeFactory.SHORT)
1441 il.Emit(OpCodes.Stind_I2);
1442 else if (this == context.PrimitiveJavaTypeFactory.INT)
1443 il.Emit(OpCodes.Stind_I4);
1444 else if (this == context.PrimitiveJavaTypeFactory.LONG)
1445 il.Emit(OpCodes.Stind_I8);
1446 else if (this == context.PrimitiveJavaTypeFactory.FLOAT)
1447 il.Emit(OpCodes.Stind_R4);
1448 else if (this == context.PrimitiveJavaTypeFactory.DOUBLE)
1449 il.Emit(OpCodes.Stind_R8);
1450 else
1451 il.Emit(OpCodes.Stind_Ref);
1452 }
1453
1454#endif
1455
1456 // NOTE don't call this method, call MethodWrapper.Link instead
1457 internal virtual MethodBase LinkMethod(RuntimeJavaMethod mw)
1458 {
1459 return mw.GetMethod();
1460 }
1461
1462 // NOTE don't call this method, call FieldWrapper.Link instead
1463 internal virtual FieldInfo LinkField(RuntimeJavaField fw)
1464 {
1465 return fw.GetField();
1466 }
1467
1468#if EMITTERS
1469 internal virtual void EmitRunClassConstructor(CodeEmitter ilgen)
1470 {
1471 }
1472#endif // EMITTERS
1473
1474 internal virtual string GetGenericSignature()
1475 {
1476 return null;
1477 }
1478
1479 internal virtual string GetGenericMethodSignature(RuntimeJavaMethod mw)
1480 {
1481 return null;
1482 }
1483
1484 internal virtual string GetGenericFieldSignature(RuntimeJavaField fw)
1485 {
1486 return null;
1487 }
1488
1489 internal virtual MethodParametersEntry[] GetMethodParameters(RuntimeJavaMethod mw)
1490 {
1491 return null;
1492 }
1493
1494#if !IMPORTER && !EXPORTER
1495 internal virtual string[] GetEnclosingMethod()
1496 {
1497 return null;
1498 }
1499
1500 internal virtual object[] GetDeclaredAnnotations()
1501 {
1502 return null;
1503 }
1504
1505 internal virtual object[] GetMethodAnnotations(RuntimeJavaMethod mw)
1506 {
1507 return null;
1508 }
1509
1510 internal virtual object[][] GetParameterAnnotations(RuntimeJavaMethod mw)
1511 {
1512 return null;
1513 }
1514
1515 internal virtual object[] GetFieldAnnotations(RuntimeJavaField fw)
1516 {
1517 return null;
1518 }
1519
1520 internal virtual string GetSourceFileName()
1521 {
1522 return null;
1523 }
1524
1525 internal virtual int GetSourceLineNumber(MethodBase mb, int ilOffset)
1526 {
1527 return -1;
1528 }
1529
1530 internal virtual object GetAnnotationDefault(RuntimeJavaMethod mw)
1531 {
1532 MethodBase mb = mw.GetMethod();
1533 if (mb != null)
1534 {
1535 object[] attr = mb.GetCustomAttributes(typeof(AnnotationDefaultAttribute), false);
1536 if (attr.Length == 1)
1537 {
1538 return JVM.NewAnnotationElementValue(mw.DeclaringType.ClassLoader.GetJavaClassLoader(), mw.ReturnType.ClassObject, ((AnnotationDefaultAttribute)attr[0]).Value);
1539 }
1540 }
1541 return null;
1542 }
1543#endif // !IMPORTER && !EXPORTER
1544
1545 internal virtual Annotation Annotation => null;
1546
1547 internal virtual Type EnumType => null;
1548
1549 private static Type[] GetInterfaces(Type type)
1550 {
1551#if IMPORTER || EXPORTER
1552 List<Type> list = new List<Type>();
1553 for (; type != null && !type.__IsMissing; type = type.BaseType)
1554 {
1555 AddInterfaces(list, type);
1556 }
1557 return list.ToArray();
1558#else
1559 return type.GetInterfaces();
1560#endif
1561 }
1562
1563#if IMPORTER || EXPORTER
1564
1565 private static void AddInterfaces(List<Type> list, Type type)
1566 {
1567 foreach (var iface in type.__GetDeclaredInterfaces())
1568 {
1569 if (!list.Contains(iface))
1570 {
1571 list.Add(iface);
1572 if (!iface.__IsMissing)
1573 {
1574 AddInterfaces(list, iface);
1575 }
1576 }
1577 }
1578 }
1579
1580#endif
1581
1582 protected static RuntimeJavaType[] GetImplementedInterfacesAsTypeWrappers(RuntimeContext context, Type type)
1583 {
1584 var interfaceTypes = GetInterfaces(type);
1585 var interfaces = new RuntimeJavaType[interfaceTypes.Length];
1586
1587 for (int i = 0; i < interfaceTypes.Length; i++)
1588 {
1589 var decl = interfaceTypes[i].DeclaringType;
1590 if (decl != null && context.AttributeHelper.IsGhostInterface(decl))
1591 {
1592 // we have to return the declaring type for ghost interfaces
1593 interfaces[i] = context.ClassLoaderFactory.GetJavaTypeFromType(decl);
1594 }
1595 else
1596 {
1597 interfaces[i] = context.ClassLoaderFactory.GetJavaTypeFromType(interfaceTypes[i]);
1598 }
1599 }
1600
1601 for (int i = 0; i < interfaceTypes.Length; i++)
1602 {
1603 if (interfaces[i].IsRemapped)
1604 {
1605 // for remapped interfaces, we also return the original interface (Java types will ignore it, if it isn't listed in the ImplementsAttribute)
1606 var twRemapped = interfaces[i];
1607 var tw = context.ManagedJavaTypeFactory.GetJavaTypeFromManagedType(interfaceTypes[i]);
1608 interfaces[i] = tw;
1609 if (Array.IndexOf(interfaces, twRemapped) == -1)
1610 interfaces = ArrayUtil.Concat(interfaces, twRemapped);
1611 }
1612 }
1613
1614 return interfaces;
1615 }
1616
1617 internal RuntimeJavaType GetPublicBaseTypeWrapper()
1618 {
1619 Debug.Assert(!IsPublic);
1620
1621 if (IsUnloadable || IsInterface)
1622 return Context.JavaBase.TypeOfJavaLangObject;
1623
1624 for (var tw = this; ; tw = tw.BaseTypeWrapper)
1625 if (tw.IsPublic)
1626 return tw;
1627 }
1628
1629#if !EXPORTER
1630
1631 // return the constructor used for automagic .NET serialization
1632 internal virtual MethodBase GetSerializationConstructor()
1633 {
1634 return TypeAsBaseType.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, [context.Resolver.ResolveCoreType(typeof(System.Runtime.Serialization.SerializationInfo).FullName).AsReflection(), context.Resolver.ResolveCoreType(typeof(System.Runtime.Serialization.StreamingContext).FullName).AsReflection()], null);
1635 }
1636
1637 internal virtual MethodBase GetBaseSerializationConstructor()
1638 {
1639 return BaseTypeWrapper.GetSerializationConstructor();
1640 }
1641
1642#endif
1643
1644#if !IMPORTER && !EXPORTER
1645 internal virtual object GhostWrap(object obj)
1646 {
1647 return obj;
1648 }
1649
1650 internal virtual object GhostUnwrap(object obj)
1651 {
1652 return obj;
1653 }
1654#endif
1655
1656 internal bool IsDynamic
1657 {
1658#if EXPORTER
1659 get { return false; }
1660#else
1661 get { return this is RuntimeByteCodeJavaType; }
1662#endif
1663 }
1664
1665 internal virtual object[] GetConstantPool()
1666 {
1667 return null;
1668 }
1669
1670 internal virtual byte[] GetRawTypeAnnotations()
1671 {
1672 return null;
1673 }
1674
1675 internal virtual byte[] GetMethodRawTypeAnnotations(RuntimeJavaMethod mw)
1676 {
1677 return null;
1678 }
1679
1680 internal virtual byte[] GetFieldRawTypeAnnotations(RuntimeJavaField fw)
1681 {
1682 return null;
1683 }
1684
1685#if !IMPORTER && !EXPORTER
1686 internal virtual RuntimeJavaType Host
1687 {
1688 get { return null; }
1689 }
1690#endif
1691 }
1692
1693}
IKVM.Reflection.Type Type
IKVM.Reflection.FieldInfo FieldInfo
IKVM.Reflection.MethodBase MethodBase
global::java.lang.invoke.LambdaForm.Name Name
Implementation of RuntimeClassLoader that emits loaded Java types to an AssemblyBuilder.
Exposes methods to accept diagnostic invocations.