Skip to content

Instantly share code, notes, and snippets.

@jessiepathfinder
Created November 10, 2020 07:14
Show Gist options
  • Save jessiepathfinder/2a3596a20921d37ab66733690dd43b79 to your computer and use it in GitHub Desktop.
Save jessiepathfinder/2a3596a20921d37ab66733690dd43b79 to your computer and use it in GitHub Desktop.
IKVM.NET AOT Compiler
using System.Collections;
using System.Reflection;
using System.IO;
using IKVM.Internal;
using java.lang;
using java.util.zip;
using java.io;
using jessielesbian.IKVM;
using Console = System.Console;
using File = java.io.File;
using ikvm.runtime;
namespace ikvmaotc
{
public static class Program
{
static void Main(string[] args)
{
Console.WriteLine("IKVMAOTC v1.0.1: The IKVM.NET Dynamic Optimizing AOT Compiler");
Console.WriteLine("Made by Jessie Lesbian");
Console.WriteLine("Email: [email protected] Reddit: https://www.reddit.com/u/jessielesbian");
Console.WriteLine();
if(args.Length != 3)
{
Console.WriteLine("USAGE: ikvmaotc <input jar> <output assemblies name> <classpath>");
Console.WriteLine("Example: ikvmaotc libminecraft1.11.2-ikvmsafe.jar IKVM.libminecraft.1.11.2 authlib-1.5.24.jar;codecjorbis-20101023.jar;codecwav-20101023.jar;commons-codec-1.9.jar;commons-compress-1.8.1.jar;commons-io-2.4.jar;commons-lang3-3.3.2.jar;commons-logging-1.1.3.jar;fastutil-7.0.12_mojang.jar;gson-2.2.4.jar;guava-17.0.jar;httpclient-4.3.3.jar;httpcore-4.3.2.jar;icu4j-core-mojang-51.2.jar;jinput-2.0.5.jar;jna-3.4.0.jar;jopt-simple-4.6.jar;jutils-1.0.0.jar;libraryjavasound-20101123.jar;librarylwjglopenal-20100824.jar;log4j-api-2.0-beta9.jar;log4j-core-2.0-beta9.jar;lwjgl-2.9.4-nightly-20150209.jar;lwjgl_util-2.9.4-nightly-20150209.jar;netty-1.6.jar;netty-all-4.0.23.Final.jar;oshi-core-1.1.jar;platform-3.4.0.jar;realms-1.10.16.jar;soundsystem-20120107.jar");
Console.WriteLine("NOTE: Assembly names are NOT file names, and don't end with .dll");
return;
}
Console.WriteLine("Initializing...");
string input = args[0];
string output = args[1];
string classpath = input + ";" + args[2];
//The global constant pool is only meant to be used in "truly" dynamic mode. It is there just in case I decide to add a LLVM-based compiler known as IKVMfast or re-implement IKVMCI.
Helper.DisableGlobalConstantPool = true;
Helper.FirstDynamicAssemblyName = output;
Helper.UseSingleDynamicAssembly = true;
Console.WriteLine("Starting suspended JVM...");
Hashtable hashtable = new Hashtable();
hashtable["java.class.path"] = classpath;
hashtable["sun.java.launcher"] = "SUN_STANDARD";
Startup.setProperties(hashtable);
Starter.PrepareForSaveDebugImage();
Startup.enterMainThread();
Console.WriteLine("Getting system class loader...");
ClassLoader classloader = ClassLoader.getSystemClassLoader();
Console.WriteLine("Opening input file...");
ZipInputStream zipInputStream = new ZipInputStream(new FileInputStream(new File(input)));
Console.WriteLine("Creating resources file...");
string tempfile = Path.GetTempFileName();
ZipOutputStream zipOutputStream = new ZipOutputStream(new FileOutputStream(tempfile));
zipOutputStream.setLevel(9);
while(true) {
ZipEntry ze = zipInputStream.getNextEntry();
if(ze == null)
{
break;
}
string filename = ze.name;
if(filename.EndsWith(".class"))
{
string classname = filename.Substring(0, filename.Length - 6).Replace('/', '.');
Console.WriteLine("Compiling class: " + classname + "...");
try
{
classloader.loadClass(classname);
}
catch(System.Exception e)
{
Console.WriteLine("Unable to compile class: " + classname + "!");
Console.WriteLine(e.Message);
}
}
else
{
Console.WriteLine("Adding resource: " + filename + "...");
InputStream IS = classloader.getResourceAsStream(filename);
zipOutputStream.putNextEntry(new ZipEntry(filename));
if(!filename.EndsWith("/"))
{
zipOutputStream.write(ExtractCurrentFile(IS));
IS.close();
}
}
}
Console.WriteLine("Shutting down suspended JVM...");
Startup.exitMainThread();
Console.WriteLine("Closing resources file...");
zipOutputStream.flush();
zipOutputStream.close();
Console.WriteLine("Injecting resources...");
FileStream fileStream = new FileStream(tempfile, FileMode.Open, FileAccess.Read);
Helper.FirstDynamicAssembly.GetDynamicModule(output).DefineManifestResource("resources.jar", fileStream, ResourceAttributes.Public);
Console.WriteLine("Saving assemblies...");
Starter.SaveDebugImage();
Console.WriteLine("Deleting resources file...");
fileStream.Dispose();
System.IO.File.Delete(tempfile);
}
private static byte[] ExtractCurrentFile(InputStream input)
{
MemoryStream memoryStream = new MemoryStream();
memoryStream.Capacity = 65536;
byte[] buffer = new byte[65536];
while(true)
{
int read = input.read(buffer, 0, buffer.Length);
if(read <= 0)
{
byte[] bytes = memoryStream.ToArray();
memoryStream.Dispose();
return bytes;
}
else
{
memoryStream.Capacity += 65536;
}
memoryStream.Write(buffer, 0, read);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment