IKVM11  11
Java SE 11 Virtual Machine for .NET
Loading...
Searching...
No Matches
RuntimeClassLoaderFactory.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
29
30#if NETCOREAPP
31using System.Runtime.Loader;
32#endif
33
34#if IMPORTER || EXPORTER
35using IKVM.Reflection;
36
37using Type = IKVM.Reflection.Type;
38using ProtectionDomain = System.Object;
39#else
40using System.Reflection;
41#endif
42
43#if IMPORTER
45#endif
46
47namespace IKVM.Runtime
48{
53 {
54
55 readonly RuntimeContext context;
56 readonly object wrapperLock = new object();
57 internal readonly Dictionary<Type, RuntimeJavaType> globalTypeToTypeWrapper = new Dictionary<Type, RuntimeJavaType>();
58 internal readonly Dictionary<Type, string> remappedTypes = new Dictionary<Type, string>();
59 readonly List<RuntimeGenericClassLoader> genericClassLoaders = new List<RuntimeGenericClassLoader>();
60
61#if IMPORTER || EXPORTER
62 internal RuntimeClassLoader bootstrapClassLoader;
63#else
64 internal RuntimeAssemblyClassLoader bootstrapClassLoader;
65#endif
66
71 {
72 this.context = context;
73
74 globalTypeToTypeWrapper[context.PrimitiveJavaTypeFactory.BOOLEAN.TypeAsTBD] = context.PrimitiveJavaTypeFactory.BOOLEAN;
75 globalTypeToTypeWrapper[context.PrimitiveJavaTypeFactory.BYTE.TypeAsTBD] = context.PrimitiveJavaTypeFactory.BYTE;
76 globalTypeToTypeWrapper[context.PrimitiveJavaTypeFactory.CHAR.TypeAsTBD] = context.PrimitiveJavaTypeFactory.CHAR;
77 globalTypeToTypeWrapper[context.PrimitiveJavaTypeFactory.DOUBLE.TypeAsTBD] = context.PrimitiveJavaTypeFactory.DOUBLE;
78 globalTypeToTypeWrapper[context.PrimitiveJavaTypeFactory.FLOAT.TypeAsTBD] = context.PrimitiveJavaTypeFactory.FLOAT;
79 globalTypeToTypeWrapper[context.PrimitiveJavaTypeFactory.INT.TypeAsTBD] = context.PrimitiveJavaTypeFactory.INT;
80 globalTypeToTypeWrapper[context.PrimitiveJavaTypeFactory.LONG.TypeAsTBD] = context.PrimitiveJavaTypeFactory.LONG;
81 globalTypeToTypeWrapper[context.PrimitiveJavaTypeFactory.SHORT.TypeAsTBD] = context.PrimitiveJavaTypeFactory.SHORT;
82 globalTypeToTypeWrapper[context.PrimitiveJavaTypeFactory.VOID.TypeAsTBD] = context.PrimitiveJavaTypeFactory.VOID;
83 LoadRemappedTypes();
84 }
85
86#if IMPORTER || EXPORTER
87
88 // HACK this is used by the ahead-of-time compiler to overrule the bootstrap classloader
89 // when we're compiling the core class libraries and by ikvmstub with the -bootstrap option
90 internal void SetBootstrapClassLoader(RuntimeClassLoader bootstrapClassLoader)
91 {
92 Debug.Assert(this.bootstrapClassLoader == null);
93
94 this.bootstrapClassLoader = bootstrapClassLoader;
95 }
96
97#endif
98
99 internal void LoadRemappedTypes()
100 {
101 // if we're compiling the base assembly, we won't be able to resolve one
102 var baseAssembly = context.Resolver.ResolveBaseAssembly().AsReflection();
103 if (baseAssembly != null && remappedTypes.Count == 0)
104 {
105 var remapped = context.AttributeHelper.GetRemappedClasses(baseAssembly);
106 if (remapped.Length > 0)
107 {
108 foreach (var r in remapped)
109 remappedTypes.Add(r.RemappedType, r.Name);
110 }
111 else
112 {
113#if IMPORTER
115#else
116 throw new InternalException("Failed to find core classes in core library.");
117#endif
118 }
119 }
120 }
121
122 internal bool IsRemappedType(Type type)
123 {
124 return remappedTypes.ContainsKey(type);
125 }
126
127#if IMPORTER || EXPORTER
128 internal RuntimeClassLoader GetBootstrapClassLoader()
129#else
130 internal RuntimeAssemblyClassLoader GetBootstrapClassLoader()
131#endif
132 {
133 lock (wrapperLock)
134 return bootstrapClassLoader ??= new BootstrapClassLoader(context);
135 }
136
137#if !IMPORTER && !EXPORTER
138
139 internal RuntimeClassLoader GetClassLoaderWrapper(java.lang.ClassLoader javaClassLoader)
140 {
141 if (javaClassLoader == null)
142 return GetBootstrapClassLoader();
143
144 lock (wrapperLock)
145 {
146#if FIRST_PASS
147 RuntimeClassLoader wrapper = null;
148#else
149 RuntimeClassLoader wrapper = javaClassLoader.wrapper;
150#endif
151
152 if (wrapper == null)
153 {
154 var opt = CodeGenOptions.None;
155 if (JVM.EmitSymbols)
156 opt |= CodeGenOptions.DisableOptimizations;
157#if NETFRAMEWORK
158 if (!AppDomain.CurrentDomain.IsFullyTrusted)
159 opt |= CodeGenOptions.NoAutomagicSerialization;
160#endif
161 wrapper = new RuntimeClassLoader(context, opt, javaClassLoader);
162 SetWrapperForClassLoader(javaClassLoader, wrapper);
163 }
164 return wrapper;
165 }
166 }
167#endif
168
174 internal RuntimeJavaType GetJavaTypeFromType(Type type)
175 {
176#if IMPORTER
177 if (type.__ContainsMissingType)
178 {
179 return new RuntimeUnloadableJavaType(context, type);
180 }
181#endif
182 //Tracer.Info(Tracer.Runtime, "GetWrapperFromType: {0}", type.AssemblyQualifiedName);
183#if !IMPORTER
184 RuntimeJavaType.AssertFinished(type);
185#endif
186 Debug.Assert(!type.IsPointer);
187 Debug.Assert(!type.IsByRef);
188
189 RuntimeJavaType wrapper;
190 lock (globalTypeToTypeWrapper)
191 globalTypeToTypeWrapper.TryGetValue(type, out wrapper);
192
193 if (wrapper != null)
194 return wrapper;
195
196#if EXPORTER
197 if (type.__IsMissing || type.__ContainsMissingType)
198 {
199 wrapper = new RuntimeUnloadableJavaType(context, type);
200 globalTypeToTypeWrapper.Add(type, wrapper);
201 return wrapper;
202 }
203#endif
204
205 if (remappedTypes.TryGetValue(type, out var remapped))
206 {
207 wrapper = LoadClassCritical(remapped);
208 }
209 else if (ReflectUtil.IsVector(type))
210 {
211 // it might be an array of a dynamically compiled Java type
212 int rank = 1;
213 Type elem = type.GetElementType();
214 while (ReflectUtil.IsVector(elem))
215 {
216 rank++;
217 elem = elem.GetElementType();
218 }
219
220 wrapper = GetJavaTypeFromType(elem).MakeArrayType(rank);
221 }
222 else
223 {
224 var asm = type.Assembly;
225
226#if !IMPORTER && !EXPORTER
227 if (RuntimeAnonymousJavaType.IsAnonymous(context, type))
228 {
229 var typeToTypeWrapper = globalTypeToTypeWrapper;
230 var tw = new RuntimeAnonymousJavaType(context, type);
231 lock (typeToTypeWrapper)
232 if (!typeToTypeWrapper.TryGetValue(type, out wrapper))
233 typeToTypeWrapper.Add(type, wrapper = tw);
234
235 return wrapper;
236 }
237
238 if (ReflectUtil.IsReflectionOnly(type))
239 {
240 // historically we've always returned null for types that don't have a corresponding TypeWrapper (or java.lang.Class)
241 return null;
242 }
243#endif
244 // if the wrapper doesn't already exist, that must mean that the type
245 // is a .NET type (or a pre-compiled Java class), which means that it
246 // was "loaded" by an assembly classloader
247 wrapper = context.AssemblyClassLoaderFactory.FromAssembly(asm).GetJavaTypeFromAssemblyType(type);
248 }
249
250 lock (globalTypeToTypeWrapper)
251 {
252 try
253 {
254 // critical code in the finally block to avoid Thread.Abort interrupting the thread
255 }
256 finally
257 {
258 globalTypeToTypeWrapper[type] = wrapper;
259 }
260 }
261
262 return wrapper;
263 }
264
265 internal RuntimeClassLoader GetGenericClassLoader(RuntimeJavaType wrapper)
266 {
267 Type type = wrapper.TypeAsTBD;
268 Debug.Assert(type.IsGenericType);
269 Debug.Assert(!type.ContainsGenericParameters);
270
271 List<RuntimeClassLoader> list = new List<RuntimeClassLoader>();
272 list.Add(context.AssemblyClassLoaderFactory.FromAssembly(type.Assembly));
273 foreach (Type arg in type.GetGenericArguments())
274 {
275 RuntimeClassLoader loader = GetJavaTypeFromType(arg).ClassLoader;
276 if (!list.Contains(loader) && loader != bootstrapClassLoader)
277 {
278 list.Add(loader);
279 }
280 }
281 RuntimeClassLoader[] key = list.ToArray();
282 RuntimeClassLoader matchingLoader = GetGenericClassLoaderByKey(key);
283 matchingLoader.RegisterInitiatingLoader(wrapper);
284 return matchingLoader;
285 }
286
287 internal RuntimeJavaType LoadClassCritical(string name)
288 {
289#if IMPORTER
290 var wrapper = GetBootstrapClassLoader().TryLoadClassByName(name);
291 if (wrapper == null)
293
294 return wrapper;
295#else
296 try
297 {
298 return GetBootstrapClassLoader().LoadClassByName(name);
299 }
300 catch (Exception e)
301 {
302 throw new InternalException("Loading of critical class failed.", e);
303 }
304#endif
305 }
306
307 RuntimeClassLoader GetGenericClassLoaderByKey(RuntimeClassLoader[] key)
308 {
309 lock (wrapperLock)
310 {
311 foreach (RuntimeGenericClassLoader loader in genericClassLoaders)
312 if (loader.Matches(key))
313 return loader;
314
315#if IMPORTER || EXPORTER || FIRST_PASS
316 var newLoader = new RuntimeGenericClassLoader(context, key, null);
317#else
318 var javaClassLoader = new ikvm.runtime.GenericClassLoader();
319 var newLoader = new RuntimeGenericClassLoader(context, key, javaClassLoader);
320 SetWrapperForClassLoader(javaClassLoader, newLoader);
321#endif
322 genericClassLoaders.Add(newLoader);
323 return newLoader;
324 }
325 }
326
327#if !IMPORTER && !EXPORTER
328
329 public void SetWrapperForClassLoader(java.lang.ClassLoader javaClassLoader, RuntimeClassLoader wrapper)
330 {
331#if FIRST_PASS
332 throw new NotImplementedException();
333#else
334 javaClassLoader.wrapper = wrapper;
335#endif
336 }
337
338#endif
339
340#if !IMPORTER && !EXPORTER
341
342 internal RuntimeClassLoader GetGenericClassLoaderByName(string name)
343 {
344 Debug.Assert(name.StartsWith("[[") && name.EndsWith("]]"));
345
346 var stack = new Stack<List<RuntimeClassLoader>>();
347 List<RuntimeClassLoader> list = null;
348
349 for (int i = 0; i < name.Length; i++)
350 {
351 if (name[i] == '[')
352 {
353 if (name[i + 1] == '[')
354 {
355 stack.Push(list);
356 list = new List<RuntimeClassLoader>();
357 if (name[i + 2] == '[')
358 {
359 i++;
360 }
361 }
362 else
363 {
364 int start = i + 1;
365 i = name.IndexOf(']', i);
366 list.Add(context.ClassLoaderFactory.GetAssemblyClassLoaderByName(name.Substring(start, i - start)));
367 }
368 }
369 else if (name[i] == ']')
370 {
371 var loader = GetGenericClassLoaderByKey(list.ToArray());
372 list = stack.Pop();
373 if (list == null)
374 return loader;
375
376 list.Add(loader);
377 }
378 else
379 {
380 throw new InvalidOperationException();
381 }
382 }
383
384 throw new InvalidOperationException();
385 }
386
387 internal RuntimeClassLoader GetAssemblyClassLoaderByName(string name)
388 {
389 if (name.StartsWith("[["))
390 return GetGenericClassLoaderByName(name);
391
392#if NETFRAMEWORK
393 return context.AssemblyClassLoaderFactory.FromAssembly(Assembly.Load(name));
394#else
395 return context.AssemblyClassLoaderFactory.FromAssembly(AssemblyLoadContext.GetLoadContext(typeof(RuntimeClassLoader).Assembly).LoadFromAssemblyName(new AssemblyName(name)));
396#endif
397 }
398
399#endif
400
401 internal int GetGenericClassLoaderId(RuntimeClassLoader wrapper)
402 {
403 lock (wrapperLock)
404 return genericClassLoaders.IndexOf(wrapper as RuntimeGenericClassLoader);
405 }
406
407 internal RuntimeClassLoader GetGenericClassLoaderById(int id)
408 {
409 lock (wrapperLock)
410 return genericClassLoaders[id];
411 }
412
413 internal void SetWrapperForType(Type type, RuntimeJavaType wrapper)
414 {
415#if !IMPORTER
416 RuntimeJavaType.AssertFinished(type);
417#endif
418
419 lock (globalTypeToTypeWrapper)
420 {
421 try
422 {
423 // critical code in the finally block to avoid Thread.Abort interrupting the thread
424 }
425 finally
426 {
427 globalTypeToTypeWrapper.Add(type, wrapper);
428 }
429 }
430 }
431
432 }
433
434}
java.security.ProtectionDomain ProtectionDomain
IKVM.Reflection.Type Type
IKVM.Reflection.Assembly Assembly
IKVM.Reflection.AssemblyName AssemblyName
Manages instances of RuntimeClassLoader.
void SetWrapperForClassLoader(java.lang.ClassLoader javaClassLoader, RuntimeClassLoader wrapper)
RuntimeClassLoaderFactory(RuntimeContext context)
Initializes the static instance.
Runtime support for a class loader.
Maintains services relevant to an instane of the IKVM runtime.
RuntimePrimitiveJavaTypeFactory PrimitiveJavaTypeFactory
Gets the RuntimePrimitiveJavaTypeFactory associated with this instance of the runtime.
static DiagnosticEvent CoreClassesMissing(Exception? exception=null, DiagnosticLocation location=default)
The 'CoreClassesMissing' diagnostic.
static DiagnosticEvent CriticalClassNotFound(string arg0, Exception? exception=null, DiagnosticLocation location=default)
The 'CriticalClassNotFound' diagnostic.