mirror of
https://github.com/hpi-swa/native-minecraft-server.git
synced 2024-11-27 15:01:57 +00:00
Add project files
This commit is contained in:
parent
710cf1096d
commit
b7300a343e
25
.github/workflows/main.yml
vendored
Normal file
25
.github/workflows/main.yml
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
name: Build Native Minecraft Server
|
||||
on: [ push, pull_request ]
|
||||
jobs:
|
||||
build:
|
||||
name: Build on ${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: graalvm/setup-graalvm@v1
|
||||
with:
|
||||
version: '22.2.0'
|
||||
java-version: '17'
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Check build.sh
|
||||
shell: bash
|
||||
run: shellcheck build.sh
|
||||
if: ${{ matrix.os == 'ubuntu-latest' }}
|
||||
- name: Build and run native Minecraft server
|
||||
shell: bash
|
||||
run: |
|
||||
./build.sh
|
||||
./native-minecraft-server --help
|
9
.gitignore
vendored
Normal file
9
.gitignore
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
/*.json
|
||||
build
|
||||
debug
|
||||
eula.txt
|
||||
logs
|
||||
native-minecraft-server
|
||||
server.properties
|
||||
sources
|
||||
world
|
63
README.md
63
README.md
@ -1 +1,62 @@
|
||||
# Native Minecraft Server
|
||||
# Native Minecraft Servers with GraalVM Native Image
|
||||
|
||||
[![Build Native Minecraft Server](https://github.com/hpi-swa/native-minecraft-server/actions/workflows/main.yml/badge.svg)](https://github.com/hpi-swa/native-minecraft-server/actions/workflows/main.yml)
|
||||
|
||||
![Banner](./assets/graalvm_native_image_minecraft_banner.jpg)
|
||||
|
||||
The Minecraft server is known to require a lot of CPU and memory resources and can be hard to deploy.
|
||||
This project makes it possible to compile the Minecraft server into a self-contained native executable using [GraalVM Native Image][ni].
|
||||
As such, it is supposed to require fewer CPU and memory resources, provide better startup times, and be easier and cheaper to deploy.
|
||||
|
||||
A native Minecraft server is less than 120MB in size, and with that significantly smaller than Minecraft's `server.jar` plus a JDK required to run it.
|
||||
With [upx] compression, the size of the native executable can be reduced even further to less than 40MB, which is smaller than just the `server.jar`.
|
||||
Initial experiments also suggest competitive run-time performance with a reduced memory footprint.
|
||||
For best results, build with [GraalVM Enterprise][ee] Native Image, which provides better performance and lower memory usage than the Community Edition, and try out the [G1 GC][g1gc] and [Profile-Guided Optimizations][pgo].
|
||||
The [Oracle Cloud Free Tier][oci-free] not only provides four Ampere A1 cores and 24 GB of RAM always free, which is plenty for [hosting a Minecraft server][oci-minecraft], but also free access to GraalVM Enterprise.
|
||||
|
||||
Check out [this blog post][blog-post] for more information.
|
||||
|
||||
*Disclaimer: This project is meant for demonstration purposes only and intended to help the Minecraft community evaluate the use of GraalVM Native Image. Please use at your own risk.*
|
||||
|
||||
## Getting Started
|
||||
|
||||
1. Download GraalVM [Community][ce] or [Enterprise][ee] *(GraalVM 22.2.0 or later is required)*.
|
||||
*Optional: make sure [upx] is on your `$PATH` to enable compression.*
|
||||
2. Download or check out this repository and run the [`build.sh`](build.sh).
|
||||
3. Launch the native Minecraft server with `./native-minecraft-server`.
|
||||
*The first time you run the server, you will have to follow the regular procedure of accepting Minecraft's EULA.*
|
||||
|
||||
## How It Works
|
||||
This project only contains the `build.sh` script and [reachability metadata][metadata] for building a native Minecraft server.
|
||||
The `build.sh` script first downloads Minecraft's `server.jar` and extracts jars and other resources from it.
|
||||
Afterward, it invokes GraalVM Native Image with an appropriate configuration to generate a native version of the Minecraft server.
|
||||
Finally, and only if [upx] is on the `$PATH`, the script will compress the native executable.
|
||||
|
||||
## Limitations and Known Issues
|
||||
|
||||
- The configuration currently only supports Minecraft `1.18.2`.
|
||||
- The server GUI is not yet supported.
|
||||
- Mods are currently not supported.
|
||||
- There is no build script for Windows yet, but the [WSL] should work.
|
||||
- The native executable sometimes fails on startup. Restarting it a few times usually helps.
|
||||
*Error: `com.mojang.datafixers.types.templates.List$ListType cannot be cast to java.lang.Comparable`*.
|
||||
|
||||
## Contributions
|
||||
Please [report any issues here on GitHub][issues] and open pull requests if you'd like to contribute to the project.
|
||||
|
||||
## License
|
||||
This project is released under the [MIT license](./LICENSE).
|
||||
|
||||
|
||||
[blog-post]: https://medium.com/p/1a3f6a92eb48
|
||||
[ce]: https://github.com/graalvm/graalvm-ce-builds/releases/latest
|
||||
[ee]: https://www.oracle.com/downloads/graalvm-downloads.html
|
||||
[g1gc]: https://www.graalvm.org/22.2/reference-manual/native-image/optimizations-and-performance/MemoryManagement/
|
||||
[issues]: https://github.com/hpi-swa/native-minecraft-server/issues
|
||||
[metadata]: https://www.graalvm.org/22.2/reference-manual/native-image/metadata/
|
||||
[ni]: https://www.graalvm.org/native-image/
|
||||
[oci-free]: https://www.oracle.com/cloud/free/
|
||||
[oci-minecraft]: https://blogs.oracle.com/developers/post/how-to-set-up-and-run-a-really-powerful-free-minecraft-server-in-the-cloud
|
||||
[pgo]: https://www.graalvm.org/22.2/reference-manual/native-image/guides/optimize-native-executable-with-pgo/
|
||||
[upx]: https://upx.github.io/
|
||||
[wsl]: https://docs.microsoft.com/en-us/windows/wsl/install
|
||||
|
BIN
assets/graalvm_native_image_minecraft_banner.jpg
Normal file
BIN
assets/graalvm_native_image_minecraft_banner.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 91 KiB |
75
build.sh
Executable file
75
build.sh
Executable file
@ -0,0 +1,75 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -o errexit
|
||||
set -o nounset
|
||||
|
||||
SERVER_JAR_DL="https://launcher.mojang.com/v1/objects/c8f83c5655308435b3dcf03c06d9fe8740a77469/server.jar"
|
||||
SCRIPT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||
BUILD_DIR="${SCRIPT_DIR}/build"
|
||||
JAR_PATH="${BUILD_DIR}/server.jar"
|
||||
META_INF_PATH="${BUILD_DIR}/META-INF"
|
||||
BINARY_NAME="native-minecraft-server"
|
||||
NI_EXEC="${GRAALVM_HOME:-}/bin/native-image"
|
||||
readonly SERVER_JAR_DL SCRIPT_DIR BUILD_DIR JAR_PATH META_INF_PATH BINARY_NAME NI_EXEC
|
||||
|
||||
if [[ -z "${GRAALVM_HOME:-}" ]]; then
|
||||
echo "\$GRAALVM_HOME is not set. Please provide a GraalVM installation. Exiting..."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command -v "${NI_EXEC}" &> /dev/null; then
|
||||
echo "Installing GraalVM Native Image..."
|
||||
"${GRAALVM_HOME}/bin/gu" install --no-progress native-image
|
||||
fi
|
||||
|
||||
if [[ ! -d "${BUILD_DIR}" ]]; then
|
||||
mkdir "${BUILD_DIR}"
|
||||
fi
|
||||
pushd "${BUILD_DIR}" > /dev/null
|
||||
|
||||
if [[ ! -f "${JAR_PATH}" ]]; then
|
||||
echo "Downloading Minecraft's server.jar..."
|
||||
curl --show-error --fail --location -o "${JAR_PATH}" "${SERVER_JAR_DL}"
|
||||
fi
|
||||
|
||||
if [[ ! -d "${META_INF_PATH}" ]]; then
|
||||
echo "Extracting resources from Minecraft's server.jar..."
|
||||
unzip -qq "${JAR_PATH}" "META-INF/*" -d "."
|
||||
fi
|
||||
|
||||
if [[ ! -f "${META_INF_PATH}/classpath-joined" ]]; then
|
||||
echo "Unable to determine classpath. Exiting..."
|
||||
exit 1
|
||||
fi
|
||||
CLASSPATH_JOINED=$(cat "${META_INF_PATH}/classpath-joined")
|
||||
readonly CLASSPATH_JOINED
|
||||
|
||||
if [[ ! -f "${META_INF_PATH}/main-class" ]]; then
|
||||
echo "Unable to determine main class. Exiting..."
|
||||
exit 1
|
||||
fi
|
||||
MAIN_CLASS=$(cat "${META_INF_PATH}/main-class")
|
||||
readonly MAIN_CLASS
|
||||
|
||||
pushd "${META_INF_PATH}" > /dev/null
|
||||
"${NI_EXEC}" --no-fallback \
|
||||
-H:ConfigurationFileDirectories="${SCRIPT_DIR}/configuration/" \
|
||||
--enable-url-protocols=https \
|
||||
--initialize-at-run-time=io.netty \
|
||||
-H:+AllowVMInspection \
|
||||
--initialize-at-build-time=net.minecraft.util.profiling.jfr.event \
|
||||
-H:Name="${BINARY_NAME}" \
|
||||
-cp "${CLASSPATH_JOINED//;/:}" \
|
||||
"${MAIN_CLASS}"
|
||||
mv "${BINARY_NAME}" "${SCRIPT_DIR}/${BINARY_NAME}"
|
||||
popd > /dev/null # Exit $META_INF_PATH
|
||||
popd > /dev/null # Exit $BUILD_DIR
|
||||
|
||||
if command -v upx &> /dev/null; then
|
||||
echo "Compressing the native Minecraft server with upx..."
|
||||
upx "${SCRIPT_DIR}/${BINARY_NAME}"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Done! The native Minecraft server is located at:"
|
||||
echo "${SCRIPT_DIR}/${BINARY_NAME}"
|
159
configuration/jni-config.json
Normal file
159
configuration/jni-config.json
Normal file
@ -0,0 +1,159 @@
|
||||
[
|
||||
{
|
||||
"name":"[Lcom.sun.management.internal.DiagnosticCommandArgumentInfo;"
|
||||
},
|
||||
{
|
||||
"name":"[Lcom.sun.management.internal.DiagnosticCommandInfo;"
|
||||
},
|
||||
{
|
||||
"name":"com.sun.management.internal.DiagnosticCommandArgumentInfo",
|
||||
"methods":[{"name":"<init>","parameterTypes":["java.lang.String","java.lang.String","java.lang.String","java.lang.String","boolean","boolean","boolean","int"] }]
|
||||
},
|
||||
{
|
||||
"name":"com.sun.management.internal.DiagnosticCommandInfo",
|
||||
"methods":[{"name":"<init>","parameterTypes":["java.lang.String","java.lang.String","java.lang.String","java.lang.String","java.lang.String","java.lang.String","boolean","java.util.List"] }]
|
||||
},
|
||||
{
|
||||
"name":"io.netty.channel.ChannelException"
|
||||
},
|
||||
{
|
||||
"name":"io.netty.channel.DefaultFileRegion",
|
||||
"fields":[
|
||||
{"name":"file"},
|
||||
{"name":"transferred"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name":"io.netty.channel.epoll.LinuxSocket"
|
||||
},
|
||||
{
|
||||
"name":"io.netty.channel.epoll.Native"
|
||||
},
|
||||
{
|
||||
"name":"io.netty.channel.epoll.NativeDatagramPacketArray$NativeDatagramPacket",
|
||||
"fields":[
|
||||
{"name":"count"},
|
||||
{"name":"memoryAddress"},
|
||||
{"name":"recipientAddr"},
|
||||
{"name":"recipientAddrLen"},
|
||||
{"name":"recipientPort"},
|
||||
{"name":"recipientScopeId"},
|
||||
{"name":"segmentSize"},
|
||||
{"name":"senderAddr"},
|
||||
{"name":"senderAddrLen"},
|
||||
{"name":"senderPort"},
|
||||
{"name":"senderScopeId"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name":"io.netty.channel.epoll.NativeStaticallyReferencedJniMethods"
|
||||
},
|
||||
{
|
||||
"name":"io.netty.channel.unix.Buffer"
|
||||
},
|
||||
{
|
||||
"name":"io.netty.channel.unix.DatagramSocketAddress",
|
||||
"methods":[{"name":"<init>","parameterTypes":["byte[]","int","int","int","io.netty.channel.unix.DatagramSocketAddress"] }]
|
||||
},
|
||||
{
|
||||
"name":"io.netty.channel.unix.DomainDatagramSocketAddress",
|
||||
"methods":[{"name":"<init>","parameterTypes":["byte[]","int","io.netty.channel.unix.DomainDatagramSocketAddress"] }]
|
||||
},
|
||||
{
|
||||
"name":"io.netty.channel.unix.ErrorsStaticallyReferencedJniMethods"
|
||||
},
|
||||
{
|
||||
"name":"io.netty.channel.unix.FileDescriptor"
|
||||
},
|
||||
{
|
||||
"name":"io.netty.channel.unix.LimitsStaticallyReferencedJniMethods"
|
||||
},
|
||||
{
|
||||
"name":"io.netty.channel.unix.PeerCredentials",
|
||||
"methods":[{"name":"<init>","parameterTypes":["int","int","int[]"] }]
|
||||
},
|
||||
{
|
||||
"name":"io.netty.channel.unix.Socket"
|
||||
},
|
||||
{
|
||||
"name":"java.io.FileDescriptor",
|
||||
"fields":[{"name":"fd"}]
|
||||
},
|
||||
{
|
||||
"name":"java.io.IOException"
|
||||
},
|
||||
{
|
||||
"name":"java.lang.Boolean",
|
||||
"methods":[{"name":"getBoolean","parameterTypes":["java.lang.String"] }]
|
||||
},
|
||||
{
|
||||
"name":"java.lang.ClassLoader",
|
||||
"methods":[
|
||||
{"name":"getPlatformClassLoader","parameterTypes":[] },
|
||||
{"name":"loadClass","parameterTypes":["java.lang.String"] }
|
||||
]
|
||||
},
|
||||
{
|
||||
"name":"java.lang.OutOfMemoryError"
|
||||
},
|
||||
{
|
||||
"name":"java.lang.RuntimeException"
|
||||
},
|
||||
{
|
||||
"name":"java.lang.SecurityManager",
|
||||
"fields":[{"name":"initialized"}]
|
||||
},
|
||||
{
|
||||
"name":"java.net.InetSocketAddress",
|
||||
"methods":[{"name":"<init>","parameterTypes":["java.lang.String","int"] }]
|
||||
},
|
||||
{
|
||||
"name":"java.net.PortUnreachableException"
|
||||
},
|
||||
{
|
||||
"name":"java.nio.Buffer",
|
||||
"fields":[
|
||||
{"name":"limit"},
|
||||
{"name":"position"}
|
||||
],
|
||||
"methods":[
|
||||
{"name":"limit","parameterTypes":[] },
|
||||
{"name":"position","parameterTypes":[] }
|
||||
]
|
||||
},
|
||||
{
|
||||
"name":"java.nio.DirectByteBuffer"
|
||||
},
|
||||
{
|
||||
"name":"java.nio.channels.ClosedChannelException",
|
||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
||||
},
|
||||
{
|
||||
"name":"java.util.Arrays",
|
||||
"methods":[{"name":"asList","parameterTypes":["java.lang.Object[]"] }]
|
||||
},
|
||||
{
|
||||
"name":"jdk.internal.loader.ClassLoaders$PlatformClassLoader"
|
||||
},
|
||||
{
|
||||
"name":"org.graalvm.jniutils.JNIExceptionWrapperEntryPoints",
|
||||
"methods":[{"name":"getClassName","parameterTypes":["java.lang.Class"] }]
|
||||
},
|
||||
{
|
||||
"name":"sun.management.VMManagementImpl",
|
||||
"fields":[
|
||||
{"name":"compTimeMonitoringSupport"},
|
||||
{"name":"currentThreadCpuTimeSupport"},
|
||||
{"name":"objectMonitorUsageSupport"},
|
||||
{"name":"otherThreadCpuTimeSupport"},
|
||||
{"name":"remoteDiagnosticCommandsSupport"},
|
||||
{"name":"synchronizerUsageSupport"},
|
||||
{"name":"threadAllocatedMemorySupport"},
|
||||
{"name":"threadContentionMonitoringSupport"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name":"sun.nio.ch.FileChannelImpl",
|
||||
"fields":[{"name":"fd"}]
|
||||
}
|
||||
]
|
8
configuration/predefined-classes-config.json
Normal file
8
configuration/predefined-classes-config.json
Normal file
@ -0,0 +1,8 @@
|
||||
[
|
||||
{
|
||||
"type":"agent-extracted",
|
||||
"classes":[
|
||||
]
|
||||
}
|
||||
]
|
||||
|
2
configuration/proxy-config.json
Normal file
2
configuration/proxy-config.json
Normal file
@ -0,0 +1,2 @@
|
||||
[
|
||||
]
|
2156
configuration/reflect-config.json
Normal file
2156
configuration/reflect-config.json
Normal file
File diff suppressed because it is too large
Load Diff
63
configuration/resource-config.json
Normal file
63
configuration/resource-config.json
Normal file
@ -0,0 +1,63 @@
|
||||
{
|
||||
"resources":{
|
||||
"includes":[
|
||||
{
|
||||
"pattern":"assets/.*"
|
||||
},
|
||||
{
|
||||
"pattern":"data/.*"
|
||||
},
|
||||
{
|
||||
"pattern":"\\QMETA-INF/MOJANGCS.SF\\E"
|
||||
},
|
||||
{
|
||||
"pattern":"\\QMETA-INF/MOJANGCS.RSA\\E"
|
||||
},
|
||||
{
|
||||
"pattern":"\\Qflightrecorder-config.jfc\\E"
|
||||
},
|
||||
{
|
||||
"pattern":"\\QMETA-INF/libraries.list\\E"
|
||||
},
|
||||
{
|
||||
"pattern":"\\QMETA-INF/native/libnetty_transport_native_epoll_x86_64.so\\E"
|
||||
},
|
||||
{
|
||||
"pattern":"\\QMETA-INF/org/apache/logging/log4j/core/config/plugins/Log4j2Plugins.dat\\E"
|
||||
},
|
||||
{
|
||||
"pattern":"\\QMETA-INF/services/java.nio.file.spi.FileSystemProvider\\E"
|
||||
},
|
||||
{
|
||||
"pattern":"\\QMETA-INF/services/org.apache.logging.log4j.core.util.ContextDataProvider\\E"
|
||||
},
|
||||
{
|
||||
"pattern":"\\QMETA-INF/services/org.apache.logging.log4j.spi.Provider\\E"
|
||||
},
|
||||
{
|
||||
"pattern":"\\QMETA-INF/services/org.apache.logging.log4j.util.PropertySource\\E"
|
||||
},
|
||||
{
|
||||
"pattern":"\\QMETA-INF/services/org.slf4j.spi.SLF4JServiceProvider\\E"
|
||||
},
|
||||
{
|
||||
"pattern":"\\Qlog4j2.xml\\E"
|
||||
},
|
||||
{
|
||||
"pattern":"\\Qoshi.architecture.properties\\E"
|
||||
},
|
||||
{
|
||||
"pattern":"\\Qoshi.properties\\E"
|
||||
},
|
||||
{
|
||||
"pattern":"\\Qversion.json\\E"
|
||||
},
|
||||
{
|
||||
"pattern":"\\Qyggdrasil_session_pubkey.der\\E"
|
||||
}
|
||||
]},
|
||||
"bundles":[
|
||||
{ "name":"joptsimple.ExceptionMessages" },
|
||||
{ "name":"joptsimple.HelpFormatterMessages" }
|
||||
]
|
||||
}
|
6
configuration/serialization-config.json
Normal file
6
configuration/serialization-config.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"types":[
|
||||
],
|
||||
"lambdaCapturingTypes":[
|
||||
]
|
||||
}
|
Loading…
Reference in New Issue
Block a user