diff --git a/Launcher.pro b/Launcher.pro index 688a459..2b71aa6 100644 --- a/Launcher.pro +++ b/Launcher.pro @@ -16,8 +16,10 @@ -renamesourcefileattribute Source -dontnote +-dontwarn -dontshrink -dontoptimize +-ignorewarnings -target 8 -forceprocessing diff --git a/Launcher/runtime/dialog/overlay/update/update.js b/Launcher/runtime/dialog/overlay/update/update.js index 5c9a27e..d4e366c 100644 --- a/Launcher/runtime/dialog/overlay/update/update.js +++ b/Launcher/runtime/dialog/overlay/update/update.js @@ -43,8 +43,8 @@ // Formatting state.filePath, // File path - state.getFileDownloadedMiB(), state.getFileSizeMiB(), // File downloaded - state.getTotalDownloadedMiB(), state.getTotalSizeMiB(), // Total downloaded + state.getFileDownloadedMiB() + /* Fuck nashorn */ 0.0, state.getFileSizeMiB() + 0.0, // File downloaded + state.getTotalDownloadedMiB() + /* Fuck nashorn */ 0.0, state.getTotalSizeMiB() + 0.0, // Total downloaded bps <= 0.0 ? 0.0 : bps / 1024.0, // Speed estimatedHH, estimatedMM, estimatedSS // Estimated (hh:mm:ss) )); diff --git a/Launcher/source/client/ClientLauncher.java b/Launcher/source/client/ClientLauncher.java index a1cd310..79f289e 100644 --- a/Launcher/source/client/ClientLauncher.java +++ b/Launcher/source/client/ClientLauncher.java @@ -2,8 +2,8 @@ import java.io.IOException; import java.lang.ProcessBuilder.Redirect; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodType; import java.net.URL; import java.nio.file.FileVisitResult; import java.nio.file.Files; @@ -47,6 +47,7 @@ import launcher.serialize.stream.StreamObject; public final class ClientLauncher { + private static final String[] EMPTY_ARRAY = new String[0]; private static final String MAGICAL_INTEL_OPTION = "-XX:HeapDumpPath=ThisTricksIntelDriversForPerformance_javaw.exe_minecraft.exe.heapdump"; private static final Set BIN_POSIX_PERMISSIONS = Collections.unmodifiableSet(EnumSet.of( PosixFilePermission.OWNER_READ, PosixFilePermission.OWNER_WRITE, PosixFilePermission.OWNER_EXECUTE, // Owner @@ -311,18 +312,13 @@ // Resolve main class and method Class mainClass = Class.forName(profile.getMainClass()); - Method mainMethod = mainClass.getDeclaredMethod("main", String[].class); - mainMethod.setAccessible(true); + MethodHandle mainMethod = JVMHelper.LOOKUP.findStatic(mainClass, "main", MethodType.methodType(void.class, String[].class)); // Invoke main method with exception wrapping LAUNCHED.set(true); JVMHelper.fullGC(); - try { - System.setProperty("minecraft.applet.TargetDirectory", params.clientDir.toString()); // For 1.5.2 - mainMethod.invoke(null, (Object) args.toArray(new String[args.size()])); - } catch (InvocationTargetException e) { - throw e.getTargetException(); - } + System.setProperty("minecraft.applet.TargetDirectory", params.clientDir.toString()); // For 1.5.2 + mainMethod.invoke((Object) args.toArray(EMPTY_ARRAY)); } private static URL[] resolveClassPath(Path clientDir, String... classPath) throws IOException { diff --git a/Launcher/source/helper/JVMHelper.java b/Launcher/source/helper/JVMHelper.java index 8996b5b..0e014d8 100644 --- a/Launcher/source/helper/JVMHelper.java +++ b/Launcher/source/helper/JVMHelper.java @@ -1,18 +1,22 @@ package launcher.helper; import java.io.File; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodHandles.Lookup; +import java.lang.invoke.MethodType; import java.lang.management.ManagementFactory; import java.lang.management.RuntimeMXBean; import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; import java.net.URL; import java.nio.file.Path; import java.security.cert.Certificate; +import java.util.Arrays; import java.util.Locale; import com.sun.management.OperatingSystemMXBean; import launcher.LauncherAPI; +import sun.misc.Unsafe; public final class JVMHelper { // MXBeans exports @@ -28,18 +32,20 @@ @LauncherAPI public static final int RAM = getRAMAmount(); // Public static fields + @LauncherAPI public static final Unsafe UNSAFE; + @LauncherAPI public static final Lookup LOOKUP; @LauncherAPI public static final Runtime RUNTIME = Runtime.getRuntime(); @LauncherAPI public static final ClassLoader LOADER = ClassLoader.getSystemClassLoader(); // Useful internal fields and constants private static final String JAVA_LIBRARY_PATH = "java.library.path"; - private static final Field USR_PATHS_FIELD; - private static final Field SYS_PATHS_FIELD; + private static final MethodHandle MH_SET_USR_PATHS; + private static final MethodHandle MH_SET_SYS_PATHS; private static final Object UCP; - private static final Method UCP_ADDURL_METHOD; - private static final Method UCP_GETURLS_METHOD; - private static final Method UCP_GETRESOURCE_METHOD; - private static final Method RESOURCE_GETCERTS_METHOD; + private static final MethodHandle MH_UCP_ADDURL_METHOD; + private static final MethodHandle MH_UCP_GETURLS_METHOD; + private static final MethodHandle MH_UCP_GETRESOURCE_METHOD; + private static final MethodHandle MH_RESOURCE_GETCERTS_METHOD; private JVMHelper() { } @@ -47,9 +53,9 @@ @LauncherAPI public static void addClassPath(URL url) { try { - UCP_ADDURL_METHOD.invoke(UCP, url); - } catch (IllegalAccessException | InvocationTargetException e) { - throw new InternalError(e); + MH_UCP_ADDURL_METHOD.invoke(UCP, url); + } catch (Throwable exc) { + throw new InternalError(exc); } } @@ -68,10 +74,10 @@ // Reset usrPaths and sysPaths cache try { - USR_PATHS_FIELD.set(null, null); - SYS_PATHS_FIELD.set(null, null); - } catch (IllegalAccessException e) { - throw new InternalError(e); + MH_SET_USR_PATHS.invoke((Object) null); + MH_SET_SYS_PATHS.invoke((Object) null); + } catch (Throwable exc) { + throw new InternalError(exc); } } @@ -86,19 +92,19 @@ @LauncherAPI public static Certificate[] getCertificates(String resource) { try { - Object resource0 = UCP_GETRESOURCE_METHOD.invoke(UCP, resource); - return resource0 == null ? null : (Certificate[]) RESOURCE_GETCERTS_METHOD.invoke(resource0); - } catch (IllegalAccessException | InvocationTargetException e) { - throw new InternalError(e); + Object resource0 = MH_UCP_GETRESOURCE_METHOD.invoke(UCP, resource); + return resource0 == null ? null : (Certificate[]) MH_RESOURCE_GETCERTS_METHOD.invoke(resource0); + } catch (Throwable exc) { + throw new InternalError(exc); } } @LauncherAPI public static URL[] getClassPath() { try { - return (URL[]) UCP_GETURLS_METHOD.invoke(UCP); - } catch (IllegalAccessException | InvocationTargetException e) { - throw new InternalError(e); + return (URL[]) MH_UCP_GETURLS_METHOD.invoke(UCP); + } catch (Throwable exc) { + throw new InternalError(exc); } } @@ -106,9 +112,9 @@ public static void halt0(int status) { LogHelper.debug("Trying to halt JVM"); try { - getMethod(Class.forName("java.lang.Shutdown"), "halt0", int.class).invoke(null, status); - } catch (ClassNotFoundException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { - throw new InternalError(e); + LOOKUP.findStatic(Class.forName("java.lang.Shutdown"), "halt0", MethodType.methodType(void.class, int.class)).invokeExact(status); + } catch (Throwable exc) { + throw new InternalError(exc); } } @@ -146,34 +152,48 @@ return System.getProperty("os.arch").contains("64") ? 64 : 32; } - private static Field getField(Class clazz, String name) throws NoSuchFieldException { - Field field = clazz.getDeclaredField(name); - field.setAccessible(true); - return field; - } - - private static Method getMethod(Class clazz, String name, Class... params) throws NoSuchMethodException { - Method method = clazz.getDeclaredMethod(name, params); - method.setAccessible(true); - return method; - } - private static int getRAMAmount() { int physicalRam = (int) (OPERATING_SYSTEM_MXBEAN.getTotalPhysicalMemorySize() >> 20); return Math.min(physicalRam, OS_BITS == 32 ? 1536 : 4096); // Limit 32-bit OS to 1536 MiB, and 64-bit OS to 4096 MiB (because it's enough) } + public static Class firstClass(String... names) throws ClassNotFoundException { + for (String name : names) { + try { + return Class.forName(name, false, LOADER); + } catch (ClassNotFoundException ignored) { + // Expected + } + } + throw new ClassNotFoundException(Arrays.toString(names)); + } + static { try { - USR_PATHS_FIELD = getField(ClassLoader.class, "usr_paths"); - SYS_PATHS_FIELD = getField(ClassLoader.class, "sys_paths"); - UCP = getField(LOADER.getClass(), "ucp").get(LOADER); - UCP_ADDURL_METHOD = getMethod(UCP.getClass(), "addURL", URL.class); - UCP_GETURLS_METHOD = getMethod(UCP.getClass(), "getURLs"); - UCP_GETRESOURCE_METHOD = getMethod(UCP.getClass(), "getResource", String.class); - RESOURCE_GETCERTS_METHOD = getMethod(UCP_GETRESOURCE_METHOD.getReturnType(), "getCertificates"); - } catch (NoSuchFieldException | NoSuchMethodException | IllegalAccessException e) { - throw new InternalError(e); + MethodHandles.publicLookup(); // Just to initialize class + + // Get unsafe to get trusted lookup + Field theUnsafeField = Unsafe.class.getDeclaredField("theUnsafe"); + theUnsafeField.setAccessible(true); + UNSAFE = (Unsafe) theUnsafeField.get(null); + + // Get trusted lookup and other stuff + Field implLookupField = Lookup.class.getDeclaredField("IMPL_LOOKUP"); + LOOKUP = (Lookup) UNSAFE.getObject(UNSAFE.staticFieldBase(implLookupField), UNSAFE.staticFieldOffset(implLookupField)); + MH_SET_USR_PATHS = LOOKUP.findStaticSetter(ClassLoader.class, "usr_paths", String[].class); + MH_SET_SYS_PATHS = LOOKUP.findStaticSetter(ClassLoader.class, "sys_paths", String[].class); + + // Get UCP stuff1 + Class ucpClass = firstClass("jdk.internal.loader.URLClassPath", "sun.misc.URLClassPath"); + Class loaderClass = firstClass("jdk.internal.loader.ClassLoaders$AppClassLoader", "java.net.URLClassLoader"); + Class resourceClass = firstClass("jdk.internal.loader.Resource", "sun.misc.Resource"); + UCP = LOOKUP.findGetter(loaderClass, "ucp", ucpClass).invoke(LOADER); + MH_UCP_ADDURL_METHOD = LOOKUP.findVirtual(ucpClass, "addURL", MethodType.methodType(void.class, URL.class)); + MH_UCP_GETURLS_METHOD = LOOKUP.findVirtual(ucpClass, "getURLs", MethodType.methodType(URL[].class)); + MH_UCP_GETRESOURCE_METHOD = LOOKUP.findVirtual(ucpClass, "getResource", MethodType.methodType(resourceClass, String.class)); + MH_RESOURCE_GETCERTS_METHOD = LOOKUP.findVirtual(resourceClass, "getCertificates", MethodType.methodType(Certificate[].class)); + } catch (Throwable exc) { + throw new InternalError(exc); } } diff --git a/Launcher/source/serialize/stream/EnumSerializer.java b/Launcher/source/serialize/stream/EnumSerializer.java index 8ad71fe..f6b2de2 100644 --- a/Launcher/source/serialize/stream/EnumSerializer.java +++ b/Launcher/source/serialize/stream/EnumSerializer.java @@ -1,7 +1,6 @@ package launcher.serialize.stream; import java.io.IOException; -import java.lang.reflect.Field; import java.util.HashMap; import java.util.Map; @@ -16,20 +15,8 @@ @LauncherAPI public EnumSerializer(Class clazz) { - for (Field field : clazz.getFields()) { - if (!field.isEnumConstant()) { - continue; - } - - // Add to map - Itf itf; - try { - itf = (Itf) field.get(null); - } catch (IllegalAccessException e) { - throw new InternalError(e); - } - VerifyHelper.putIfAbsent(map, itf.getNumber(), clazz.cast(itf), - "Duplicate number for enum constant " + field.getName()); + for (E e : clazz.getEnumConstants()) { + VerifyHelper.putIfAbsent(map, e.getNumber(), e, "Duplicate number for enum constant " + e.name()); } }