IKVM11  11
Java SE 11 Virtual Machine for .NET
Loading...
Searching...
No Matches
RuntimeByteCodeJavaType.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;
30using System.Text;
31
32
33
34#if IMPORTER
35using IKVM.Reflection;
38
39using Type = IKVM.Reflection.Type;
40using ProtectionDomain = System.Object;
41#else
42using System.Reflection;
43using System.Reflection.Emit;
44
45using ProtectionDomain = java.security.ProtectionDomain;
46#endif
47
48namespace IKVM.Runtime
49{
50
51#if IMPORTER
52 abstract partial class RuntimeByteCodeJavaType : RuntimeJavaType
53#else
54#pragma warning disable 628 // don't complain about protected members in sealed type
55 sealed partial class RuntimeByteCodeJavaType : RuntimeJavaType
56#endif
57 {
58
59#if IMPORTER == false && NETCOREAPP
60
61 static readonly PropertyInfo MetadataTokenInternalPropertyInfo = typeof(MethodBuilder).GetProperty("MetadataTokenInternal", BindingFlags.Instance | BindingFlags.NonPublic);
62
63#endif
64
65#if IMPORTER
66 protected readonly ImportClassLoader classLoader;
67#else
68 protected readonly RuntimeClassLoader classLoader;
69#endif
70 volatile DynamicImpl impl;
71 readonly RuntimeJavaType baseTypeWrapper;
72 readonly RuntimeJavaType[] interfaces;
73 readonly string sourceFileName;
74#if !IMPORTER
75 byte[][] lineNumberTables;
76#endif
77 MethodBase automagicSerializationCtor;
78
79 RuntimeJavaType LoadTypeWrapper(RuntimeClassLoader classLoader, ProtectionDomain pd, ClassFile.ConstantPoolItemClass clazz)
80 {
81 // check for patched constant pool items
82 var tw = clazz.GetClassType();
83 if (tw == null || tw == classLoader.Context.VerifierJavaTypeFactory.Null)
84 tw = classLoader.TryLoadClassByName(clazz.Name);
85 if (tw == null)
86 throw new NoClassDefFoundError(clazz.Name);
87
88 CheckMissing(this, tw);
89 classLoader.CheckPackageAccess(tw, pd);
90 return tw;
91 }
92
93 private static void CheckMissing(RuntimeJavaType prev, RuntimeJavaType tw)
94 {
95#if IMPORTER
96 do
97 {
99 if (missing != null)
100 {
101 Type mt = ReflectUtil.GetMissingType(missing.MissingType);
102 if (mt.Assembly.__IsMissing)
103 {
104 throw new FatalCompilerErrorException(DiagnosticEvent.MissingBaseTypeReference(mt.FullName, mt.Assembly.FullName));
105 }
106
107 throw new FatalCompilerErrorException(DiagnosticEvent.MissingBaseType(mt.FullName, mt.Assembly.FullName, prev.TypeAsBaseType.FullName, prev.TypeAsBaseType.Module.Name));
108 }
109 foreach (RuntimeJavaType iface in tw.Interfaces)
110 {
111 CheckMissing(tw, iface);
112 }
113 prev = tw;
114 tw = tw.BaseTypeWrapper;
115 }
116 while (tw != null);
117#endif
118 }
119
120#if IMPORTER
121 internal RuntimeByteCodeJavaType(RuntimeJavaType host, ClassFile f, ImportClassLoader classLoader, ProtectionDomain pd)
122#else
123 internal RuntimeByteCodeJavaType(RuntimeJavaType host, ClassFile f, RuntimeClassLoader classLoader, ProtectionDomain pd)
124#endif
125 : base(classLoader.Context, f.IsInternal ? TypeFlags.InternalAccess : host != null ? TypeFlags.Anonymous : TypeFlags.None, f.Modifiers, f.Name)
126 {
127 Profiler.Count("RuntimeByteCodeJavaType");
128 this.classLoader = classLoader;
129 this.sourceFileName = f.SourceFileAttribute;
130 if (f.IsInterface)
131 {
132 // interfaces can't "override" final methods in object
133 foreach (ClassFile.Method method in f.Methods)
134 {
135 RuntimeJavaMethod mw;
136 if (method.IsVirtual
137 && (mw = Context.JavaBase.TypeOfJavaLangObject.GetMethod(method.Name, method.Signature, false)) != null
138 && mw.IsVirtual
139 && mw.IsFinal)
140 {
141 throw new VerifyError("class " + f.Name + " overrides final method " + method.Name + "." + method.Signature);
142 }
143 }
144 }
145 else
146 {
147 this.baseTypeWrapper = LoadTypeWrapper(classLoader, pd, f.SuperClass);
148 if (!BaseTypeWrapper.IsAccessibleFrom(this))
149 {
150 throw new IllegalAccessError("Class " + f.Name + " cannot access its superclass " + BaseTypeWrapper.Name);
151 }
152 if (BaseTypeWrapper.IsFinal)
153 {
154 throw new VerifyError("Class " + f.Name + " extends final class " + BaseTypeWrapper.Name);
155 }
156 if (BaseTypeWrapper.IsInterface)
157 {
158 throw new IncompatibleClassChangeError("Class " + f.Name + " has interface " + BaseTypeWrapper.Name + " as superclass");
159 }
160 if (BaseTypeWrapper.TypeAsTBD == Context.Types.Delegate)
161 {
162 throw new VerifyError(BaseTypeWrapper.Name + " cannot be used as a base class");
163 }
164 // NOTE defining value types, enums is not supported in IKVM v1
165 if (BaseTypeWrapper.TypeAsTBD == Context.Types.ValueType || BaseTypeWrapper.TypeAsTBD == Context.Types.Enum)
166 {
167 throw new VerifyError("Defining value types in Java is not implemented in IKVM v1");
168 }
169 if (IsDelegate)
170 {
171 VerifyDelegate(f);
172 }
173 }
174
175 ClassFile.ConstantPoolItemClass[] interfaces = f.Interfaces;
176 this.interfaces = new RuntimeJavaType[interfaces.Length];
177 for (int i = 0; i < interfaces.Length; i++)
178 {
179 RuntimeJavaType iface = LoadTypeWrapper(classLoader, pd, interfaces[i]);
180 if (!iface.IsAccessibleFrom(this))
181 {
182 throw new IllegalAccessError("Class " + f.Name + " cannot access its superinterface " + iface.Name);
183 }
184 if (!iface.IsInterface)
185 {
186 throw new IncompatibleClassChangeError("Implementing class");
187 }
188 this.interfaces[i] = iface;
189 }
190
191 impl = new JavaTypeImpl(host, f, this);
192 }
193
194 private void VerifyDelegate(ClassFile f)
195 {
196 if (!f.IsFinal)
197 {
198 throw new VerifyError("Delegate must be final");
199 }
200 ClassFile.Method invoke = null;
201 ClassFile.Method beginInvoke = null;
202 ClassFile.Method endInvoke = null;
203 ClassFile.Method constructor = null;
204 foreach (ClassFile.Method m in f.Methods)
205 {
206 if (m.Name == "Invoke")
207 {
208 if (invoke != null)
209 {
210 throw new VerifyError("Delegate may only have a single Invoke method");
211 }
212 invoke = m;
213 }
214 else if (m.Name == "BeginInvoke")
215 {
216 if (beginInvoke != null)
217 {
218 throw new VerifyError("Delegate may only have a single BeginInvoke method");
219 }
220 beginInvoke = m;
221 }
222 else if (m.Name == "EndInvoke")
223 {
224 if (endInvoke != null)
225 {
226 throw new VerifyError("Delegate may only have a single EndInvoke method");
227 }
228 endInvoke = m;
229 }
230 else if (m.Name == "<init>")
231 {
232 if (constructor != null)
233 {
234 throw new VerifyError("Delegate may only have a single constructor");
235 }
236 constructor = m;
237 }
238 else if (m.IsNative)
239 {
240 throw new VerifyError("Delegate may not have any native methods besides Invoke, BeginInvoke and EndInvoke");
241 }
242 }
243 if (invoke == null || constructor == null)
244 {
245 throw new VerifyError("Delegate must have a constructor and an Invoke method");
246 }
247 if (!invoke.IsPublic || !invoke.IsNative || invoke.IsFinal || invoke.IsStatic)
248 {
249 throw new VerifyError("Delegate Invoke method must be a public native non-final instance method");
250 }
251 if ((beginInvoke != null && endInvoke == null) || (beginInvoke == null && endInvoke != null))
252 {
253 throw new VerifyError("Delegate must have both BeginInvoke and EndInvoke or neither");
254 }
255 if (!constructor.IsPublic)
256 {
257 throw new VerifyError("Delegate constructor must be public");
258 }
259 if (constructor.Instructions.Length < 3
260 || constructor.Instructions[0].NormalizedOpCode != NormalizedByteCode.__aload
261 || constructor.Instructions[0].NormalizedArg1 != 0
262 || constructor.Instructions[1].NormalizedOpCode != NormalizedByteCode.__invokespecial
263 || constructor.Instructions[2].NormalizedOpCode != NormalizedByteCode.__return)
264 {
265 throw new VerifyError("Delegate constructor must be empty");
266 }
267 if (f.Fields.Length != 0)
268 {
269 throw new VerifyError("Delegate may not declare any fields");
270 }
271 var iface = classLoader.TryLoadClassByName(f.Name + RuntimeManagedJavaType.DelegateInterfaceSuffix);
272 DelegateInnerClassCheck(iface != null);
273 DelegateInnerClassCheck(iface.IsInterface);
274 DelegateInnerClassCheck(iface.IsPublic);
275 DelegateInnerClassCheck(iface.ClassLoader == classLoader);
276 RuntimeJavaMethod[] methods = iface.GetMethods();
277 DelegateInnerClassCheck(methods.Length == 1 && methods[0].Name == "Invoke");
278 if (methods[0].Signature != invoke.Signature)
279 {
280 throw new VerifyError("Delegate Invoke method signature must be identical to inner interface Invoke method signature");
281 }
282 if (iface.Interfaces.Length != 0)
283 {
284 throw new VerifyError("Delegate inner interface may not extend any interfaces");
285 }
286 if (constructor.Signature != "(" + iface.SigName + ")V")
287 {
288 throw new VerifyError("Delegate constructor must take a single argument of type inner Method interface");
289 }
290 if (beginInvoke != null && beginInvoke.Signature != invoke.Signature.Substring(0, invoke.Signature.IndexOf(')')) + "Lcli.System.AsyncCallback;Ljava.lang.Object;)Lcli.System.IAsyncResult;")
291 {
292 throw new VerifyError("Delegate BeginInvoke method has incorrect signature");
293 }
294 if (endInvoke != null && endInvoke.Signature != "(Lcli.System.IAsyncResult;)" + invoke.Signature.Substring(invoke.Signature.IndexOf(')') + 1))
295 {
296 throw new VerifyError("Delegate EndInvoke method has incorrect signature");
297 }
298 }
299
300 private static void DelegateInnerClassCheck(bool cond)
301 {
302 if (!cond)
303 {
304 throw new VerifyError("Delegate must have a public inner interface named Method with a single method named Invoke");
305 }
306 }
307
308 private bool IsDelegate
309 {
310 get
311 {
312 RuntimeJavaType baseTypeWrapper = BaseTypeWrapper;
313 return baseTypeWrapper != null && baseTypeWrapper.TypeAsTBD == Context.Types.MulticastDelegate;
314 }
315 }
316
317 internal sealed override RuntimeJavaType BaseTypeWrapper
318 {
319 get { return baseTypeWrapper; }
320 }
321
322 internal override RuntimeClassLoader ClassLoader => classLoader;
323
324 internal override Modifiers ReflectiveModifiers
325 {
326 get
327 {
328 return impl.ReflectiveModifiers;
329 }
330 }
331
332 internal override RuntimeJavaType[] Interfaces
333 {
334 get
335 {
336 return interfaces;
337 }
338 }
339
340 internal override RuntimeJavaType[] InnerClasses
341 {
342 get
343 {
344 return impl.InnerClasses;
345 }
346 }
347
348 internal override RuntimeJavaType DeclaringTypeWrapper
349 {
350 get
351 {
352 return impl.DeclaringTypeWrapper;
353 }
354 }
355
356 internal override Type TypeAsTBD
357 {
358 get
359 {
360 return impl.Type;
361 }
362 }
363
364 internal override void Finish()
365 {
366 // we don't need locking, because Finish is Thread safe
367 impl = impl.Finish();
368 }
369
370 internal void CreateStep1()
371 {
372 ((JavaTypeImpl)impl).CreateStep1();
373 }
374
375 internal void CreateStep2()
376 {
377 ((JavaTypeImpl)impl).CreateStep2();
378 }
379
380 private bool IsSerializable
381 {
382 get
383 {
384 return this.IsSubTypeOf(Context.JavaBase.TypeOfJavaIoSerializable);
385 }
386 }
387
388 static bool CheckRequireOverrideStub(RuntimeJavaMethod mw1, RuntimeJavaMethod mw2)
389 {
390 // TODO this is too late to generate LinkageErrors so we need to figure this out earlier
391 if (!TypesMatchForOverride(mw1.ReturnType, mw2.ReturnType))
392 return true;
393
394 var args1 = mw1.GetParameters();
395 var args2 = mw2.GetParameters();
396 for (int i = 0; i < args1.Length; i++)
397 if (!TypesMatchForOverride(args1[i], args2[i]))
398 return true;
399
400 return false;
401 }
402
403 static bool TypesMatchForOverride(RuntimeJavaType tw1, RuntimeJavaType tw2)
404 {
405 if (tw1 == tw2)
406 return true;
407 else if (tw1.IsUnloadable && tw2.IsUnloadable)
408 return ((RuntimeUnloadableJavaType)tw1).CustomModifier == ((RuntimeUnloadableJavaType)tw2).CustomModifier;
409 else
410 return false;
411 }
412
413 void GenerateOverrideStub(TypeBuilder typeBuilder, RuntimeJavaMethod baseMethod, MethodInfo target, RuntimeJavaMethod targetMethod)
414 {
415 Debug.Assert(!baseMethod.HasCallerID);
416
417 var overrideStub = baseMethod.GetDefineMethodHelper().DefineMethod(this, typeBuilder, "__<overridestub>" + baseMethod.DeclaringType.Name + "::" + baseMethod.Name, MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.Final);
418 typeBuilder.DefineMethodOverride(overrideStub, (MethodInfo)baseMethod.GetMethod());
419
420 var stubargs = baseMethod.GetParameters();
421 var targetArgs = targetMethod.GetParameters();
422 var ilgen = Context.CodeEmitterFactory.Create(overrideStub);
423 ilgen.Emit(OpCodes.Ldarg_0);
424
425 for (int i = 0; i < targetArgs.Length; i++)
426 {
427 ilgen.EmitLdarg(i + 1);
428 ConvertStubArg(stubargs[i], targetArgs[i], ilgen);
429 }
430
431 if (target != null)
432 ilgen.Emit(OpCodes.Callvirt, target);
433 else
434 targetMethod.EmitCallvirt(ilgen);
435
436 ConvertStubArg(targetMethod.ReturnType, baseMethod.ReturnType, ilgen);
437 ilgen.Emit(OpCodes.Ret);
438 ilgen.DoEmit();
439 }
440
441 static void ConvertStubArg(RuntimeJavaType src, RuntimeJavaType dst, CodeEmitter ilgen)
442 {
443 if (src != dst)
444 {
445 if (dst.IsUnloadable)
446 {
447 if (!src.IsUnloadable && (src.IsGhost || src.IsNonPrimitiveValueType))
448 {
449 src.EmitConvSignatureTypeToStackType(ilgen);
450 }
451 }
452 else if (dst.IsGhost || dst.IsNonPrimitiveValueType)
453 {
454 dst.EmitConvStackTypeToSignatureType(ilgen, null);
455 }
456 else
457 {
458 dst.EmitCheckcast(ilgen);
459 }
460 }
461 }
462
463 static void GetParameterNamesFromMP(ClassFile.Method m, string[] parameterNames)
464 {
465 var methodParameters = m.MethodParameters;
466 if (methodParameters != null)
467 {
468 for (int i = 0, count = Math.Min(parameterNames.Length, methodParameters.Length); i < count; i++)
469 {
470 if (parameterNames[i] == null)
471 {
472 parameterNames[i] = methodParameters[i].name;
473 }
474 }
475 }
476 }
477
478 protected static void GetParameterNamesFromLVT(ClassFile.Method m, string[] parameterNames)
479 {
480 var localVars = m.LocalVariableTableAttribute;
481 if (localVars != null)
482 {
483 for (int i = m.IsStatic ? 0 : 1, pos = 0; i < m.ArgMap.Length; i++)
484 {
485 // skip double & long fillers
486 if (m.ArgMap[i] != -1)
487 {
488 if (parameterNames[pos] == null)
489 {
490 for (int j = 0; j < localVars.Length; j++)
491 {
492 if (localVars[j].index == i)
493 {
494 parameterNames[pos] = localVars[j].name;
495 break;
496 }
497 }
498 }
499
500 pos++;
501 }
502 }
503 }
504 }
505
506 protected static void GetParameterNamesFromSig(string sig, string[] parameterNames)
507 {
508 var names = new List<string>();
509 for (int i = 1; sig[i] != ')'; i++)
510 {
511 if (sig[i] == 'L')
512 {
513 i++;
514 int end = sig.IndexOf(';', i);
515 names.Add(GetParameterName(sig.Substring(i, end - i)));
516 i = end;
517 }
518 else if (sig[i] == '[')
519 {
520 while (sig[++i] == '[') ;
521 if (sig[i] == 'L')
522 {
523 i++;
524 int end = sig.IndexOf(';', i);
525 names.Add(GetParameterName(sig.Substring(i, end - i)) + "arr");
526 i = end;
527 }
528 else
529 {
530 switch (sig[i])
531 {
532 case 'B':
533 case 'Z':
534 names.Add("barr");
535 break;
536 case 'C':
537 names.Add("charr");
538 break;
539 case 'S':
540 names.Add("sarr");
541 break;
542 case 'I':
543 names.Add("iarr");
544 break;
545 case 'J':
546 names.Add("larr");
547 break;
548 case 'F':
549 names.Add("farr");
550 break;
551 case 'D':
552 names.Add("darr");
553 break;
554 }
555 }
556 }
557 else
558 {
559 switch (sig[i])
560 {
561 case 'B':
562 case 'Z':
563 names.Add("b");
564 break;
565 case 'C':
566 names.Add("ch");
567 break;
568 case 'S':
569 names.Add("s");
570 break;
571 case 'I':
572 names.Add("i");
573 break;
574 case 'J':
575 names.Add("l");
576 break;
577 case 'F':
578 names.Add("f");
579 break;
580 case 'D':
581 names.Add("d");
582 break;
583 }
584 }
585 }
586
587 for (int i = 0; i < parameterNames.Length; i++)
588 if (parameterNames[i] == null)
589 parameterNames[i] = names[i];
590 }
591
592 protected static ParameterBuilder[] GetParameterBuilders(MethodBuilder mb, int parameterCount, string[] parameterNames)
593 {
594 var parameterBuilders = new ParameterBuilder[parameterCount];
595 Dictionary<string, int> clashes = null;
596 for (int i = 0; i < parameterBuilders.Length; i++)
597 {
598 string name = null;
599 if (parameterNames != null && parameterNames[i] != null)
600 {
601 name = parameterNames[i];
602 if (Array.IndexOf(parameterNames, name, i + 1) >= 0 || (clashes != null && clashes.ContainsKey(name)))
603 {
604 clashes ??= new Dictionary<string, int>();
605
606 int clash = 1;
607 if (clashes.ContainsKey(name))
608 clash = clashes[name] + 1;
609
610 clashes[name] = clash;
611 name += clash;
612 }
613 }
614 parameterBuilders[i] = mb.DefineParameter(i + 1, ParameterAttributes.None, name);
615 }
616 return parameterBuilders;
617 }
618
619 static string GetParameterName(string type)
620 {
621 if (type == "java.lang.String")
622 {
623 return "str";
624 }
625 else if (type == "java.lang.Object")
626 {
627 return "obj";
628 }
629 else
630 {
631 var sb = new ValueStringBuilder(type.Length);
632 for (int i = type.LastIndexOf('.') + 1; i < type.Length; i++)
633 if (char.IsUpper(type, i))
634 sb.Append(char.ToLower(type[i]));
635
636 return sb.ToString();
637 }
638 }
639
640#if IMPORTER
641
642 protected abstract void AddMapXmlFields(ref RuntimeJavaField[] fields);
643
644 protected abstract bool EmitMapXmlMethodPrologueAndOrBody(CodeEmitter ilgen, ClassFile f, ClassFile.Method m);
645
646 protected abstract void EmitMapXmlMetadata(TypeBuilder typeBuilder, ClassFile classFile, RuntimeJavaField[] fields, RuntimeJavaMethod[] methods);
647
648 protected abstract MethodBuilder DefineGhostMethod(TypeBuilder typeBuilder, string name, MethodAttributes attribs, RuntimeJavaMethod mw);
649
650 protected abstract void FinishGhost(TypeBuilder typeBuilder, RuntimeJavaMethod[] methods);
651
652 protected abstract void FinishGhostStep2();
653
654 protected abstract TypeBuilder DefineGhostType(string mangledTypeName, TypeAttributes typeAttribs);
655
656#endif // IMPORTER
657
658 private bool IsPInvokeMethod(ClassFile.Method m)
659 {
660#if IMPORTER
661 Dictionary<string, IKVM.Tools.Importer.MapXml.Class> mapxml = classLoader.GetMapXmlClasses();
662 if (mapxml != null)
663 {
664 IKVM.Tools.Importer.MapXml.Class clazz;
665 if (mapxml.TryGetValue(this.Name, out clazz) && clazz.Methods != null)
666 {
667 foreach (IKVM.Tools.Importer.MapXml.Method method in clazz.Methods)
668 {
669 if (method.Name == m.Name && method.Sig == m.Signature)
670 {
671 if (method.Attributes != null)
672 {
673 foreach (IKVM.Tools.Importer.MapXml.Attribute attr in method.Attributes)
674 {
675 if (Context.StaticCompiler.GetType(classLoader, attr.Type) == Context.Resolver.ResolveCoreType(typeof(System.Runtime.InteropServices.DllImportAttribute).FullName).AsReflection())
676 {
677 return true;
678 }
679 }
680 }
681 break;
682 }
683 }
684 }
685 }
686#endif
687 if (m.Annotations != null)
688 {
689 foreach (object[] annot in m.Annotations)
690 {
691 if ("Lcli/System/Runtime/InteropServices/DllImportAttribute$Annotation;".Equals(annot[1]))
692 {
693 return true;
694 }
695 }
696 }
697 return false;
698 }
699
700 internal override MethodBase LinkMethod(RuntimeJavaMethod mw)
701 {
702 mw.AssertLinked();
703 return impl.LinkMethod(mw);
704 }
705
706 internal override FieldInfo LinkField(RuntimeJavaField fw)
707 {
708 fw.AssertLinked();
709 return impl.LinkField(fw);
710 }
711
712 internal override void EmitRunClassConstructor(CodeEmitter ilgen)
713 {
714 impl.EmitRunClassConstructor(ilgen);
715 }
716
717 internal override string GetGenericSignature()
718 {
719 return impl.GetGenericSignature();
720 }
721
722 internal override string GetGenericMethodSignature(RuntimeJavaMethod method)
723 {
724 var methods = GetMethods();
725 for (int i = 0; i < methods.Length; i++)
726 if (methods[i] == method)
727 return impl.GetGenericMethodSignature(i);
728
729 Debug.Fail("Unreachable code");
730 return null;
731 }
732
733 internal override string GetGenericFieldSignature(RuntimeJavaField field)
734 {
735 var fields = GetFields();
736 for (int i = 0; i < fields.Length; i++)
737 if (fields[i] == field)
738 return impl.GetGenericFieldSignature(i);
739
740 Debug.Fail("Unreachable code");
741 return null;
742 }
743
744 internal override MethodParametersEntry[] GetMethodParameters(RuntimeJavaMethod method)
745 {
746 var methods = GetMethods();
747 for (int i = 0; i < methods.Length; i++)
748 if (methods[i] == method)
749 return impl.GetMethodParameters(i);
750
751 Debug.Fail("Unreachable code");
752 return null;
753 }
754
755#if !IMPORTER
756
757 internal override string[] GetEnclosingMethod()
758 {
759 return impl.GetEnclosingMethod();
760 }
761
766 internal override string GetSourceFileName()
767 {
768 return sourceFileName;
769 }
770
776 int GetMethodBaseToken(MethodBase mb)
777 {
778 if (mb is MethodBuilder mbld)
779 {
780#if NETFRAMEWORK
781 return mbld.GetToken().Token;
782#else
783 try
784 {
785 return mbld.GetMetadataToken();
786 }
787 catch (InvalidOperationException)
788 {
789 if (MetadataTokenInternalPropertyInfo != null)
790 return (int)MetadataTokenInternalPropertyInfo.GetValue(mbld);
791 }
792#endif
793 }
794
795#if NETFRAMEWORK
796 return mb.MetadataToken;
797#else
798 return mb.GetMetadataToken();
799#endif
800 }
801
808 internal override int GetSourceLineNumber(MethodBase mb, int ilOffset)
809 {
810 if (lineNumberTables != null)
811 {
812 var token = GetMethodBaseToken(mb);
813 var methods = GetMethods();
814 for (int i = 0; i < methods.Length; i++)
815 {
816 if (GetMethodBaseToken(methods[i].GetMethod()) == token)
817 {
818 if (lineNumberTables[i] != null)
819 return new LineNumberTableAttribute(lineNumberTables[i]).GetLineNumber(ilOffset);
820
821 break;
822 }
823 }
824 }
825
826 return -1;
827 }
828
829 object[] DecodeAnnotations(object[] definitions)
830 {
831 if (definitions == null)
832 return null;
833
834 var loader = ClassLoader.GetJavaClassLoader();
835 var annotations = new List<object>();
836
837 for (int i = 0; i < definitions.Length; i++)
838 {
839 var obj = JVM.NewAnnotation(loader, definitions[i]);
840 if (obj != null)
841 annotations.Add(obj);
842 }
843
844 return annotations.ToArray();
845 }
846
847 internal override object[] GetDeclaredAnnotations()
848 {
849 return DecodeAnnotations(impl.GetDeclaredAnnotations());
850 }
851
852 internal override object[] GetMethodAnnotations(RuntimeJavaMethod mw)
853 {
854 RuntimeJavaMethod[] methods = GetMethods();
855 for (int i = 0; i < methods.Length; i++)
856 {
857 if (methods[i] == mw)
858 {
859 return DecodeAnnotations(impl.GetMethodAnnotations(i));
860 }
861 }
862 Debug.Fail("Unreachable code");
863 return null;
864 }
865
866 internal override object[][] GetParameterAnnotations(RuntimeJavaMethod mw)
867 {
868 RuntimeJavaMethod[] methods = GetMethods();
869 for (int i = 0; i < methods.Length; i++)
870 {
871 if (methods[i] == mw)
872 {
873 object[][] annotations = impl.GetParameterAnnotations(i);
874 if (annotations != null)
875 {
876 object[][] objs = new object[annotations.Length][];
877 for (int j = 0; j < annotations.Length; j++)
878 {
879 objs[j] = DecodeAnnotations(annotations[j]);
880 }
881 return objs;
882 }
883 return null;
884 }
885 }
886 Debug.Fail("Unreachable code");
887 return null;
888 }
889
890 internal override object[] GetFieldAnnotations(RuntimeJavaField fw)
891 {
892 RuntimeJavaField[] fields = GetFields();
893 for (int i = 0; i < fields.Length; i++)
894 {
895 if (fields[i] == fw)
896 {
897 return DecodeAnnotations(impl.GetFieldAnnotations(i));
898 }
899 }
900 Debug.Fail("Unreachable code");
901 return null;
902 }
903
904 internal override object GetAnnotationDefault(RuntimeJavaMethod mw)
905 {
906 RuntimeJavaMethod[] methods = GetMethods();
907 for (int i = 0; i < methods.Length; i++)
908 {
909 if (methods[i] == mw)
910 {
911 object defVal = impl.GetMethodDefaultValue(i);
912 if (defVal != null)
913 {
914 return JVM.NewAnnotationElementValue(mw.DeclaringType.ClassLoader.GetJavaClassLoader(), mw.ReturnType.ClassObject, defVal);
915 }
916 return null;
917 }
918 }
919 Debug.Fail("Unreachable code");
920 return null;
921 }
922
923 private Type GetBaseTypeForDefineType()
924 {
925 return BaseTypeWrapper.TypeAsBaseType;
926 }
927
928#endif
929
930#if IMPORTER
931
932 protected virtual Type GetBaseTypeForDefineType()
933 {
934 return BaseTypeWrapper.TypeAsBaseType;
935 }
936
937 internal virtual RuntimeJavaMethod[] GetReplacedMethodsFor(RuntimeJavaMethod mw)
938 {
939 return null;
940 }
941
942#endif // IMPORTER
943
944 internal override MethodBase GetSerializationConstructor()
945 {
946 return automagicSerializationCtor;
947 }
948
949 private Type[] GetModOpt(RuntimeJavaType tw, bool mustBePublic)
950 {
951 return GetModOpt(ClassLoader.GetTypeWrapperFactory(), tw, mustBePublic);
952 }
953
954 internal static Type[] GetModOpt(RuntimeJavaTypeFactory context, RuntimeJavaType tw, bool mustBePublic)
955 {
956 Type[] modopt = Type.EmptyTypes;
957 if (tw.IsUnloadable)
958 {
959 if (((RuntimeUnloadableJavaType)tw).MissingType == null)
960 {
961 modopt = new Type[] { ((RuntimeUnloadableJavaType)tw).GetCustomModifier(context) };
962 }
963 }
964 else
965 {
966 RuntimeJavaType tw1 = tw.IsArray ? tw.GetUltimateElementTypeWrapper() : tw;
967 if (tw1.IsErasedOrBoxedPrimitiveOrRemapped || tw.IsGhostArray || (mustBePublic && !tw1.IsPublic))
968 {
969 // FXBUG Ref.Emit refuses arrays in custom modifiers, so we add an array type for each dimension
970 modopt = new Type[tw.ArrayRank + 1];
971 modopt[0] = GetModOptHelper(tw1);
972 for (int i = 1; i < modopt.Length; i++)
973 {
974 modopt[i] = tw.Context.Types.Array;
975 }
976 }
977 }
978 return modopt;
979 }
980
981 private static Type GetModOptHelper(RuntimeJavaType tw)
982 {
983 Debug.Assert(!tw.IsUnloadable);
984 if (tw.IsArray)
985 {
986 return RuntimeArrayJavaType.MakeArrayType(GetModOptHelper(tw.GetUltimateElementTypeWrapper()), tw.ArrayRank);
987 }
988 else if (tw.IsGhost)
989 {
990 return tw.TypeAsTBD;
991 }
992 else
993 {
994 return tw.TypeAsBaseType;
995 }
996 }
997
998#if IMPORTER
999 private bool NeedsType2AccessStub(RuntimeJavaField fw)
1000 {
1001 Debug.Assert(this.IsPublic && fw.DeclaringType == this);
1002 return fw.IsType2FinalField
1003 || (fw.HasNonPublicTypeInSignature
1004 && (fw.IsPublic || (fw.IsProtected && !this.IsFinal))
1005 && (fw.FieldTypeWrapper.IsUnloadable || fw.FieldTypeWrapper.IsAccessibleFrom(this) || fw.FieldTypeWrapper.InternalsVisibleTo(this)));
1006 }
1007#endif
1008
1009 internal static bool RequiresDynamicReflectionCallerClass(string classFile, string method, string signature)
1010 {
1011 return (classFile == "java.lang.ClassLoader" && method == "getParent" && signature == "()Ljava.lang.ClassLoader;")
1012 || (classFile == "java.lang.Thread" && method == "getContextClassLoader" && signature == "()Ljava.lang.ClassLoader;")
1013 || (classFile == "java.io.ObjectStreamField" && method == "getType" && signature == "()Ljava.lang.Class;")
1014 || (classFile == "javax.sql.rowset.serial.SerialJavaObject" && method == "getFields" && signature == "()[Ljava.lang.reflect.Field;")
1015 ;
1016 }
1017
1018
1019 internal override object[] GetConstantPool()
1020 {
1021 Finish();
1022 return impl.GetConstantPool();
1023 }
1024
1025 internal override byte[] GetRawTypeAnnotations()
1026 {
1027 Finish();
1028 return impl.GetRawTypeAnnotations();
1029 }
1030
1031 internal override byte[] GetMethodRawTypeAnnotations(RuntimeJavaMethod mw)
1032 {
1033 Finish();
1034 return impl.GetMethodRawTypeAnnotations(Array.IndexOf(GetMethods(), mw));
1035 }
1036
1037 internal override byte[] GetFieldRawTypeAnnotations(RuntimeJavaField fw)
1038 {
1039 Finish();
1040 return impl.GetFieldRawTypeAnnotations(Array.IndexOf(GetFields(), fw));
1041 }
1042
1043#if !IMPORTER && !EXPORTER
1044 internal override RuntimeJavaType Host
1045 {
1046 get { return impl.Host; }
1047 }
1048#endif
1049
1050 [Conditional("IMPORTER")]
1051 internal void EmitLevel4Warning(HardError error, string message)
1052 {
1053#if IMPORTER
1054 if (ClassLoader.WarningLevelHigh)
1055 {
1056 switch (error)
1057 {
1058 case HardError.AbstractMethodError:
1059 ClassLoader.Diagnostics.EmittedAbstractMethodError(this.Name, message);
1060 break;
1061 case HardError.IncompatibleClassChangeError:
1062 ClassLoader.Diagnostics.EmittedIncompatibleClassChangeError(this.Name, message);
1063 break;
1064 default:
1065 throw new InvalidOperationException();
1066 }
1067 }
1068#endif
1069 }
1070 }
1071
1072}
java.security.ProtectionDomain ProtectionDomain
IKVM.Reflection.Type Type
IKVM.Reflection.FieldInfo FieldInfo
IKVM.Reflection.PropertyInfo PropertyInfo
IKVM.Reflection.MethodInfo MethodInfo
IKVM.Reflection.MethodBase MethodBase
global::java.lang.invoke.LambdaForm.Name Name
CodeEmitter Create(MethodBuilder mb)
Creates a new instance.
static ParameterBuilder[] GetParameterBuilders(MethodBuilder mb, int parameterCount, string[] parameterNames)
static void GetParameterNamesFromSig(string sig, string[] parameterNames)
static void GetParameterNamesFromLVT(ClassFile.Method m, string[] parameterNames)
Runtime support for a class loader.
RuntimeContext Context
Gets a reference to the RuntimeContext that this RuntimeClassLoader is hosted within.
CodeEmitterFactory CodeEmitterFactory
Gets the CodeEmitterFactory associated with this instance of the runtime.
Types Types
Gets the Types associated with this instance of the runtime.
RuntimeVerifierJavaTypeFactory VerifierJavaTypeFactory
Gets the RuntimeVerifierJavaTypeFactory associated with this instance of the runtime.
ISymbolResolver Resolver
Gets the ISymbolResolver associated with this instance of the runtime.
CoreClasses JavaBase
Gets the CoreClasses associated with this instance of the runtime.
Type MulticastDelegate
Definition Types.cs:109
Implementation of RuntimeClassLoader that emits loaded Java types to an AssemblyBuilder.
static DiagnosticEvent MissingBaseTypeReference(string arg0, string arg1, Exception? exception=null, DiagnosticLocation location=default)
The 'MissingBaseTypeReference' diagnostic.
static DiagnosticEvent MissingBaseType(string arg0, string arg1, string arg2, string arg3, Exception? exception=null, DiagnosticLocation location=default)
The 'MissingBaseType' diagnostic.