-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RFC - Smaller bundled JRE #11091
Comments
Sounds good!!! |
I was tending to "not worth the extra hassle". This came from that "can no longer start the gradle 8 builds" issue that doesn't answer our questions, and thus awakened curiosity ("were we not much much leaner not too long ago, in the 10M range???"). What prepares our current jre? Anuken packr? If it has options to control jlink... If not, this would mean one packr run discarding everything packr produces except the exe, then running jlink separately? Also, the module list needs manual maintenance if any major library is added or changed - jdeps autodetection, as shown, fails with a few modules that aren't loaded the normal way. (superficial duckduck skimming suggests the ssl stuff is loaded via reflection) Wait - packr refers to jlink in their readme - will maybe read later. |
No, LibGDX packr run by cli command |
This issue is stale because it has been open 90 days with no activity. Remove stale label or comment or this will be closed in 15 days. |
This issue was closed because it has been stalled for 5 days with no activity. |
Building JREs from JDK on demand? Cool idea. |
I did not even know something like this was even possible.
|
Found related discussions in: packr support seems sus, the docs are discussed here: This looks a little too complex to me, jlink: https://docs.oracle.com/en/java/javase/11/tools/jlink.html |
Anyways, I can try to write actions code for this issue with |
My brain says: Uuuuugghhhh... There's areas where it feels like a Neanderthal seeing the Monolith - so I agree where I understand, and shy away cowardly where learning is required. I fear to get this automated requires a little trial and error, which I didn't want to back then - I know a little more about actions now, such as how you can get the "release patch" uncivbot to run on your own fork - so actual testing before submitting the script to the boss fork is possible... But add some laziness, and I'm happy if someone else does all that. |
ok, I tried the tutorial here: https://adoptium.net/blog/2021/10/jlink-to-produce-own-runtime/ Here is the result: 312M jdk-11.0.23+9 // unpacked official temurin 11 jdk
125M jdk-11.0.23+9-jre // unpacked official temurin 11 jre
187M jdk.tar.gz // official temurin 11 jdk
42M jre.tar.gz // official temurin 11 jre
53M minimized-jre // the minimized jre that i generated
53M Unciv.jar // latest Unciv jar So, 125M to 53M is like ~57.6% save. And yes, I tried running Unciv, it works. |
Ok, there one problem though. Maybe this is not as easy as it looks. I tried running Unciv with ~$ ~/test$ ./minimized-jre/bin/java -jar Unciv.jar
sh: 1: xdg-mime: not found // ignore this, common across all jres
2024-06-15T10:42:25.721715Z [threadpool-daemon-1] [Github] [ERROR] Exception during GitHub download | javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
at java.base/sun.security.ssl.Alert.createSSLException(Unknown Source)
at java.base/sun.security.ssl.Alert.createSSLException(Unknown Source)
at java.base/sun.security.ssl.TransportContext.fatal(Unknown Source)
at java.base/sun.security.ssl.Alert$AlertConsumer.consume(Unknown Source)
at java.base/sun.security.ssl.TransportContext.dispatch(Unknown Source)
at java.base/sun.security.ssl.SSLTransport.decode(Unknown Source)
at java.base/sun.security.ssl.SSLSocketImpl.decode(Unknown Source)
at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(Unknown Source)
at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
at java.base/sun.net.www.protocol.https.HttpsClient.afterConnect(Unknown Source)
at java.base/sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(Unknown Source)
at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream0(Unknown Source)
at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
at java.base/java.net.HttpURLConnection.getResponseCode(Unknown Source)
at java.base/sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(Unknown Source)
at com.unciv.logic.github.Github$tryGetGithubReposWithTopic$inputStream$1.invoke(Github.kt:209)
at com.unciv.logic.github.Github$tryGetGithubReposWithTopic$inputStream$1.invoke(Github.kt:208)
at com.unciv.logic.github.Github.download(Github.kt:52)
at com.unciv.logic.github.Github.tryGetGithubReposWithTopic(Github.kt:208)
at com.unciv.logic.github.Github.tryGetGithubReposWithTopic$default(Github.kt:200)
at com.unciv.ui.screens.modmanager.ModManagementScreen$tryDownloadPage$1.invokeSuspend(ModManagementScreen.kt:288)
at com.unciv.ui.screens.modmanager.ModManagementScreen$tryDownloadPage$1.invoke(ModManagementScreen.kt)
at com.unciv.ui.screens.modmanager.ModManagementScreen$tryDownloadPage$1.invoke(ModManagementScreen.kt)
at com.unciv.utils.ConcurrencyKt$launchCrashHandling$1.invokeSuspend(Concurrency.kt:89)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:108)
at com.unciv.utils.Dispatchers$CrashHandlingDispatcher$dispatch$1.invoke(Concurrency.kt:190)
at com.unciv.utils.Dispatchers$CrashHandlingDispatcher$dispatch$1.invoke(Concurrency.kt:190)
at com.unciv.ui.crashhandling.CrashHandlingExtensionsKt$wrapCrashHandling$1.invoke(CrashHandlingExtensions.kt:17)
at com.unciv.ui.crashhandling.CrashHandlingExtensionsKt$wrapCrashHandlingUnit$1.invoke(CrashHandlingExtensions.kt:33)
at com.unciv.ui.crashhandling.CrashHandlingExtensionsKt$wrapCrashHandlingUnit$1.invoke(CrashHandlingExtensions.kt:33)
at com.unciv.utils.Dispatchers$CrashHandlingDispatcher.dispatch$lambda$0(Concurrency.kt:190)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.base/java.lang.Thread.run(Unknown Source)
2024-06-15T10:42:25.945385Z [threadpool-daemon-1] [Github] [ERROR] Exception during GitHub download | javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
at java.base/sun.security.ssl.Alert.createSSLException(Unknown Source)
at java.base/sun.security.ssl.Alert.createSSLException(Unknown Source)
at java.base/sun.security.ssl.TransportContext.fatal(Unknown Source)
at java.base/sun.security.ssl.Alert$AlertConsumer.consume(Unknown Source)
at java.base/sun.security.ssl.TransportContext.dispatch(Unknown Source)
at java.base/sun.security.ssl.SSLTransport.decode(Unknown Source)
at java.base/sun.security.ssl.SSLSocketImpl.decode(Unknown Source)
at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(Unknown Source)
at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
at java.base/sun.net.www.protocol.https.HttpsClient.afterConnect(Unknown Source)
at java.base/sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(Unknown Source)
at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream0(Unknown Source)
at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
at java.base/java.net.HttpURLConnection.getResponseCode(Unknown Source)
at java.base/sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(Unknown Source)
at com.unciv.logic.github.Github$tryGetGithubReposWithTopic$inputStream$1.invoke(Github.kt:209)
at com.unciv.logic.github.Github$tryGetGithubReposWithTopic$inputStream$1.invoke(Github.kt:208)
at com.unciv.logic.github.Github.download(Github.kt:52)
at com.unciv.logic.github.Github.tryGetGithubReposWithTopic(Github.kt:208)
at com.unciv.logic.github.Github.tryGetGithubReposWithTopic$default(Github.kt:200)
at com.unciv.ui.screens.modmanager.ModManagementScreen$tryDownloadPage$1.invokeSuspend(ModManagementScreen.kt:288)
at com.unciv.ui.screens.modmanager.ModManagementScreen$tryDownloadPage$1.invoke(ModManagementScreen.kt)
at com.unciv.ui.screens.modmanager.ModManagementScreen$tryDownloadPage$1.invoke(ModManagementScreen.kt)
at com.unciv.utils.ConcurrencyKt$launchCrashHandling$1.invokeSuspend(Concurrency.kt:89)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:108)
at com.unciv.utils.Dispatchers$CrashHandlingDispatcher$dispatch$1.invoke(Concurrency.kt:190)
at com.unciv.utils.Dispatchers$CrashHandlingDispatcher$dispatch$1.invoke(Concurrency.kt:190)
at com.unciv.ui.crashhandling.CrashHandlingExtensionsKt$wrapCrashHandling$1.invoke(CrashHandlingExtensions.kt:17)
at com.unciv.ui.crashhandling.CrashHandlingExtensionsKt$wrapCrashHandlingUnit$1.invoke(CrashHandlingExtensions.kt:33)
at com.unciv.ui.crashhandling.CrashHandlingExtensionsKt$wrapCrashHandlingUnit$1.invoke(CrashHandlingExtensions.kt:33)
at com.unciv.utils.Dispatchers$CrashHandlingDispatcher.dispatch$lambda$0(Concurrency.kt:190)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.base/java.lang.Thread.run(Unknown Source)
2024-06-15T10:42:25.946604Z [threadpool-daemon-1] [ModManagementScreen$tryDownloadPage] [ERROR] Could not download mod list | java.lang.NullPointerException
at com.unciv.ui.screens.modmanager.ModManagementScreen$tryDownloadPage$1.invokeSuspend(ModManagementScreen.kt:288)
at com.unciv.ui.screens.modmanager.ModManagementScreen$tryDownloadPage$1.invoke(ModManagementScreen.kt)
at com.unciv.ui.screens.modmanager.ModManagementScreen$tryDownloadPage$1.invoke(ModManagementScreen.kt)
at com.unciv.utils.ConcurrencyKt$launchCrashHandling$1.invokeSuspend(Concurrency.kt:89)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:108)
at com.unciv.utils.Dispatchers$CrashHandlingDispatcher$dispatch$1.invoke(Concurrency.kt:190)
at com.unciv.utils.Dispatchers$CrashHandlingDispatcher$dispatch$1.invoke(Concurrency.kt:190)
at com.unciv.ui.crashhandling.CrashHandlingExtensionsKt$wrapCrashHandling$1.invoke(CrashHandlingExtensions.kt:17)
at com.unciv.ui.crashhandling.CrashHandlingExtensionsKt$wrapCrashHandlingUnit$1.invoke(CrashHandlingExtensions.kt:33)
at com.unciv.ui.crashhandling.CrashHandlingExtensionsKt$wrapCrashHandlingUnit$1.invoke(CrashHandlingExtensions.kt:33)
at com.unciv.utils.Dispatchers$CrashHandlingDispatcher.dispatch$lambda$0(Concurrency.kt:190)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.base/java.lang.Thread.run(Unknown Source) |
Anyways, here are the steps that I used so that you guys can try debugging. wget https://api.adoptium.net/v3/binary/latest/11/ga/linux/x64/jdk/hotspot/normal/eclipse -O jdk.tar.gz
tar -xzvf jdk.tar.gz
rm jdk.tar.gz
mv jdk-11* jdk-11
./jdk-11/bin/jdeps -s Unciv.jar > deps.txt
UNCIV_MODULES=$(cat deps.txt | grep -v 'not found' | cut -d ' ' -f 3 | tr '\n' ',' | sed 's/,$//')
./jdk-11/bin/jlink --add-modules $UNCIV_MODULES --strip-debug --no-man-pages --no-header-files --compress=2 --output minimized-jre
wget https://github.com/yairm210/Unciv/releases/download/4.11.19-patch1/Unciv.jar
./minimized-jre/bin/java -jar Unciv.jar |
I think this will take time to figure out. The best for now maybe just to merge #11751 for now as we try to figure this out. ./jdk-11/bin/jdeps -s Unciv.jar > deps.txt
UNCIV_MODULES=$(cat deps.txt | grep -v 'not found' | cut -d ' ' -f 3 | tr '\n' ',' | sed 's/,$//') |
This one I did cover up there... Look for "(jdk.crypto.ec was missed by jdeps, missing it blocks any https)" in the first post. A search turns up some explanations hinting why, and hinting this is pretty common IIRC. |
So, just adding |
Yes, but 4 eyes see more than 2, so don't buy that bag untested, or don't let me prejudice you on which Unciv features to thoroughly test for missing modules from jlink minification. 'Later, I need to do some RL. |
That is the concern I have also. How to know if the JRE we have shipped will work? We can do trial and error by actually shipping it first then debugging but that would be hilarious (maybe something like putting the cart before the horse also). |
Ok found a solution that looks like it might resolve any such unforseen dependency missing issues. It is here: |
Before creating
Problem Description
Thinking about those 90MB download zip...
Related Issue Links
No response
Desired Solution
I tried, out of a hunch, to ask the jdk to build a jre adapted to Unciv. The installed size shrinks by ~70MB, the ZIP size by ~9MB.
I asked
jdeps
which modules are required:jdk\bin\jdeps.exe --print-module-deps --ignore-missing-deps --recursive --multi-release 11 Unciv.jar
(supplying an unpacked jar to --class-path and/or --module-path did not change the result).Then I asked jlink to make a runtime: Delete jre from extracted zip, leave exe and jar in place, then:
jdk\bin\jlink.exe --add-modules java.base,java.desktop,java.instrument,java.logging,java.management,java.prefs,jdk.unsupported,jdk.crypto.ec --strip-debug --no-man-pages --no-header-files --compress=2 --output .\jre
(jdk.crypto.ec was missed by jdeps, missing it blocks any https)Now jre/lib/modules is 20M instead of 90M, and zipping it back up gives 79.6MiB.
Alternative Approaches
Not investigated whether a similar effect can be achieved using our current packer.
Additional Context
There's not much savings to be had elsewhere - translations is 15M uncompressed, kotlin reflection is >8M of class files, looking into why com.unciv is taking so much space just leads to tons of successively smaller files...
The text was updated successfully, but these errors were encountered: