IKVM11  11
Java SE 11 Virtual Machine for .NET
Loading...
Searching...
No Matches
RuntimeClassLoader.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*/
24
25using System;
26using System.Collections.Generic;
27using System.Diagnostics;
28using System.Threading;
29
32
33#if NETCOREAPP
34using System.Runtime.Loader;
35#endif
36
37#if IMPORTER || EXPORTER
38using IKVM.Reflection;
39
40using Type = IKVM.Reflection.Type;
41using ProtectionDomain = System.Object;
42#else
43using System.Reflection;
44
45using ProtectionDomain = java.security.ProtectionDomain;
46using System.Collections.Immutable;
47using System.Text;
48#endif
49
50#if IMPORTER
52#endif
53
54namespace IKVM.Runtime
55{
56
61 {
62
63 readonly RuntimeContext context;
64
65#if !IMPORTER && !FIRST_PASS && !EXPORTER
66
67 ClassLoaderAccessor classLoaderAccessor;
68 ClassLoaderAccessor ClassLoaderAccessor => JVM.Internal.BaseAccessors.Get(ref classLoaderAccessor);
69
70 protected java.lang.ClassLoader javaClassLoader;
71
72#endif
73
74#if !EXPORTER
76#endif // !EXPORTER
77 readonly Dictionary<string, RuntimeJavaType> types = new Dictionary<string, RuntimeJavaType>();
78 readonly Dictionary<string, Thread> defineClassInProgress = new Dictionary<string, Thread>();
79 List<IntPtr> nativeLibraries;
80 readonly CodeGenOptions codegenoptions;
81
88 internal RuntimeClassLoader(RuntimeContext context, CodeGenOptions codegenoptions, object javaClassLoader)
89 {
90 this.context = context ?? throw new ArgumentNullException(nameof(context));
91 this.codegenoptions = codegenoptions;
92#if !IMPORTER && !FIRST_PASS && !EXPORTER
93 this.javaClassLoader = (java.lang.ClassLoader)javaClassLoader;
94#endif
95 }
96
100 public virtual IDiagnosticHandler Diagnostics => Context.Diagnostics;
101
102#if IMPORTER || EXPORTER
103
104 internal void SetRemappedType(Type type, RuntimeJavaType tw)
105 {
106 lock (types)
107 types.Add(tw.Name, tw);
108
109 lock (Context.ClassLoaderFactory.globalTypeToTypeWrapper)
110 context.ClassLoaderFactory.globalTypeToTypeWrapper.Add(type, tw);
111
112 context.ClassLoaderFactory.remappedTypes.Add(type, tw.Name);
113 }
114
115#endif
116
120 public RuntimeContext Context => context;
121
122 // return the TypeWrapper if it is already loaded, this exists for DynamicTypeWrapper.SetupGhosts
123 // and implements ClassLoader.findLoadedClass()
124 internal RuntimeJavaType FindLoadedClass(string name)
125 {
126 if (name.Length > 1 && name[0] == '[')
127 return FindOrLoadArrayClass(name, LoadMode.Find);
128
129 RuntimeJavaType tw;
130 lock (types)
131 types.TryGetValue(name, out tw);
132
133 return tw ?? FindLoadedClassLazy(name);
134 }
135
136 protected virtual RuntimeJavaType FindLoadedClassLazy(string name)
137 {
138 return null;
139 }
140
141 internal RuntimeJavaType RegisterInitiatingLoader(RuntimeJavaType tw)
142 {
143 Debug.Assert(tw != null);
144 Debug.Assert(!tw.IsUnloadable);
145 Debug.Assert(!tw.IsPrimitive);
146
147 try
148 {
149 // critical code in the finally block to avoid Thread.Abort interrupting the thread
150 }
151 finally
152 {
153 tw = RegisterInitiatingLoaderCritical(tw);
154 }
155
156 return tw;
157 }
158
159 RuntimeJavaType RegisterInitiatingLoaderCritical(RuntimeJavaType tw)
160 {
161 lock (types)
162 {
163 types.TryGetValue(tw.Name, out var existing);
164 if (existing != tw)
165 {
166 if (existing != null)
167 {
168 // another thread beat us to it, discard the new TypeWrapper and
169 // return the previous one
170 return existing;
171 }
172 // NOTE if types.ContainsKey(tw.Name) is true (i.e. the value is null),
173 // we currently have a DefineClass in progress on another thread and we've
174 // beaten that thread to the punch by loading the class from a parent class
175 // loader instead. This is ok as DefineClass will throw a LinkageError when
176 // it is done.
177 types[tw.Name] = tw;
178 }
179 }
180
181 return tw;
182 }
183
184 internal bool EmitSymbols => (codegenoptions & CodeGenOptions.EmitSymbols) != 0;
185
186 internal bool EmitStackTraceInfo => (codegenoptions & CodeGenOptions.NoStackTraceInfo) == 0;
187
188 internal bool StrictFinalFieldSemantics => (codegenoptions & CodeGenOptions.StrictFinalFieldSemantics) != 0;
189
190 internal bool NoJNI => (codegenoptions & CodeGenOptions.NoJNI) != 0;
191
192 internal bool RemoveAsserts => (codegenoptions & CodeGenOptions.RemoveAsserts) != 0;
193
194 internal bool NoAutomagicSerialization => (codegenoptions & CodeGenOptions.NoAutomagicSerialization) != 0;
195
196 internal bool DisableDynamicBinding => (codegenoptions & CodeGenOptions.DisableDynamicBinding) != 0;
197
198 internal bool EmitNoRefEmitHelpers => (codegenoptions & CodeGenOptions.NoRefEmitHelpers) != 0;
199
200 internal bool RemoveUnusedFields => (codegenoptions & CodeGenOptions.RemoveUnusedFields) != 0;
201
202 internal bool EnableOptimizations => (codegenoptions & CodeGenOptions.DisableOptimizations) == 0;
203
204#if !IMPORTER && !EXPORTER
205#if FIRST_PASS == false
206
213 internal bool IsTrusted
214 {
215 get
216 {
217 var scl = ClassLoaderAccessor.GetScl();
218
219 // are we within the parent hierarchy of the system class loader?
220 for (var cl = scl; cl != null; cl = ClassLoaderAccessor.GetParent(cl))
221 if (javaClassLoader == cl)
222 return true;
223
224 return false;
225 }
226 }
227
228#endif
229
230 internal bool RelaxedClassNameValidation
231 {
232 get
233 {
234#if FIRST_PASS
235 return true;
236#else
237 return JVM.RelaxedVerification && (javaClassLoader == null || IsTrusted);
238#endif
239 }
240 }
241
242#endif
243
244 protected virtual void CheckProhibitedPackage(string className)
245 {
246 if (className.StartsWith("java.", StringComparison.Ordinal))
247 throw new JavaSecurityException("Prohibited package name: " + className.Substring(0, className.LastIndexOf('.')));
248 }
249
250#if !EXPORTER
251 internal RuntimeJavaType DefineClass(ClassFile f, ProtectionDomain protectionDomain)
252 {
253#if !IMPORTER
254 var dotnetAssembly = f.IKVMAssemblyAttribute;
255 if (dotnetAssembly != null)
256 {
257 // It's a stub class generated by ikvmstub (or generated by the runtime when getResource was
258 // called on a statically compiled class).
259 RuntimeClassLoader loader;
260 try
261 {
262 loader = Context.ClassLoaderFactory.GetAssemblyClassLoaderByName(dotnetAssembly);
263 }
264 catch (Exception x)
265 {
266 // TODO don't catch all exceptions here
267 throw new NoClassDefFoundError($"{f.Name} ({x.Message})");
268 }
269
270 var tw = loader.TryLoadClassByName(f.Name);
271 if (tw == null)
272 throw new NoClassDefFoundError($"{f.Name} (type not found in {dotnetAssembly})");
273
274 return RegisterInitiatingLoader(tw);
275 }
276#endif
278
279 // check if the class already exists if we're an AssemblyClassLoader
280 if (FindLoadedClassLazy(f.Name) != null)
281 throw new LinkageError("duplicate class definition: " + f.Name);
282
283 RuntimeJavaType def;
284 try
285 {
286 // critical code in the finally block to avoid Thread.Abort interrupting the thread
287 }
288 finally
289 {
290 def = DefineClassCritical(f, protectionDomain);
291 }
292
293 return def;
294 }
295
296 RuntimeJavaType DefineClassCritical(ClassFile classFile, ProtectionDomain protectionDomain)
297 {
298 lock (types)
299 {
300 if (types.ContainsKey(classFile.Name))
301 throw new LinkageError($"duplicate class definition: {classFile.Name}");
302
303 // mark the type as "loading in progress", so that we can detect circular dependencies.
304 types.Add(classFile.Name, null);
305 defineClassInProgress.Add(classFile.Name, Thread.CurrentThread);
306 }
307 try
308 {
309 return GetTypeWrapperFactory().DefineClassImpl(types, null, classFile, this, protectionDomain);
310 }
311 finally
312 {
313 lock (types)
314 {
315 if (types[classFile.Name] == null)
316 {
317 // if loading the class fails, we remove the indicator that we're busy loading the class,
318 // because otherwise we get a ClassCircularityError if we try to load the class again.
319 types.Remove(classFile.Name);
320 }
321 defineClassInProgress.Remove(classFile.Name);
322 Monitor.PulseAll(types);
323 }
324 }
325 }
326
327 internal RuntimeJavaTypeFactory GetTypeWrapperFactory()
328 {
329 if (factory == null)
330 {
331 lock (this)
332 {
333 try
334 {
335 // critical code in the finally block to avoid Thread.Abort interrupting the thread
336 }
337 finally
338 {
339 factory ??= context.DynamicClassLoaderFactory.GetOrCreate(this);
340 }
341 }
342 }
343
344 return factory;
345 }
346
347#endif // !EXPORTER
348
349 internal RuntimeJavaType LoadClassByName(string name)
350 {
351 return LoadClass(name, LoadMode.LoadOrThrow);
352 }
353
354 internal RuntimeJavaType TryLoadClassByName(string name)
355 {
356 return LoadClass(name, LoadMode.LoadOrNull);
357 }
358
359 internal RuntimeJavaType LoadClass(string name, LoadMode mode)
360 {
361 Profiler.Enter("LoadClass");
362
363 try
364 {
365 var javaType = LoadRegisteredOrPendingClass(name);
366 if (javaType != null)
367 return javaType;
368
369 if (name.Length > 1 && name[0] == '[')
370 javaType = FindOrLoadArrayClass(name, mode);
371 else
372 javaType = LoadClassImpl(name, mode);
373
374 if (javaType != null)
375 return RegisterInitiatingLoader(javaType);
376
377 if (!(name.Length > 1 && name[0] == '[') && ((mode & LoadMode.WarnClassNotFound) != 0) || WarningLevelHigh)
378 Diagnostics.ClassNotFound(name);
379
380 return (mode & LoadMode.MaskReturn) switch
381 {
382 LoadMode.ReturnNull => null,
383 LoadMode.ReturnUnloadable => new RuntimeUnloadableJavaType(context, name),
384 LoadMode.ThrowClassNotFound => throw new ClassNotFoundException(name),
385 _ => throw new InvalidOperationException(),
386 };
387 }
388 finally
389 {
390 Profiler.Leave("LoadClass");
391 }
392 }
393
394 RuntimeJavaType LoadRegisteredOrPendingClass(string name)
395 {
396 RuntimeJavaType javaType;
397
398 lock (types)
399 {
400 if (types.TryGetValue(name, out javaType) && javaType == null)
401 {
402 if (defineClassInProgress.TryGetValue(name, out var defineThread))
403 {
404 if (Thread.CurrentThread == defineThread)
405 throw new ClassCircularityError(name);
406
407 // the requested class is currently being defined by another thread, so we have to wait on that
408 while (defineClassInProgress.ContainsKey(name))
409 Monitor.Wait(types);
410
411 // the defineClass may have failed, so we need to use TryGetValue
412 types.TryGetValue(name, out javaType);
413 }
414 }
415 }
416
417 return javaType;
418 }
419
426 RuntimeJavaType FindOrLoadArrayClass(string name, LoadMode mode)
427 {
428 // calculate number of dimensions of type name
429 int pos = 1;
430 while (name[pos] == '[')
431 if (++pos == name.Length)
432 return null; // malformed class name
433
434 // type signature is an Object
435 if (name[pos] == 'L')
436 {
437 // must end with ';', and not contain improper array characters
438 if (name.EndsWith(";") == false || name.Length <= pos + 2 || name[pos + 1] == '[')
439 return null; // malformed class name
440
441 var elemClass = name.Substring(pos + 1, name.Length - pos - 2);
442
443 // it's important that we're registered as the initiating loader for the element type here
444 var type = LoadClass(elemClass, mode | LoadMode.DontReturnUnloadable);
445 if (type != null)
446 type = CreateArrayType(name, type, pos);
447
448 return type;
449 }
450
451 if (name.Length != pos + 1)
452 return null; // malformed class name
453
454 // array of primitive type
455 return name[pos] switch
456 {
457 'B' => CreateArrayType(name, context.PrimitiveJavaTypeFactory.BYTE, pos),
458 'C' => CreateArrayType(name, context.PrimitiveJavaTypeFactory.CHAR, pos),
459 'D' => CreateArrayType(name, context.PrimitiveJavaTypeFactory.DOUBLE, pos),
460 'F' => CreateArrayType(name, context.PrimitiveJavaTypeFactory.FLOAT, pos),
461 'I' => CreateArrayType(name, context.PrimitiveJavaTypeFactory.INT, pos),
462 'J' => CreateArrayType(name, context.PrimitiveJavaTypeFactory.LONG, pos),
463 'S' => CreateArrayType(name, context.PrimitiveJavaTypeFactory.SHORT, pos),
464 'Z' => CreateArrayType(name, context.PrimitiveJavaTypeFactory.BOOLEAN, pos),
465 _ => null,
466 };
467 }
468
469 internal RuntimeJavaType FindOrLoadGenericClass(string name, LoadMode mode)
470 {
471 // we don't want to expose any failures to load any of the component types
472 mode = (mode & LoadMode.MaskReturn) | LoadMode.ReturnNull;
473
474 // we need to handle delegate methods here (for generic delegates)
475 // (note that other types with manufactured inner classes such as Attribute and Enum can't be generic)
476 if (name.EndsWith(RuntimeManagedJavaType.DelegateInterfaceSuffix))
477 {
478 var outer = FindOrLoadGenericClass(name.Substring(0, name.Length - RuntimeManagedJavaType.DelegateInterfaceSuffix.Length), mode);
479 if (outer != null && outer.IsFakeTypeContainer)
480 foreach (var javaType in outer.InnerClasses)
481 if (javaType.Name == name)
482 return javaType;
483 }
484
485 // generic class name grammar:
486 //
487 // mangled(open_generic_type_name) "_$$$_" M(parameter_class_name) ( "_$$_" M(parameter_class_name) )* "_$$$$_"
488 //
489 // mangled() is the normal name mangling algorithm
490 // M() is a replacement of "__" with "$$005F$$005F" followed by a replace of "." with "__"
491 //
492 var pos = name.IndexOf("_$$$_");
493 if (pos <= 0 || !name.EndsWith("_$$$$_"))
494 return null;
495
496 var def = LoadClass(name.Substring(0, pos), mode);
497 if (def == null || !def.TypeAsTBD.IsGenericTypeDefinition)
498 return null;
499
500 var type = def.TypeAsTBD;
501 var typeParamNames = new List<string>();
502 pos += 5;
503 int start = pos;
504 int nest = 0;
505 for (; ; )
506 {
507 pos = name.IndexOf("_$$", pos);
508 if (pos == -1)
509 return null;
510
511 if (name.IndexOf("_$$_", pos, 4) == pos)
512 {
513 if (nest == 0)
514 {
515 typeParamNames.Add(name.Substring(start, pos - start));
516 start = pos + 4;
517 }
518
519 pos += 4;
520 }
521 else if (name.IndexOf("_$$$_", pos, 5) == pos)
522 {
523 nest++;
524 pos += 5;
525 }
526 else if (name.IndexOf("_$$$$_", pos, 6) == pos)
527 {
528 if (nest == 0)
529 {
530 if (pos + 6 != name.Length)
531 {
532 return null;
533 }
534 typeParamNames.Add(name.Substring(start, pos - start));
535 break;
536 }
537 nest--;
538 pos += 6;
539 }
540 else
541 {
542 pos += 3;
543 }
544 }
545
546 var typeArguments = new Type[typeParamNames.Count];
547 for (int i = 0; i < typeArguments.Length; i++)
548 {
549 var s = typeParamNames[i];
550 // only do the unmangling for non-generic types (because we don't want to convert
551 // the double underscores in two adjacent _$$$_ or _$$$$_ markers)
552 if (s.IndexOf("_$$$_") == -1)
553 {
554 s = s.Replace("__", ".");
555 s = s.Replace("$$005F$$005F", "__");
556 }
557
558 int dims = 0;
559 while (s.Length > dims && s[dims] == 'A')
560 dims++;
561
562 if (s.Length == dims)
563 return null;
564
565 RuntimeJavaType tw;
566 switch (s[dims])
567 {
568 case 'L':
569 tw = LoadClass(s.Substring(dims + 1), mode);
570 if (tw == null)
571 {
572 return null;
573 }
574 tw.Finish();
575 break;
576 case 'Z':
577 tw = context.PrimitiveJavaTypeFactory.BOOLEAN;
578 break;
579 case 'B':
580 tw = context.PrimitiveJavaTypeFactory.BYTE;
581 break;
582 case 'S':
583 tw = context.PrimitiveJavaTypeFactory.SHORT;
584 break;
585 case 'C':
586 tw = context.PrimitiveJavaTypeFactory.CHAR;
587 break;
588 case 'I':
589 tw = context.PrimitiveJavaTypeFactory.INT;
590 break;
591 case 'F':
592 tw = context.PrimitiveJavaTypeFactory.FLOAT;
593 break;
594 case 'J':
595 tw = context.PrimitiveJavaTypeFactory.LONG;
596 break;
597 case 'D':
598 tw = context.PrimitiveJavaTypeFactory.DOUBLE;
599 break;
600 default:
601 return null;
602 }
603
604 if (dims > 0)
605 tw = tw.MakeArrayType(dims);
606
607 typeArguments[i] = tw.TypeAsSignatureType;
608 }
609
610 try
611 {
612 type = type.MakeGenericType(typeArguments);
613 }
614 catch (ArgumentException)
615 {
616 // one of the typeArguments failed to meet the constraints
617 return null;
618 }
619
620 var wrapper = context.ClassLoaderFactory.GetJavaTypeFromType(type);
621 if (wrapper != null && wrapper.Name != name)
622 {
623 // the name specified was not in canonical form
624 return null;
625 }
626
627 return wrapper;
628 }
629
630 protected virtual RuntimeJavaType LoadClassImpl(string name, LoadMode mode)
631 {
632 var javaType = FindOrLoadGenericClass(name, mode);
633 if (javaType != null)
634 return javaType;
635
636#if !FIRST_PASS && !IMPORTER && !EXPORTER
637
638 if ((mode & LoadMode.Load) == 0)
639 return null;
640
641 Profiler.Enter("ClassLoader.loadClass");
642
643 try
644 {
645 // invoke 'loadClass' on the associated Java class loader instance
646 // this can cause a call to defineClass
647 var c = (java.lang.Class)ClassLoaderAccessor.InvokeLoadClassInternal(GetJavaClassLoader(), name);
648 if (c == null)
649 return null;
650
651 // map resulting reflective instance back into Java type
652 var type = RuntimeJavaType.FromClass(c);
653 if (type.Name != name)
654 return null;
655
656 return type;
657 }
658 catch (java.lang.ClassNotFoundException x)
659 {
660 if ((mode & LoadMode.MaskReturn) == LoadMode.ThrowClassNotFound)
661 throw new ClassLoadingException(ikvm.runtime.Util.mapException(x), name);
662
663 return null;
664 }
665 catch (global::java.lang.ThreadDeath)
666 {
667 throw;
668 }
669 catch (Exception x)
670 {
671 if ((mode & LoadMode.SuppressExceptions) == 0)
672 throw new ClassLoadingException(ikvm.runtime.Util.mapException(x), name);
673
674 if (Diagnostics.IsEnabled(Diagnostic.GenericClassLoadingError))
675 {
676 var cl = GetJavaClassLoader();
677 if (cl != null)
678 {
679 var sb = new ValueStringBuilder();
680 var sep = "";
681 while (cl != null)
682 {
683 sb.Append(sep);
684 sb.Append(cl.ToString());
685 sep = " -> ";
686 cl = cl.getParent();
687 }
688
689 Diagnostics.GenericClassLoadingError($"ClassLoader chain: {sb.ToString()}");
690 }
691
692 var m = ikvm.runtime.Util.mapException(x);
693 Diagnostics.GenericClassLoadingError(m.ToString() + Environment.NewLine + m.StackTrace);
694 }
695
696 return null;
697 }
698 finally
699 {
700 Profiler.Leave("ClassLoader.loadClass");
701 }
702#else
703 return null;
704#endif
705 }
706
714 static RuntimeJavaType CreateArrayType(string name, RuntimeJavaType elementJavaType, int dimensions)
715 {
716 Debug.Assert(new string('[', dimensions) + elementJavaType.SigName == name);
717 Debug.Assert(!elementJavaType.IsUnloadable && !elementJavaType.IsVerifierType && !elementJavaType.IsArray);
718 Debug.Assert(dimensions >= 1);
719
720 return elementJavaType.ClassLoader.RegisterInitiatingLoader(new RuntimeArrayJavaType(elementJavaType.Context, elementJavaType, name));
721 }
722
723#if !IMPORTER && !EXPORTER
724
729 internal virtual java.lang.ClassLoader GetJavaClassLoader()
730 {
731#if FIRST_PASS
732 throw new NotImplementedException();
733#else
734 return javaClassLoader;
735#endif
736 }
737#endif
738
747 internal Type[] ArgTypeListFromSig(string signature)
748 {
749 if (signature[1] == ')')
750 return Type.EmptyTypes;
751
752 var javaTypes = ArgJavaTypeListFromSig(signature, LoadMode.LoadOrThrow);
753 var types = new Type[javaTypes.Length];
754 for (int i = 0; i < javaTypes.Length; i++)
755 types[i] = javaTypes[i].TypeAsSignatureType;
756
757 return types;
758 }
759
771 RuntimeJavaType SigDecoderWrapper(ref int index, string signature, LoadMode mode)
772 {
773 switch (signature[index++])
774 {
775 case 'B':
776 return context.PrimitiveJavaTypeFactory.BYTE;
777 case 'C':
778 return context.PrimitiveJavaTypeFactory.CHAR;
779 case 'D':
780 return context.PrimitiveJavaTypeFactory.DOUBLE;
781 case 'F':
782 return context.PrimitiveJavaTypeFactory.FLOAT;
783 case 'I':
784 return context.PrimitiveJavaTypeFactory.INT;
785 case 'J':
786 return context.PrimitiveJavaTypeFactory.LONG;
787 case 'L':
788 {
789 int pos = index;
790 index = signature.IndexOf(';', index) + 1;
791 return LoadClass(signature.Substring(pos, index - pos - 1), mode);
792 }
793 case 'S':
794 return context.PrimitiveJavaTypeFactory.SHORT;
795 case 'Z':
796 return context.PrimitiveJavaTypeFactory.BOOLEAN;
797 case 'V':
798 return context.PrimitiveJavaTypeFactory.VOID;
799 case '[':
800 {
801 // TODO this can be optimized
802 // should be able to navigate over the original sig and pass spans
803
804 var array = "[";
805 while (signature[index] == '[')
806 {
807 index++;
808 array += "[";
809 }
810
811 switch (signature[index])
812 {
813 case 'L':
814 {
815 var pos = index;
816 index = signature.IndexOf(';', index) + 1;
817 return LoadClass(array + signature.Substring(pos, index - pos), mode);
818 }
819 case 'B':
820 case 'C':
821 case 'D':
822 case 'F':
823 case 'I':
824 case 'J':
825 case 'S':
826 case 'Z':
827 return LoadClass(array + signature[index++], mode);
828 default:
829 throw new InvalidOperationException(signature.Substring(index));
830 }
831 }
832 default:
833 throw new InvalidOperationException(signature.Substring(index));
834 }
835 }
836
837 internal RuntimeJavaType FieldTypeWrapperFromSig(string sig, LoadMode mode)
838 {
839 int index = 0;
840 return SigDecoderWrapper(ref index, sig, mode);
841 }
842
843 internal RuntimeJavaType RetTypeWrapperFromSig(string sig, LoadMode mode)
844 {
845 int index = sig.IndexOf(')') + 1;
846 return SigDecoderWrapper(ref index, sig, mode);
847 }
848
849 internal RuntimeJavaType[] ArgJavaTypeListFromSig(string sig, LoadMode mode)
850 {
851 if (sig[1] == ')')
852 return [];
853
854 var list = new List<RuntimeJavaType>();
855 for (int i = 1; sig[i] != ')';)
856 list.Add(SigDecoderWrapper(ref i, sig, mode));
857
858 return list.ToArray();
859 }
860
861#if !IMPORTER && !FIRST_PASS && !EXPORTER
862
863 internal static object DoPrivileged(java.security.PrivilegedAction action)
864 {
865 return java.security.AccessController.doPrivileged(action, ikvm.@internal.CallerID.create(typeof(java.lang.ClassLoader).TypeHandle));
866 }
867
868#endif
869
870 internal void RegisterNativeLibrary(IntPtr p)
871 {
872 lock (this)
873 {
874 try
875 {
876 // critical code in the finally block to avoid Thread.Abort interrupting the thread
877 }
878 finally
879 {
880 nativeLibraries ??= new List<IntPtr>();
881 nativeLibraries.Add(p);
882 }
883 }
884 }
885
886 internal void UnregisterNativeLibrary(IntPtr p)
887 {
888 lock (this)
889 {
890 try
891 {
892 // critical code in the finally block to avoid Thread.Abort interrupting the thread
893 }
894 finally
895 {
896 nativeLibraries.Remove(p);
897 }
898 }
899 }
900
901 internal nint[] GetNativeLibraries()
902 {
903 lock (this)
904 return nativeLibraries == null ? Array.Empty<nint>() : nativeLibraries.ToArray();
905 }
906
907#if !IMPORTER && !FIRST_PASS && !EXPORTER
908
909 public override string ToString()
910 {
911 var javaClassLoader = GetJavaClassLoader();
912 if (javaClassLoader == null)
913 return "null";
914 else
915 return string.Format("{0}@{1:X}", Context.ClassLoaderFactory.GetJavaTypeFromType(javaClassLoader.GetType()).Name, javaClassLoader.GetHashCode());
916 }
917
918#endif
919
920 internal virtual bool InternalsVisibleToImpl(RuntimeJavaType wrapper, RuntimeJavaType friend)
921 {
922 Debug.Assert(wrapper.ClassLoader == this);
923 return this == friend.ClassLoader;
924 }
925
926#if !IMPORTER && !EXPORTER
927
928 // this method is used by IKVM.Runtime.JNI
929 internal static RuntimeClassLoader FromCallerID(ikvm.@internal.CallerID callerID)
930 {
931#if FIRST_PASS
932 return null;
933#else
934 return JVM.Context.ClassLoaderFactory.GetClassLoaderWrapper(callerID.getCallerClassLoader());
935#endif
936 }
937
938#endif
939
940 internal void CheckPackageAccess(RuntimeJavaType tw, ProtectionDomain pd)
941 {
942#if !IMPORTER && !FIRST_PASS && !EXPORTER
943 if (javaClassLoader != null)
944 ClassLoaderAccessor.InvokeCheckPackageAccess(javaClassLoader, tw.ClassObject, pd);
945#endif
946 }
947
948#if !EXPORTER
949
951 {
952 get
953 {
954#if IMPORTER
955 var cfp = ClassFileParseOptions.LocalVariableTable | ClassFileParseOptions.StaticImport;
956 if (EmitStackTraceInfo)
957 cfp |= ClassFileParseOptions.LineNumberTable;
958 if (context.ClassLoaderFactory.bootstrapClassLoader is ImportClassLoader)
959 cfp |= ClassFileParseOptions.TrustedAnnotations;
960 if (RemoveAsserts)
961 cfp |= ClassFileParseOptions.RemoveAssertions;
962 return cfp;
963#else
964 var cfp = ClassFileParseOptions.LineNumberTable;
965 if (EmitSymbols)
966 cfp |= ClassFileParseOptions.LocalVariableTable;
967 if (RelaxedClassNameValidation)
968 cfp |= ClassFileParseOptions.RelaxedClassNameValidation;
969 if (this == Context.ClassLoaderFactory.bootstrapClassLoader)
970 cfp |= ClassFileParseOptions.TrustedAnnotations;
971
972 return cfp;
973#endif
974 }
975 }
976
977#endif
978
979 internal virtual bool WarningLevelHigh
980 {
981 get { return false; }
982 }
983
984 internal virtual bool NoParameterReflection
985 {
986 get { return false; }
987 }
988
989 }
990
991}
java.security.ProtectionDomain ProtectionDomain
IKVM.Reflection.Type Type
static readonly Diagnostic GenericClassLoadingError
The 'GenericClassLoadingError' diagnostic.
This is not a Java exception, but instead it wraps a Java exception that was thrown by a class loader...
DynamicClassLoader GetOrCreate(RuntimeClassLoader loader)
Gets the DynamicClassLoader instance which should be used for dynamic classes emitted by the given cl...
Main state of the running JVM.
Runtime support for a class loader.
RuntimeContext Context
Gets a reference to the RuntimeContext that this RuntimeClassLoader is hosted within.
virtual RuntimeJavaType FindLoadedClassLazy(string name)
virtual void CheckProhibitedPackage(string className)
virtual RuntimeJavaType LoadClassImpl(string name, LoadMode mode)
java.lang.ClassLoader javaClassLoader
Maintains services relevant to an instane of the IKVM runtime.
IDiagnosticHandler Diagnostics
Gets the IDiagnosticHandler where events should be sent.
DynamicClassLoaderFactory DynamicClassLoaderFactory
Gets the DynamicClassLoaderFactory 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.
Implements a RuntimeJavaType that exposes existing managed .NET types not the result of static compil...
Implementation of RuntimeClassLoader that emits loaded Java types to an AssemblyBuilder.
Exposes methods to accept diagnostic invocations.