IKVM11  11
Java SE 11 Virtual Machine for .NET
Loading...
Searching...
No Matches
JVM.Properties.cs
Go to the documentation of this file.
1using System;
2using System.Collections.Generic;
3using System.Configuration;
4using System.IO;
5using System.Linq;
6using System.Runtime.InteropServices;
7using System.Security;
8
10
11namespace IKVM.Runtime
12{
13
14 static partial class JVM
15 {
16
20 public static class Properties
21 {
22
26 internal record struct IkvmPropEntry(string BasePath, string Value);
27
28 static readonly IDictionary<string, string> user = new Dictionary<string, string>();
29 static readonly Lazy<Dictionary<string, IkvmPropEntry>> ikvm = new Lazy<Dictionary<string, IkvmPropEntry>>(GetIkvmProperties);
30 static readonly Lazy<Dictionary<string, string>> init = new Lazy<Dictionary<string, string>>(GetInitProperties);
31 static readonly Lazy<string> homePath = new Lazy<string>(GetHomePath);
32
38 public static IDictionary<string, string> User => user;
39
43 internal static IReadOnlyDictionary<string, IkvmPropEntry> Ikvm => ikvm.Value;
44
48 internal static IReadOnlyDictionary<string, string> Init => init.Value;
49
53 internal static string HomePath => homePath.Value;
54
59 static IEnumerable<string> GetIkvmPropertiesSearchPathsIter()
60 {
61 if (AppContext.BaseDirectory is string basePath && !string.IsNullOrEmpty(basePath))
62 yield return basePath;
63
64 if (AppDomain.CurrentDomain.BaseDirectory is string appBasePath && !string.IsNullOrEmpty(appBasePath))
65 yield return appBasePath;
66
67 // search upwards from the location of IKVM.Runtime
68 // we do this because IKVM.Runtime may be in runtimes/{rid}/lib
69 if (typeof(Properties).Assembly.Location is string runtimeAssemblyPath && !string.IsNullOrEmpty(runtimeAssemblyPath))
70 foreach (var parent in GetParentDirs(runtimeAssemblyPath))
71 yield return parent;
72 }
73
79 static IEnumerable<string> GetParentDirs(string path)
80 {
81 while (string.IsNullOrWhiteSpace(path = Path.GetDirectoryName(path)) == false)
82 yield return path;
83 }
84
89 static IEnumerable<string> GetIkvmPropertiesSearchPaths()
90 {
91 return GetIkvmPropertiesSearchPathsIter().Distinct();
92 }
93
98 static Dictionary<string, IkvmPropEntry> GetIkvmProperties()
99 {
100 var props = new Dictionary<string, IkvmPropEntry>();
101
102 foreach (var basePath in GetIkvmPropertiesSearchPaths())
103 {
104 var ikvmPropertiesPath = Path.Combine(basePath, "ikvm.properties");
105 if (File.Exists(ikvmPropertiesPath))
106 {
107 LoadProperties(basePath, File.ReadAllLines(ikvmPropertiesPath), props);
108 break;
109 }
110 }
111
112 return props;
113 }
114
119 static string GetHomePath()
120 {
121 // user value takes priority
122 if (User.TryGetValue("ikvm.home", out var userHomePath) && !string.IsNullOrWhiteSpace(userHomePath))
123 if (Directory.Exists(Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, userHomePath))))
124 return Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, userHomePath));
125
126 // ikvm properties value comes next
127 if (Ikvm.TryGetValue("ikvm.home", out var ikvmHomeEntry) && !string.IsNullOrWhiteSpace(ikvmHomeEntry.Value))
128 if (Directory.Exists(Path.GetFullPath(Path.Combine(ikvmHomeEntry.BasePath, ikvmHomeEntry.Value))))
129 return Path.GetFullPath(Path.Combine(ikvmHomeEntry.BasePath, ikvmHomeEntry.Value));
130
131#if NET
132 // specified home directory in runtime.json, where path is relative to application
133 if (AppContext.GetData("IKVM.Home") is string confHome && !string.IsNullOrWhiteSpace(confHome))
134 if (Directory.Exists(Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, confHome))))
135 return Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, confHome));
136#endif
137
138#if NETFRAMEWORK
139 // attempt to find settings in legacy app.config
140 try
141 {
142 // specified home directory in app.config relative to base directory
143 if (ConfigurationManager.AppSettings["ikvm:ikvm.home"] is string confHome && !string.IsNullOrWhiteSpace(confHome))
144 if (Directory.Exists(Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, confHome))))
145 return Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, confHome));
146 }
147 catch (ConfigurationException)
148 {
149 // app.config is invalid, ignore
150 }
151#endif
152
153 // find first occurance of home root
154 if (User.TryGetValue("ikvm.home.root", out var userHomeRoot) && !string.IsNullOrWhiteSpace(userHomeRoot))
155 if (ResolveHomePathFromRoot(Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, userHomeRoot))) is string userHomeRootPath)
156 return userHomeRootPath;
157
158 // ikvm properties value comes next
159 if (Ikvm.TryGetValue("ikvm.home.root", out var ikvmHomeRootEntry) && !string.IsNullOrWhiteSpace(ikvmHomeRootEntry.Value))
160 if (ResolveHomePathFromRoot(Path.GetFullPath(Path.Combine(ikvmHomeRootEntry.BasePath, ikvmHomeRootEntry.Value))) is string ikvmHomeRootPath)
161 return ikvmHomeRootPath;
162
163#if NET
164 // specified home root directory in runtime.json, where path is relative to application
165 if (AppContext.GetData("IKVM.Home.Root") is string confHomeRoot && !string.IsNullOrWhiteSpace(confHomeRoot))
166 if (ResolveHomePathFromRoot(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, confHomeRoot)) is string confHomeRootPath)
167 return confHomeRootPath;
168#endif
169
170#if NETFRAMEWORK
171 // attempt to find settings in legacy app.config
172 try
173 {
174 // specified home root directory in app.config relative to base directory
175 if (ConfigurationManager.AppSettings["ikvm:ikvm.home.root"] is string confHomeRoot && !string.IsNullOrWhiteSpace(confHomeRoot))
176 if (ResolveHomePathFromRoot(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, confHomeRoot)) is string confHomeRootPath)
177 return confHomeRootPath;
178 }
179 catch (ConfigurationException)
180 {
181 // app.config is invalid, ignore
182 }
183#endif
184
185 // fallback to directory in base dir
186 if (string.IsNullOrWhiteSpace(AppContext.BaseDirectory) == false)
187 if (ResolveHomePathFromRoot(Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, "ikvm"))) is string appHomeRootPath)
188 return appHomeRootPath;
189
190 // fallback to directory in base dir
191 if (string.IsNullOrWhiteSpace(AppDomain.CurrentDomain.BaseDirectory) == false)
192 if (ResolveHomePathFromRoot(Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "ikvm"))) is string domainHomeRootPath)
193 return domainHomeRootPath;
194
195 throw new InternalException("Could not locate ikvm home path.");
196 }
197
203 static string ResolveHomePathFromRoot(string homePathRoot)
204 {
205 // calculate ikvm.home from ikvm.home.root
206 if (Directory.Exists(homePathRoot))
207 {
208 foreach (var rid in RuntimeUtil.SupportedRuntimeIdentifiers)
209 {
210 var ikvmHomePath = Path.GetFullPath(Path.Combine(homePathRoot, rid));
211 if (Directory.Exists(ikvmHomePath))
212 return ikvmHomePath;
213 }
214 }
215
216 return null;
217 }
218
224 static void LoadProperties(string basePath, IEnumerable<string> lines, Dictionary<string, IkvmPropEntry> props)
225 {
226 foreach (var l in lines)
227 {
228 var a = l.Split(new[] { '=' }, 2, StringSplitOptions.RemoveEmptyEntries);
229 if (a.Length >= 2)
230 props[a[0].Trim()] = new IkvmPropEntry(basePath, a[1]?.Trim() ?? "");
231 }
232 }
233
238 static Dictionary<string, string> GetInitProperties()
239 {
240#if FIRST_PASS || IMPORTER || EXPORTER
241 throw new NotImplementedException();
242#else
243 var p = new Dictionary<string, string>();
244 InitSystemProperties(p);
245 return p;
246#endif
247 }
248
253 static void InitSystemProperties(Dictionary<string, string> p)
254 {
255#if FIRST_PASS || IMPORTER || EXPORTER
256 throw new NotImplementedException();
257#else
258 p["openjdk.version"] = Constants.openjdk_version;
259 p["java.vm.name"] = Constants.java_vm_name;
260 p["java.vm.version"] = Constants.java_vm_version;
261 p["java.vm.vendor"] = Constants.java_vm_vendor;
262 p["java.vm.specification.name"] = "Java Virtual Machine Specification";
263 p["java.vm.specification.version"] = Constants.java_vm_specification_version;
264 p["java.vm.specification.vendor"] = Constants.java_vm_specification_vendor;
265 p["java.vm.info"] = "compiled mode";
266 p["java.runtime.name"] = Constants.java_runtime_name;
267 p["java.runtime.version"] = Constants.java_runtime_version;
268
269 // various directory paths
270 p["ikvm.home"] = HomePath;
271 p["java.home"] = HomePath;
272 p["java.library.path"] = GetLibraryPath();
273 p["java.ext.dirs"] = Path.Combine(HomePath, "lib", "ext");
274 p["java.endorsed.dirs"] = Path.Combine(HomePath, "lib", "endorsed");
275 p["sun.boot.library.path"] = GetBootLibraryPath();
276 p["sun.boot.class.path"] = VfsTable.GetAssemblyClassesPath(Vfs.Context, Context.Resolver.ResolveBaseAssembly().AsReflection(), HomePath);
277 p["sun.cds.enableSharedLookupCache"] = "false";
278
279 // unlimited direct memory
280 p["sun.nio.MaxDirectMemorySize"] = "-1";
281
282 // default to FORK on OSX, instead of posix_spawn with jspawnhelper
283 if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
284 p["jdk.lang.Process.launchMechanism"] = "FORK";
285
286#if NETFRAMEWORK
287 // read properties from app.config
288 try
289 {
290 foreach (string key in ConfigurationManager.AppSettings)
291 if (key.StartsWith("ikvm:"))
292 p[key.Substring(5)] = ConfigurationManager.AppSettings[key];
293 }
294 catch (ConfigurationException)
295 {
296 // app.config is invalid, ignore
297 }
298#endif
299
300#if NET
301 if (AppContext.GetData("IKVM.Properties") is string ikvmPropertiesContext && !string.IsNullOrWhiteSpace(ikvmPropertiesContext))
302 {
303 foreach (var ikvmSystemProperty in ikvmPropertiesContext.Split(';', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries))
304 {
305 if (AppContext.GetData(ikvmSystemProperty) is string ikvmPropertyValue)
306 {
307 p[ikvmSystemProperty] = ikvmPropertyValue;
308 }
309 }
310 }
311#endif
312
313 // set the properties that were specfied
314 if (user != null)
315 foreach (var kvp in user)
316 p[kvp.Key] = kvp.Value;
317#endif
318 }
319
324 static string GetLibraryPath()
325 {
326#if FIRST_PASS || IMPORTER || EXPORTER
327 throw new NotImplementedException();
328#else
329 var libraryPath = new List<string>();
330
332 {
333 // see /hotspot/src/os/windows/vm/os_windows.cpp for the comment that describes how we build the path
334 var windir = SafeGetEnvironmentVariable("SystemRoot");
335 if (windir != null)
336 libraryPath.Add(Path.Combine(windir, "Sun", "Java", "bin"));
337
338 try
339 {
340 libraryPath.Add(Environment.SystemDirectory);
341 }
342 catch (SecurityException)
343 {
344
345 }
346
347 if (windir != null)
348 libraryPath.Add(windir);
349
350 var path = SafeGetEnvironmentVariable("PATH");
351 if (path != null)
352 foreach (var i in path.Split(Path.PathSeparator))
353 libraryPath.Add(i);
354 }
355
357 {
358 // on Linux we have some hardcoded paths (from /hotspot/src/os/linux/vm/os_linux.cpp)
359 // and we can only guess the cpu arch based on bitness (that means only x86 and x64)
360 libraryPath.Add(Path.Combine("/usr/java/packages/lib/", IntPtr.Size == 4 ? "i386" : "amd64"));
361 libraryPath.Add("/lib");
362 libraryPath.Add("/usr/lib");
363
364 // prefix with LD_LIBRARY_PATH
365 var ld_library_path = SafeGetEnvironmentVariable("LD_LIBRARY_PATH");
366 if (ld_library_path != null)
367 foreach (var i in ld_library_path.Split(Path.PathSeparator).Reverse())
368 libraryPath.Insert(0, i);
369 }
370
371 if (RuntimeUtil.IsOSX)
372 {
373 var home = SafeGetEnvironmentVariable("HOME");
374 if (home != null)
375 libraryPath.Add(Path.Combine(home, "Library/Java/Extensions"));
376
377 libraryPath.Add("/Library/Java/Extensions");
378 libraryPath.Add("/Network/Library/Java/Extensions");
379 libraryPath.Add("/System/Library/Java/Extensions");
380 libraryPath.Add("/usr/lib/java");
381
382 // prefix with JAVA_LIBRARY_PATH
383 var javaLibraryPath = SafeGetEnvironmentVariable("JAVA_LIBRARY_PATH");
384 if (javaLibraryPath != null)
385 foreach (var i in javaLibraryPath.Split(Path.PathSeparator))
386 libraryPath.Add(i);
387
388 // prefix with DYLD_LIBRARY_PATH
389 var dyldLibraryPath = SafeGetEnvironmentVariable("DYLD_LIBRARY_PATH");
390 if (dyldLibraryPath != null)
391 foreach (var i in dyldLibraryPath.Split(Path.PathSeparator))
392 libraryPath.Add(i);
393
394 if (home != null)
395 libraryPath.Add(home);
396
397 libraryPath.Add(".");
398 }
399
400 try
401 {
402 var l = new List<string>();
403
404 foreach (var d in GetIkvmPropertiesSearchPaths())
405 {
406 l.Add(d);
407 foreach (var rid in RuntimeUtil.SupportedRuntimeIdentifiers)
408 l.Add(Path.Combine(d, "runtimes", rid, "native"));
409 }
410
411 libraryPath.InsertRange(0, l);
412 }
413 catch (Exception)
414 {
415 // ignore
416 }
417
419 libraryPath.Add(".");
420
421 return string.Join(Path.PathSeparator.ToString(), libraryPath.Distinct());
422#endif
423 }
424
429 static IEnumerable<string> GetBootLibraryPathsIter()
430 {
431 yield return Path.Combine(HomePath, "bin");
432 }
433
438 static string GetBootLibraryPath()
439 {
440 return string.Join(Path.PathSeparator.ToString(), GetBootLibraryPathsIter());
441 }
442
443 }
444
445 }
446
447}
IKVM.Reflection.Assembly Assembly
Represents an internal error that occurred within IKVM.
Property values loaded into the JVM from various sources.
static IDictionary< string, string > User
Gets the set of properties that are set by the user before initialization. Modification of values in ...
Main state of the running JVM.
Maintains various information about the current runtime environment.
static IEnumerable< string > SupportedRuntimeIdentifiers
Gets the supported RIDs, returned in most specific order.
static bool IsOSX
Returns true if the current platform is Mac OS X.
static bool IsWindows
Returns true if the current platform is Windows.
static bool IsLinux
Returns true if the current platform is Linux.