IKVM11  11
Java SE 11 Virtual Machine for .NET
Loading...
Searching...
No Matches
IKVM.Runtime.Launcher Class Reference

Utility for launching a Java class from a main entry point. Parses JVM command line options, then passes the remainder through to the underlying Java main method. More...

Static Public Member Functions

static int Run (Assembly assembly, string main, bool jar, string[] args, string rarg, IDictionary< string, string > properties)
 Services as the managed entry point jump for a Java executable.
 

Detailed Description

Utility for launching a Java class from a main entry point. Parses JVM command line options, then passes the remainder through to the underlying Java main method.

Definition at line 28 of file Launcher.cs.

Member Function Documentation

◆ Run()

static int IKVM.Runtime.Launcher.Run ( Assembly assembly,
string main,
bool jar,
string[] args,
string rarg,
IDictionary< string, string > properties )
static

Services as the managed entry point jump for a Java executable.

Parameters
assembly
main
jar
args
rarg
properties
Returns

Definition at line 263 of file Launcher.cs.

264 {
265 if (args is null)
266 throw new ArgumentNullException(nameof(args));
267
268#if FIRST_PASS || IMPORTER
269 throw new NotImplementedException();
270#else
271 HandleDebugTrace();
272
273 // initialize attribute parsing
274 var initialize = properties != null ? new Dictionary<string, string>(properties) : new Dictionary<string, string>();
275 var showversion = false;
276 var exit = false;
277 var hasMainArg = false;
278 var jvmArgs = args.Where(i => rarg != null).Where(i => i.StartsWith(rarg)).Select(i => i.Substring(rarg.Length)).ToList();
279 var appArgs = args.Where(i => rarg == null || i.StartsWith(rarg) == false).ToList();
280 var appArgsReset = false;
281
282 // classpath from environment by default
283 initialize["java.class.path"] = ".";
284 if (Environment.GetEnvironmentVariable("CLASSPATH") is string cp && !string.IsNullOrEmpty(cp))
285 initialize["java.class.path"] = string.Join(Path.PathSeparator.ToString(), Glob(cp.Split(Path.PathSeparator)));
286
287 // ikvm.home.root from environment by default
288 if (Environment.GetEnvironmentVariable("IKVM_HOME_ROOT") is string ihr && !string.IsNullOrEmpty(ihr))
289 initialize["ikvm.home.root"] = ihr;
290
291 // ikvm.home from environment by default
292 if (Environment.GetEnvironmentVariable("IKVM_HOME") is string ih && !string.IsNullOrEmpty(ih))
293 initialize["ikvm.home"] = ih;
294
295 // process through each incoming argument
296 for (var jvmArg = jvmArgs.GetEnumerator(); jvmArg.MoveNext();)
297 {
298 var arg = jvmArg.Current.AsSpan();
299 if (hasMainArg == false && arg.StartsWith("-".AsSpan()))
300 {
301 // define system property
302 if (arg.StartsWith("-D".AsSpan()))
303 {
304 var def = arg.Slice(2);
305 var sep = def.IndexOf('=');
306 var key = sep > -1 ? def.Slice(0, sep) : def;
307 var val = sep > -1 ? def.Slice(sep + 1) : "".AsSpan();
308 initialize[key.ToString()] = val.ToString();
309 continue;
310 }
311
312 if (ArgEquals(arg, "-ea") || ArgEquals(arg, "-enableassertions"))
313 {
314 Assertions.EnableAssertions();
315 continue;
316 }
317
318 if (arg.StartsWith("-ea:".AsSpan()) || arg.StartsWith("-enableassertions:".AsSpan()))
319 {
320 if (arg.IndexOf(':') is int v && v > -1)
321 Assertions.EnableAssertions(arg.Slice(v + 1).ToString());
322 }
323
324 if (ArgEquals(arg, "-da") || ArgEquals(arg, "-disableassertions"))
325 {
326 Assertions.DisableAssertions();
327 continue;
328 }
329
330 if (arg.StartsWith("-da:".AsSpan()) || arg.StartsWith("-disableassertions:".AsSpan()))
331 {
332 if (arg.IndexOf(':') is int v && v > -1)
333 Assertions.DisableAssertions(arg.Slice(v + 1).ToString());
334 }
335
336 if (ArgEquals(arg, "-esa") || ArgEquals(arg, "-enablesystemassertions"))
337 {
338 Assertions.EnableSystemAssertions();
339 continue;
340 }
341
342 if (ArgEquals(arg, "-dsa") || ArgEquals(arg, "-disablesystemassertions"))
343 {
344 Assertions.DisableSystemAssertions();
345 continue;
346 }
347
348 if (ArgEquals(arg, "-cp") || ArgEquals(arg, "-classpath"))
349 {
350 if (jvmArg.MoveNext() == false)
351 {
352 Console.Error.WriteLine("Error: {0} requires class path specification", arg.ToString());
353 PrintHelp();
354 return 1;
355 }
356
357 initialize["java.class.path"] = string.Join(Path.PathSeparator.ToString(), Glob(jvmArg.Current.Split(Path.PathSeparator)));
358 continue;
359 }
360
361 if (ArgEquals(arg, "-version"))
362 {
363 showversion = true;
364 exit = true;
365 continue;
366 }
367
368 if (ArgEquals(arg, "-showversion"))
369 {
370 showversion = true;
371 continue;
372 }
373
374 if (ArgEquals(arg, "-jar"))
375 {
376 jar = true;
377 continue;
378 }
379
380 if (ArgEquals(arg, "-?") || ArgEquals(arg, "-help"))
381 {
382 PrintHelp();
383 return 1;
384 }
385
386 if (ArgEquals(arg, "-X"))
387 {
388 PrintXHelp();
389 return 1;
390 }
391
392 if (ArgEquals(arg, "-Xtime"))
393 {
394 Console.Error.WriteLine("Unrecognized option: {0}", arg.ToString());
395 return 1;
396 }
397
398 if (ArgEquals(arg, "-Xbreak"))
399 {
400 Debugger.Break();
401 continue;
402 }
403
404 if (ArgEquals(arg, "-Xverify"))
405 {
406 JVM.RelaxedVerification = false;
407 continue;
408 }
409
410 if (arg.StartsWith("-Xreference:".AsSpan()))
411 {
412 if (arg.IndexOf(':') is int v && v > -1)
413 AddBootClassPathAssembly(Assembly.LoadFrom(arg.Slice(v + 1).ToString()));
414
415 continue;
416 }
417
418 if (ArgEquals(arg, "-XX:+AllowNonVirtualCalls"))
419 {
420 JVM.AllowNonVirtualCalls = true;
421 continue;
422 }
423
424 if (arg.StartsWith("-Xms".AsSpan()) ||
425 arg.StartsWith("-Xmx".AsSpan()) ||
426 arg.StartsWith("-Xmn".AsSpan()) ||
427 arg.StartsWith("-Xss".AsSpan()) ||
428 arg.StartsWith("-XX:".AsSpan()) ||
429 arg.StartsWith("-mn".AsSpan()) ||
430 arg.StartsWith("-ms".AsSpan()) ||
431 arg.StartsWith("-mx".AsSpan()) ||
432 ArgEquals(arg, "-Xmixed") ||
433 ArgEquals(arg, "-Xint") ||
434 ArgEquals(arg, "-Xincgc") ||
435 ArgEquals(arg, "-Xbatch") ||
436 ArgEquals(arg, "-Xfuture") ||
437 ArgEquals(arg, "-Xrs") ||
438 ArgEquals(arg, "-Xcheck:jni") ||
439 ArgEquals(arg, "-Xshare:off") ||
440 ArgEquals(arg, "-Xshare:auto") ||
441 ArgEquals(arg, "-Xshare:on"))
442 {
443 Console.Error.WriteLine("Ignoring unrecognized option: {0}", arg.ToString());
444 continue;
445 }
446
447 Console.Error.WriteLine("Unrecognized option: {0}", arg.ToString());
448 return 1;
449 }
450 else if (hasMainArg == false)
451 {
452 hasMainArg = true;
453 main = arg.ToString();
454 continue;
455 }
456 else
457 {
458 // indicate we're resetting the application arguments
459 if (appArgsReset == false)
460 {
461 appArgsReset = true;
462 appArgs.Clear();
463 }
464
465 // append new application argument
466 appArgs.Add(arg.ToString());
467 continue;
468 }
469 }
470
471 try
472 {
473 // if a jar file is specified, we're going to set the classpath to the jar itself
474 if (jar)
475 initialize["java.class.path"] = main;
476
477 // like the JDK we don't quote the args (even if they contain spaces)
478 initialize["sun.java.command"] = string.Join(" ", Prepend(appArgs, main));
479 initialize["sun.java.launcher"] = "SUN_STANDARD";
480
481 // apply the loaded VM properties
482 SetUserProperties(initialize);
483
484 // VM initialization, configures system properties, done before any static initializers
485 JVM.Init();
486
487 // ensure the entry assembly is added to the classpath
488 // we do this after Init since it triggers the VFS
489 if (assembly != null)
490 AddBootClassPathAssembly(assembly);
491
492 // first entry into base assembly
493 EnterMainThread();
494
495 // we were instructed to show the version
496 if (showversion)
497 PrintVersion();
498
499 // we were instructed to exit immediately
500 if (exit)
501 return 0;
502
503 // we require a main argument, either a class name or jar file
504 if (main == null)
505 {
506 PrintHelp();
507 return 1;
508 }
509
510 // process the main argument, returning the true value, and resetting the command property to match
511 var clazz = LauncherHelperAccessor.InvokeCheckAndLoadMain(true, jar ? 2 : 1, main);
512 SystemAccessor.InvokeSetProperty("sun.java.command", initialize["sun.java.command"]);
513
514 // find the main method and ensure it is accessible
515 var method = ClassAccessor.InvokeGetMethod(clazz, "main", ClassAccessor.InitArray(JVM.Context.ClassLoaderFactory.GetJavaTypeFromType(typeof(string[])).ClassObject), CallerIDAccessor.InvokeCreate(typeof(Launcher).TypeHandle));
516 MethodAccessor.InvokeSetAccessible(method, true);
517
518 try
519 {
520 // invoke main method, which is responsible for exit
521 MethodAccessor.InvokeInvoke(method, null, new[] { appArgs.ToArray() });
522 return 0;
523 }
524 catch (java.lang.reflect.InvocationTargetException e)
525 {
526 // we want to unwrap the cause to report to the user
527 ExceptionDispatchInfo.Capture(e.getCause()).Throw();
528 throw null;
529 }
530 }
531 catch (Exception e)
532 {
533 var thread = ThreadAccessor.InvokeCurrentThread();
534 ThreadGroupAccessor.InvokeUncaughtException(ThreadAccessor.InvokeGetThreadGroup(thread), thread, ikvm.runtime.Util.mapException(e));
535 }
536 finally
537 {
538 ExitMainThread();
539 }
540
541 return 1;
542#endif
543 }

The documentation for this class was generated from the following file: