IKVM11  11
Java SE 11 Virtual Machine for .NET
Loading...
Searching...
No Matches
DynamicClassLoaderFactory.cs
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2014 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;
26using System.Collections.Concurrent;
27
28
29#if IMPORTER
30using IKVM.Reflection;
33
34using Type = IKVM.Reflection.Type;
35using ProtectionDomain = System.Object;
36#else
37using System.Reflection;
38#endif
39
40namespace IKVM.Runtime
41{
46 {
47
48 readonly RuntimeContext context;
49 internal readonly ConcurrentDictionary<string, RuntimeJavaType> dynamicTypes = new();
50 DynamicClassLoader instance;
51
58 {
59 this.context = context ?? throw new ArgumentNullException(nameof(context));
60
61#if IMPORTER == false
62 // we attach to the AppDomain.TypeResolve event to be notified when the CLR cannot find a type, and we must provide it
63 AppDomain.CurrentDomain.TypeResolve += new ResolveEventHandler(OnTypeResolve);
64
65 // exclude '<Module>' as a valid type name, as it overlaps with the pseudo-type for global fields and methods
66 dynamicTypes.TryAdd("<Module>", null);
67#endif
68 }
69
70#if IMPORTER == false
71
78 Assembly OnTypeResolve(object sender, ResolveEventArgs args)
79 {
80 return Resolve(dynamicTypes, args.Name);
81 }
82
89 Assembly Resolve(ConcurrentDictionary<string, RuntimeJavaType> dict, string name)
90 {
91 if (dict.TryGetValue(name, out var type))
92 {
93 try
94 {
95 type.Finish();
96 return type.TypeAsTBD.Assembly;
97 }
98 catch (RetargetableJavaException e)
99 {
100 throw e.ToJava();
101 }
102 }
103
104 return null;
105 }
106
107#endif
108
114 [System.Security.SecuritySafeCritical]
115 public DynamicClassLoader GetOrCreate(RuntimeClassLoader loader)
116 {
117#if IMPORTER
118 // importer uses only one class loader, and we can just return a single dynamic class loader
119 return new DynamicClassLoader(context, loader.Diagnostics, ((ImportClassLoader)loader).CreateModuleBuilder(), false);
120#else
121 // each assembly class loader gets its own dynamic class loader
122 if (loader is RuntimeAssemblyClassLoader acl)
123 {
124 var name = acl.MainAssembly.GetName().Name + context.Options.DynamicAssemblySuffixAndPublicKey;
125 foreach (var attr in acl.MainAssembly.GetCustomAttributes<InternalsVisibleToAttribute>())
126 {
127 if (attr.AssemblyName == name)
128 {
129 var n = new AssemblyName(name);
130#if NETFRAMEWORK
131 n.KeyPair = DynamicClassLoader.ForgedKeyPair.Instance;
132#endif
133 return new DynamicClassLoader(context, loader.Diagnostics, DynamicClassLoader.CreateModuleBuilder(context, n), true);
134 }
135 }
136 }
137
138 return instance ??= new DynamicClassLoader(context, loader.Diagnostics, DynamicClassLoader.CreateModuleBuilder(context), false);
139#endif
140 }
141
147 public bool ReserveName(string name)
148 {
149 return dynamicTypes.TryAdd(name, null);
150 }
151
159 public static string TypeNameMangleImpl(ConcurrentDictionary<string, RuntimeJavaType> dict, string name, RuntimeJavaType javaType)
160 {
161 // the CLR maximum type name length is 1023 characters, but we need to leave some room for the suffix that we may need to append to make the name unique
162 const int MaxLength = 1000;
163
164 if (name.Length > MaxLength)
165 name = name.Substring(0, MaxLength) + "/truncated";
166
167 var mangledTypeName = TypeNameUtil.ReplaceIllegalCharacters(name);
168 var baseTypeName = mangledTypeName;
169 int instanceId = 0;
170
171 // advance through unique type names until we find a free one
172 while (dict.TryAdd(mangledTypeName, javaType) == false)
173 {
174 javaType.ClassLoader.Diagnostics.GenericCompilerWarning($"Class name clash: {mangledTypeName}");
175 mangledTypeName = baseTypeName + "/" + (++instanceId);
176 }
177
178 return mangledTypeName;
179 }
180
181 }
182
183}
java.security.ProtectionDomain ProtectionDomain
IKVM.Reflection.Type Type
IKVM.Reflection.Assembly Assembly
IKVM.Reflection.AssemblyName AssemblyName
Maintains instances of DynamicClassLoader.
static string TypeNameMangleImpl(ConcurrentDictionary< string, RuntimeJavaType > dict, string name, RuntimeJavaType javaType)
Associated the given Java type with the given type name, ensuring the actual stored name is unique.
bool ReserveName(string name)
Reserves the given type name.
DynamicClassLoader GetOrCreate(RuntimeClassLoader loader)
Gets the DynamicClassLoader instance which should be used for dynamic classes emitted by the given cl...
DynamicClassLoaderFactory(RuntimeContext context)
Initializes a new instance.
Runtime support for a class loader.
virtual IDiagnosticHandler Diagnostics
Gets the IDiagnosticHandler events originated by this class loader should be sent to.
Maintains services relevant to an instane of the IKVM runtime.
Implementation of RuntimeClassLoader that emits loaded Java types to an AssemblyBuilder.
void GenericCompilerWarning(string arg0)
The 'GenericCompilerWarning' diagnostic.