static int Main(string[] args)
{
Tracer.EnableTraceConsoleListener();
Tracer.EnableTraceForDebug();
System.Collections.Hashtable props = new System.Collections.Hashtable();
string classpath = Environment.GetEnvironmentVariable("CLASSPATH");
if(classpath == null || classpath == "")
{
classpath = ".";
}
props["java.class.path"] = classpath;
bool jar = false;
bool saveAssembly = false;
bool saveAssemblyX = false;
bool waitOnExit = false;
bool showVersion = false;
string mainClass = null;
int vmargsIndex = -1;
bool debug = false;
String debugArg = null;
for(int i = 0; i < args.Length; i++)
{
String arg = args[i];
if(arg[0] == '-')
{
if(arg == "-help" || arg == "-?")
{
break;
}
else if(arg == "-Xsave")
{
saveAssembly = true;
IKVM.Internal.Starter.PrepareForSaveDebugImage();
}
else if(arg == "-XXsave")
{
saveAssemblyX = true;
IKVM.Internal.Starter.PrepareForSaveDebugImage();
}
else if(arg == "-Xtime")
{
new Timer();
}
else if(arg == "-Xwait")
{
waitOnExit = true;
}
else if(arg == "-Xbreak")
{
System.Diagnostics.Debugger.Break();
}
else if(arg == "-Xnoclassgc")
{
IKVM.Internal.Starter.ClassUnloading = false;
}
else if(arg == "-jar")
{
jar = true;
}
else if(arg == "-version")
{
Console.WriteLine(Startup.getVersionAndCopyrightInfo());
Console.WriteLine();
Console.WriteLine("CLR version: {0} ({1} bit)", Environment.Version, IntPtr.Size * 8);
System.Type type = System.Type.GetType("Mono.Runtime");
if(type != null)
{
Console.WriteLine("Mono version: {0}", type.InvokeMember("GetDisplayName", BindingFlags.InvokeMethod | BindingFlags.Static | BindingFlags.NonPublic, null, null, new object[0]));
}
foreach(Assembly asm in AppDomain.CurrentDomain.GetAssemblies())
{
Console.WriteLine("{0}: {1}", asm.GetName().Name, asm.GetName().Version);
}
string ver = java.lang.System.getProperty("openjdk.version");
if(ver != null)
{
Console.WriteLine("OpenJDK version: {0}", ver);
}
return 0;
}
else if(arg == "-showversion")
{
showVersion = true;
}
else if(arg.StartsWith("-D"))
{
arg = arg.Substring(2);
string[] keyvalue = arg.Split('=');
string value;
if(keyvalue.Length == 2) // -Dabc=x
{
value = keyvalue[1];
}
else if (keyvalue.Length == 1) // -Dabc
{
value = "";
}
else // -Dabc=x=y
{
value = arg.Substring(keyvalue[0].Length + 1);
}
props[keyvalue[0]] = value;
}
else if(arg == "-ea" || arg == "-enableassertions")
{
IKVM.Runtime.Assertions.EnableAssertions();
}
else if(arg == "-da" || arg == "-disableassertions")
{
IKVM.Runtime.Assertions.DisableAssertions();
}
else if(arg == "-esa" || arg == "-enablesystemassertions")
{
IKVM.Runtime.Assertions.EnableSystemAssertions();
}
else if(arg == "-dsa" || arg == "-disablesystemassertions")
{
IKVM.Runtime.Assertions.DisableSystemAssertions();
}
else if(arg.StartsWith("-ea:") || arg.StartsWith("-enableassertions:"))
{
IKVM.Runtime.Assertions.EnableAssertions(arg.Substring(arg.IndexOf(':') + 1));
}
else if(arg.StartsWith("-da:") || arg.StartsWith("-disableassertions:"))
{
IKVM.Runtime.Assertions.DisableAssertions(arg.Substring(arg.IndexOf(':') + 1));
}
else if(arg == "-cp" || arg == "-classpath")
{
props["java.class.path"] = args[++i];
}
else if(arg.StartsWith("-Xtrace:"))
{
Tracer.SetTraceLevel(arg.Substring(8));
}
else if(arg.StartsWith("-Xmethodtrace:"))
{
Tracer.HandleMethodTrace(arg.Substring(14));
}
else if(arg == "-Xdebug")
{
debug = true;
}
else if (arg == "-Xnoagent")
{
//ignore it, disable support for oldjdb
}
else if (arg.StartsWith("-Xrunjdwp") || arg.StartsWith("-agentlib:jdwp"))
{
debugArg = arg;
debug = true;
}
else if (arg.StartsWith("-Xreference:"))
{
Startup.addBootClassPathAssemby(Assembly.LoadFrom(arg.Substring(12)));
}
else if (arg.StartsWith("-Xms")
|| arg.StartsWith("-Xmx")
|| arg.StartsWith("-Xss")
|| arg == "-Xmixed"
|| arg == "-Xint"
|| arg == "-Xnoclassgc"
|| arg == "-Xincgc"
|| arg == "-Xbatch"
|| arg == "-Xfuture"
|| arg == "-Xrs"
|| arg == "-Xcheck:jni"
|| arg == "-Xshare:off"
|| arg == "-Xshare:auto"
|| arg == "-Xshare:on"
)
{
Console.Error.WriteLine("Unsupported option ignored: {0}", arg);
}
else
{
Console.Error.WriteLine("{0}: illegal argument", arg);
break;
}
}
else
{
mainClass = arg;
vmargsIndex = i + 2;
break;
}
}
if(mainClass == null || showVersion)
{
Console.Error.WriteLine(Startup.getVersionAndCopyrightInfo());
Console.Error.WriteLine();
}
if(mainClass == null)
{
Console.Error.WriteLine("usage: ikvm [-options] <class> [args...]");
Console.Error.WriteLine(" (to execute a class)");
Console.Error.WriteLine(" or ikvm -jar [-options] <jarfile> [args...]");
Console.Error.WriteLine(" (to execute a jar file)");
Console.Error.WriteLine();
Console.Error.WriteLine("where options include:");
Console.Error.WriteLine(" -? -help Display this message");
Console.Error.WriteLine(" -version Display IKVM and runtime version");
Console.Error.WriteLine(" -showversion Display version and continue running");
Console.Error.WriteLine(" -cp -classpath <directories and zip/jar files separated by {0}>", Path.PathSeparator);
Console.Error.WriteLine(" Set search path for application classes and resources");
Console.Error.WriteLine(" -D<name>=<value> Set a system property");
Console.Error.WriteLine(" -ea[:<packagename>...|:<classname>]");
Console.Error.WriteLine(" -enableassertions[:<packagename>...|:<classname>]");
Console.Error.WriteLine(" Enable assertions.");
Console.Error.WriteLine(" -da[:<packagename>...|:<classname>]");
Console.Error.WriteLine(" -disableassertions[:<packagename>...|:<classname>]");
Console.Error.WriteLine(" Disable assertions");
Console.Error.WriteLine(" -Xsave Save the generated assembly (for debugging)");
Console.Error.WriteLine(" -Xtime Time the execution");
Console.Error.WriteLine(" -Xtrace:<string> Displays all tracepoints with the given name");
Console.Error.WriteLine(" -Xmethodtrace:<string>");
Console.Error.WriteLine(" Builds method trace into the specified output methods");
Console.Error.WriteLine(" -Xwait Keep process hanging around after exit");
Console.Error.WriteLine(" -Xbreak Trigger a user defined breakpoint at startup");
Console.Error.WriteLine(" -Xnoclassgc Disable class garbage collection");
return 1;
}
try
{
if (debug)
{
// Starting the debugger
Assembly asm = Assembly.GetExecutingAssembly();
String arguments = debugArg + " -pid:" + System.Diagnostics.Process.GetCurrentProcess().Id;
String program = new FileInfo(asm.Location).DirectoryName + "\\debugger.exe";
try
{
ProcessStartInfo info = new ProcessStartInfo(program, arguments);
info.UseShellExecute = false;
Process debugger = new Process();
debugger.StartInfo = info;
debugger.Start();
}
catch (Exception ex)
{
Console.Error.WriteLine(program + " " + arguments);
throw ex;
}
}
if(jar)
{
props["java.class.path"] = mainClass;
}
Startup.setProperties(props);
Startup.enterMainThread();
// HACK Starup.glob() uses Java code, so we need to do this after we've initialized
string[] vmargs = Startup.glob(vmargsIndex);
if (jar)
{
mainClass = GetMainClassFromJarManifest(mainClass);
if (mainClass == null)
{
return 1;
}
}
java.lang.Class clazz = java.lang.Class.forName(mainClass, true, java.lang.ClassLoader.getSystemClassLoader());
try
{
Method method = IKVM.Internal.Starter.FindMainMethod(clazz);
if(method == null)
{
throw new java.lang.NoSuchMethodError("main");
}
else if(!Modifier.isPublic(method.getModifiers()))
{
Console.Error.WriteLine("Main method not public.");
}
else
{
// if clazz isn't public, we can still call main
method.setAccessible(true);
if(saveAssembly)
{
java.lang.Runtime.getRuntime().addShutdownHook(new SaveAssemblyShutdownHook(clazz));
}
if(waitOnExit)
{
java.lang.Runtime.getRuntime().addShutdownHook(new WaitShutdownHook());
}
try
{
method.invoke(null, new object[] { vmargs });
return 0;
}
catch(InvocationTargetException x)
{
throw x.getCause();
}
}
}
finally
{
if(saveAssemblyX)
{
IKVM.Internal.Starter.SaveDebugImage();
}
}
}
catch(System.Exception x)
{
java.lang.Thread thread = java.lang.Thread.currentThread();
thread.getThreadGroup().uncaughtException(thread, ikvm.runtime.Util.mapException(x));
}
finally
{
Startup.exitMainThread();
}
return 1;
}