PojavLauncherTeam / PojavLauncher

A Minecraft: Java Edition Launcher for Android and iOS based on Boardwalk. This repository contains source code for Android platform.
GNU Lesser General Public License v3.0
6.82k stars 1.28k forks source link

Way to run versions higher than 1.8 on Android 9 #1

Closed artdeell closed 4 years ago

artdeell commented 4 years ago

When i started investigating this problem, i found something interesting when started multidoj outside of an application. It was utputting something about wrong class file versions. I browsed Google, and figured out: to convert code, compiled for Javas newer than Java 6, Multidoj is a rewrite for dx ver. 1.7, and this DX version refuses to convert Java 8 classes. So, I found DX version 1.16, and tried to convert with it. 1.16 converted all files successfuly.

So, you need to rewrite dx 1.16 instead of dx 1.7. 1.16 dx is attached to this issue. dx.zip

artdeell commented 4 years ago

UPD: For proper converting on Android, DX binary requires passing two arguments: --no-optimize and --min-sdk-version=26(because of invokedynamics in 1.12.2)

artdeell commented 4 years ago

UPD 2: Got 1.9 running with playable FPS (preconverted binaries) Still can't get 1.12.2 working? because of come javax.script - related classes are missing

artdeell commented 4 years ago

UPD 3: Got 1.11 running in PojavLauncher on Android 9 Screenshot_20200318-192739_PojavLauncher_(Java_Edition) Screenshot_20200318-192759_PojavLauncher_(Java_Edition)

khanhduytran0 commented 4 years ago

Multidoj is a custom dx version that I modify to enable multidex and in-app verbose. To convert Java8, D8 is used instead of DX, it directly desugar Java8 classes then convert to dex, but it can only be run in Java 8. Previous I tried using APKTool's OpenJDK8 to run, it success for my device but error for modern devices. For now, that version was lost.

khanhduytran0 commented 4 years ago

Thank you for sharing dx1.16. I will take a look at it.

artdeell commented 4 years ago

UPD 2: Got 1.9 running with playable FPS (preconverted binaries) Still can't get 1.12.2 working? because of come javax.script - related classes are missing

This is on Android 9, too.

khanhduytran0 commented 4 years ago

Yes i know. But to make a custom version dx I can choose source code instead of compiled.

artdeell commented 4 years ago

The main problem is: Fernflower can't decompile com.android.dx.Dex class and some comparators.

artdeell commented 4 years ago

I'll try to decompile and fix it.

khanhduytran0 commented 4 years ago

You don't need decompile it. DX already open source, just google and you will get.

khanhduytran0 commented 4 years ago

https://github.com/rover12421/AndroidDx/blob/master/src/main/java/com/android/dx/Version.java (yes 1.16, multidex supported)

https://github.com/rover12421/AndroidDx

artdeell commented 4 years ago

So now launcher community just need to wait... for new release...

khanhduytran0 commented 4 years ago

Maybe select DX version if error? I found an official open source latest version from Google https://android.googlesource.com/platform/dalvik/+/refs/heads/master/dx/

artdeell commented 4 years ago

Better way is to add a switch in settings: use Multidoj(android <=6) or DX 1.16 with observer(android >6).

khanhduytran0 commented 4 years ago

Multidoj based from DX, may I make a multidoj for 1.16, need verbose and progress, the Multidoj7 (dx1.7) still works for some version so my idea: if convert with Multidoj7 fails then switch to Multidoj16 (dx1.16) and might be other versions.

artdeell commented 4 years ago

What and where did you added to observe DX operations?

khanhduytran0 commented 4 years ago

com.android.dx.cf.direct.ClassPathOpener.processArchive(ClassPathOpener:~236) for setting max progress. com.android.dx.command.dexer.Main.processFileBytes(Main:???) for update progress. Also added some custom classes to dx. Just dex2jar it to see what is inside.

artdeell commented 4 years ago

Thanks. I'll try to integrate progerss in dx 1.16

artdeell commented 4 years ago

This thingy eats frikin' 2 GIGS OF RAM when converting it.unimi.dsi.fastutil This is the reason why original Boardwalw can't launch 1.8+ versions

khanhduytran0 commented 4 years ago

So dex split is a solution, original DX: converted dex keep in the memory, until convert done it write to a dex/jar file and finally release memory.

khanhduytran0 commented 4 years ago

If I set --min-sdk-version=26 then Android from 7.1 or below might get backwards compatible break. Better use "--min-sdk-version=" + android.os.Build.VERSION.SDK_INT but will break compatible with some Minecraft version if in Android below 8.0

khanhduytran0 commented 4 years ago

The original one give me OutOfMemoryError

Screenshot_2020-03-20-07-18-10

artdeell commented 4 years ago

This is the main reason why ANYONE shouldn't use original DX for REALLY big libraries. This is the main reason WHY boardwalk was unable to run 1.9 and newer.

artdeell commented 4 years ago

The original one give me OutOfMemoryError

Screenshot_2020-03-20-07-18-10

Did you use --no-optimize?

khanhduytran0 commented 4 years ago

Yes, I did. The jar file I attempt to convert with size ~14MB. So I created a custom dx 1.16. Now if add a file to the list, dx will write data to the storage instead of memory. Check at https://github.com/khanhduytran0/PojavDX

khanhduytran0 commented 4 years ago

I modified some codes to make dx create multiple dex files if methods out of 0xFFF (4095). My result (with --multi-dex): Screenshot_2020-03-20-17-51-40

artdeell commented 4 years ago

Ok. I'll try it on my device.

artdeell commented 4 years ago

It can't convert fastutil(11mb) on 256mb heap. (this is the most common value on Android) iss It eats more than 2 gigs of RAM, still. iss2

artdeell commented 4 years ago

oh now i figured out: to decrease ram usage, i should use --multi-dex, right? Now it can process 17 megabytes of Java code leaving more than 40 dex files.

artdeell commented 4 years ago

@khanhduytran0 i can't test it out with observer in real launcher because of too much references in single dex. So, there's no way to test it myself. I'll create the pull request with oserver for PojavDX, and wait for the new release.

khanhduytran0 commented 4 years ago

Running Minecraft 1.12 and later requires Java 8 which supported in Android 8.0 (?). If the launcher compile without adding:

compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
}

This is added a library backport javax.script package. Then ReactNative bootstrap will error:

java.lang.reflect.InvocationTargetException
    at java.lang.reflect.Method.invoke(Native Method)
    at net.kdt.pojavlaunch.MainActivity.runCraft(MainActivity.java:722)
    at net.kdt.pojavlaunch.MainActivity.access$1000070(Unknown Source:0)
    at net.kdt.pojavlaunch.MainActivity$100000012$100000011.run(MainActivity.java:495)
    at java.lang.Thread.run(Thread.java:764)
Caused by: java.lang.BootstrapMethodError: Exception from call site #0 bootstrap method
    at bhz.<init>(SourceFile:395)
    at net.minecraft.client.main.Main.main(SourceFile:123)
    ... 5 more
Caused by: java.lang.ClassCastException: Bootstrap method returned null
    ... 7 more

But if add, will break compatibility for Android 7.1 and below.

artdeell commented 4 years ago

oh now i figured out: to decrease ram usage, i should use --multi-dex, right? Now it can process 17 megabytes of Java code leaving more than 40 dex files.

I tested that on 300mb heap.

artdeell commented 4 years ago

So, be sute this is the problem of the phone.

artdeell commented 4 years ago

Can you give me new binary for testing? I'll check it out on Android 9

khanhduytran0 commented 4 years ago

I will give you the current development 2.4.2. It had dx 1.16. Do not leak! Request once with Google drive. EDIT: I tested it convert fastutil lib with 512MB max heap (any morden devices will have) in Android-x86.

khanhduytran0 commented 4 years ago

Here https://drive.google.com/file/d/1nlvOYOBaI1VdH29cHujJmcFJyv-hYXBj/view?usp=drivesdk EDIT: ??? QLauncher, the modified of original one.

khanhduytran0 commented 4 years ago

Did you ultramaksim? Please confirm it's yours.

artdeell commented 4 years ago

Yeah, it's me.

artdeell commented 4 years ago

It's a bad idea to use reflections. Screenshot_20200321-161138_PojavLauncher_(Minecraft_Java_Edition_for_Android)

khanhduytran0 commented 4 years ago

I Invoked it directly instead of reflection. Use some part of observer to dump error message if dx failed. It's a part of 2.4.2. Can you try 1.11?

artdeell commented 4 years ago

It crashes on the same library with same problem.

Unable to convert library %s processing archive /data/data/net.kdt.pojavlaunch/app_working_dir/libraries/com/mojang/netty/1.6/netty-1.6_orig.jar... processing META-INF/... writing META-INF/; size 0... processing META-INF/MANIFEST.MF... processing io/... writing io/; size 0... processing io/netty/... writing io/netty/; size 0... processing io/netty/bootstrap/... writing io/netty/bootstrap/; size 0... processing io/netty/bootstrap/Bootstrap.class... processing io/netty/bootstrap/Bootstrap$1.class... processing io/netty/bootstrap/Bootstrap$2.class... Uncaught translation error: java.util.concurrent.ExecutionException: java.lang.IllegalAccessError: Method 'void java.lang.System.arraycopy(int[], int, int[], int, int)' is inaccessible to class 'com.android.dx.util.IntList' (declaration of 'com.android.dx.util.IntList' appears in base.apk) Uncaught translation error: java.util.concurrent.ExecutionException: java.lang.IllegalAccessError: Method 'void java.lang.System.arraycopy(int[], int, int[], int, int)' is inaccessible to class 'com.android.dx.util.IntList' (declaration of 'com.android.dx.util.IntList' appears in base.apk) Uncaught translation error: java.util.concurrent.ExecutionException: java.lang.IllegalAccessError: Method 'void java.lang.System.arraycopy(int[], int, int[], int, int)' is inaccessible to class 'com.android.dx.util.IntList' (declaration of 'com.android.dx.util.IntList' appears in base.apk) 3 errors; aborting Exiting with code 1

khanhduytran0 commented 4 years ago

The problem is at java.lang.System.arraycopy() caused error inaccessible (I can fix using reflection) method.setAccessible(true);

artdeell commented 4 years ago

Waiting for fix. Also, the UI looked a bit better in 2.4.

khanhduytran0 commented 4 years ago

Yes, UI has been auto scaled but some big devices still not yet fit.

artdeell commented 4 years ago

@khanhduytran0 you fixed it?

khanhduytran0 commented 4 years ago

https://drive.google.com/file/d/1oAN9ZW9kiiseZQKXP4RjMHd6vV2bnsi9/view?usp=drivesdk here, check if it is preview3 or not.

artdeell commented 4 years ago

On Android 10 it's not working (i recently updated my firmware to LineageOS 17.1) Screenshot_20200322-091313_PojavLauncher_(Minecraft_Java_Edition_for_Android)

khanhduytran0 commented 4 years ago

Still need take a fix at System.arraycopy()

artdeell commented 4 years ago

It's because Android's arraycopy uses Objects instead of arrays. Screenshot_20200322-091713_Firefox

artdeell commented 4 years ago

So to fix that, you need to cast your arrays to Objects.