Optymalizacja flag JVM Javy dla serwerów Minecraft: pełny poradnik
Każdy serwer Minecraft działa na Java Virtual Machine, a domyślne ustawienia JVM nie są projektowane pod serwery gamingowe. Są dostosowane do uniwersalnych aplikacji, gdzie przepustowość ważniejsza od opóźnienia. Dla serwera Minecraft opóźnienie decyduje o wszystkim. Pauza garbage collectora 200ms oznacza widoczny lag-spike, który gracze czują natychmiast. W MineGuard konfigurowaliśmy JVM dla setek serwerów i w tym poradniku dzielimy się wszystkim, co wiemy.
Co tak naprawdę robią flagi JVM
Gdy uruchamiasz serwer komendą java -jar server.jar, JVM używa domyślnych ustawień do zarządzania pamięcią, garbage collection i optymalizacji w czasie wykonywania. Te ustawienia są dostosowane pod uniwersalne obciążenia. Minecraft nie jest uniwersalny. Tworzy i wyrzuca miliony małych obiektów co sekundę (aktualizacje bloków, ticki encji, bufory pakietów) i potrzebuje stabilnego taimingu ticków bez pauz dłuższych niż 50ms.
Flagi JVM pozwalają nadpisać te ustawienia. Kontrolują objętość pamięci JVM, jaki garbage collector pracuje, jak agresywnie zbiera i dziesiątki innych parametrów. Poprawna kombinacja może skrócić pauzy GC o 80% i ustabilizować TPS na pełnych 20.
Podstawy pamięci: -Xmx i -Xms
Dwie najważniejsze flagi to -Xmx (maksymalny rozmiar heap) i -Xms (początkowy rozmiar heap). Zawsze ustawiaj je na tę samą wartość:
-Xms8G -Xmx8G
Dlaczego te same? Gdy -Xms jest mniejsze niż -Xmx, JVM startuje z mniejszą objętością pamięci i dynamicznie powiększa heap. Przy każdym powiększeniu JVM zatrzymuje proces na czas realokacji. Ustawienie tych samych wartości całkowicie eliminuje te pauzy. JVM alokuje całą pamięć na starcie i już więcej nie zmienia rozmiaru.
Ile RAM potrzebuje twój serwer?
Praktyczne rekomendacje według liczby graczy i złożoności świata:
- 1-20 graczy: 2-4 GB
- 20-50 graczy: 4-6 GB
- 50-100 graczy: 6-8 GB
- 100-200 graczy: 8-12 GB
- 200+ graczy: 12-16 GB
Te liczby zakładają Paper albo Purpur z umiarkowaną liczbą pluginów (15-30). Mocno zmodyfikowane serwery (Forge/Fabric z 100+ modami) mogą wymagać 2-4 GB więcej.
Typowy błąd: przydzielanie za dużo RAM. Jeśli masz dostępne 32 GB, nie stawiaj -Xmx32G. Garbage collector musi przeskanować cały heap przy zbieraniu. Większy heap = dłuższe pauzy GC. Daj serwerowi tyle, ile potrzebuje, plus 20-30% zapasu, nie więcej.
Garbage collection: serce konfiguracji JVM
Garbage collection (GC) to proces znajdowania i zwalniania pamięci, której twój serwer już nie używa. JVM robi to automatycznie, ale sposób, w jaki to się dzieje, ma ogromne znaczenie. Podczas pauzy GC twój serwer dosłownie przestaje przetwarzać ticki.
G1GC (Garbage First Garbage Collector)
G1GC to rekomendowany garbage collector dla serwerów Minecraft i podstawa flag Aikara. Dzieli heap na regiony i zbiera te, w których jest najwięcej śmieci (stąd nazwa). Takie podejście daje przewidywalny czas pauz.
Dlaczego G1GC dobrze pasuje do Minecrafta:
- Docelowy maksymalny czas pauzy (konfigurowany przez
MaxGCPauseMillis) - Efektywnie pracuje z heapami od 2 do 16 GB
- Wykonuje podstawową pracę concurrent, bez zatrzymywania serwera
- Świetnie radzi sobie z obciążeniami generującymi dużo krótkożyjących obiektów (a Minecraft robi to stale)
ZGC (Z Garbage Collector)
ZGC to collector z niskim opóźnieniem dopasowany do submilisekundowych pauz. Brzmi idealnie? Niezupełnie. ZGC poświęca przepustowość na rzecz czasu pauz. Używa więcej CPU do osiągnięcia tak małych pauz, a na serwerach z ograniczoną liczbą rdzeni ten narzut może zaszkodzić TPS.
ZGC warto spróbować, jeśli:
- Masz 8+ rdzeni CPU dedykowanych dla serwera
- Heap 16 GB albo większy
- Używasz Java 21+ (ZGC znacznie się poprawił w ostatnich wersjach)
Dla większości serwerów G1GC z ustawieniami Aikara zadziała lepiej niż ZGC.
Shenandoah
Shenandoah to kolejny collector z niskimi pauzami, podobny w celach do ZGC, ale z innym podejściem. Dostępny w buildach OpenJDK (nie Oracle JDK). Podobnie jak ZGC, wymienia CPU na czas pauz i najlepiej pracuje na serwerach z dostateczną liczbą rdzeni.
Nasza rekomendacja: zacznij od G1GC. Przełączaj się na ZGC albo Shenandoah tylko, jeśli profilowałeś serwer przez Spark i potwierdziłeś, że pauzy GC to twoje wąskie gardło, a masz zapas CPU.
Flagi Aikara: złoty standard
Flagi Aikara to zestaw flag JVM specjalnie dostosowanych do serwerów Minecraft. Sprawdzone na serwerach z tysiącami graczy i dopracowywane latami. Rozbierzmy, co robi każda flaga:
Rozbiór głównych flag
-XX:+UseG1GC
Włącza garbage collector G1 zamiast domyślnego.
-XX:+ParallelRefProcEnabled
Przetwarza obiekty referencyjne (WeakReferences, SoftReferences) równolegle, nie sekwencyjnie. Pluginy Minecrafta tworzą dużo takich obiektów.
-XX:MaxGCPauseMillis=200
Wskazuje G1GC docelową maksymalną pauzę 200ms. Collector dostosowuje swoje zachowanie, żeby zostać w ramach tego celu.
-XX:+UnlockExperimentalVMOptions
Włącza eksperymentalne flagi niedostępne domyślnie. Potrzebne do niektórych parametrów poniżej.
-XX:+DisableExplicitGC
Zakazuje pluginom wywoływać System.gc() ręcznie. Niektóre źle napisane pluginy robią to, wywołując niepotrzebne pełne pauzy GC.
-XX:G1NewSizePercent=30
-XX:G1MaxNewSizePercent=40
Przydziela 30-40% heapu pod młodą generację (gdzie trafiają nowe obiekty). Minecraft tworzy tony krótkożyjących obiektów, więc większa młoda generacja oznacza rzadsze zbieranie.
-XX:G1HeapRegionSize=8M
Ustawia rozmiar każdego regionu G1 na 8 MB. Większe regiony zmniejszają narzut dla dużych heapów, ale mogą zwiększać pauzy dla małych. 8M to optymalny balans dla serwerów z 4-16 GB.
-XX:G1ReservePercent=20
Rezerwuje 20% heapu jako bufor bezpieczeństwa. To zapobiega tym strasznym pełnym pauzom GC 'to-space exhausted', które zdarzają się, gdy collectorowi kończą się wolne regiony.
-XX:G1MixedGCLiveThresholdPercent=90
Zbiera region tylko, jeśli 90% lub więcej jego zawartości to śmieci. To zmniejsza objętość żywych danych, które trzeba kopiować przy zbieraniu.
-XX:InitiatingHeapOccupancyPercent=15
Uruchamia cykl GC concurrent, gdy zajęte jest 15% heapu. To agresywne (domyślnie 45%), ale oznacza, że collector zaczyna pracę wcześnie i ma więcej czasu zakończyć bez pauzy.
-XX:SurvivorRatio=32
Zmniejsza rozmiar obszaru survivor. W obciążeniach Minecrafta obiekty albo umierają natychmiast, albo żyją długo (jak załadowane chunki). Mniej potrzeby trzymania obiektów między zbieraniem.
-XX:+PerfDisableSharedMem
Wyłącza zapis statystyk GC do pliku pamięci współdzielonej. Eliminuje okresowe spike'i opóźnienia od operacji plikowych.
-XX:MaxTenuringThreshold=1
Promuje obiekty do starej generacji po zaledwie 1 cyklu GC. W połączeniu z dużą młodą generacją dobrze pracuje dla wzorca alokacji Minecrafta.
GraalVM: alternatywne środowisko uruchomieniowe
GraalVM to alternatywna dystrybucja JDK z zaawansowanym kompilatorem JIT. Dla serwerów Minecraft GraalVM może dać 5-15% lepszą wydajność w porównaniu do zwykłego OpenJDK, zwłaszcza w scenariuszach obliczeniowo ciężkich, takich jak generacja świata i przetwarzanie redstonu.
Zalety GraalVM:
- Bardziej agresywna optymalizacja JIT
- Lepszy inlining wywołań metod
- Ulepszona analiza ucieczki (zmniejsza alokacje w heapie)
- Działa jako zamiennik OpenJDK bez zmian
Żeby używać GraalVM, pobierz go z oficjalnej strony i zamień swoją instalację Javy. Wszystkie flagi Aikara działają z GraalVM. Można też dodać specyficzne flagi:
-XX:+UseJVMCICompiler
-XX:+EagerJVMCI
Uwaga: GraalVM Community Edition jest darmowe. Enterprise Edition oferuje dodatkowe optymalizacje, ale wymaga licencji.
Duże strony pamięci
Duże strony (Large Pages, znane też jako Huge Pages) pozwalają JVM używać stron pamięci po 2 MB zamiast domyślnych 4 KB. To zmniejsza misses TLB (Translation Lookaside Buffer) i poprawia wydajność dostępu do pamięci o 5-10%.
Żeby włączyć duże strony:
- Skonfiguruj OS (Linux):
echo "vm.nr_hugepages=4096" >> /etc/sysctl.conf && sysctl -p - Dodaj flagę JVM:
-XX:+UseLargePages
Liczba potrzebnych huge pages to rozmiar heapu podzielony przez 2 MB. Dla heapu 8 GB: 8192 / 2 = 4096 stron.
Duże strony wymagają konfiguracji na poziomie root i są najbardziej przydatne na dedykowanych serwerach. Jeśli jesteś na hostingu, pomiń ten krok.
Deduplikacja stringów
Stringi Javy z identyczną zawartością można deduplikować dla oszczędności pamięci. To szczególnie przydatne dla Minecrafta, bo w pamięci istnieje dużo identycznych stringów (nazwy przedmiotów, typy bloków, wiadomości czatu).
-XX:+UseStringDeduplication
Ta flaga prawie nie obciąża CPU i może zmniejszyć zużycie pamięci o 5-10%. Działa tylko z G1GC, którego używają flagi Aikara.
Gotowe zestawy flag
Oto gotowe do użycia zestawy flag dla różnych rozmiarów serwerów. Kopiuj w całości i używaj jako komendę startową.
Mały serwer (2 GB RAM, 1-20 graczy)
java -Xms2G -Xmx2G -XX:+UseG1GC -XX:+ParallelRefProcEnabled -XX:MaxGCPauseMillis=200 -XX:+UnlockExperimentalVMOptions -XX:+DisableExplicitGC -XX:+AlwaysPreTouch -XX:G1NewSizePercent=30 -XX:G1MaxNewSizePercent=40 -XX:G1HeapRegionSize=4M -XX:G1ReservePercent=20 -XX:G1MixedGCLiveThresholdPercent=90 -XX:InitiatingHeapOccupancyPercent=15 -XX:SurvivorRatio=32 -XX:+PerfDisableSharedMem -XX:MaxTenuringThreshold=1 -XX:+UseStringDeduplication -jar server.jar --nogui
Uwaga: G1HeapRegionSize ustawione na 4M dla serwera 2 GB (mały heap wygrywa z mniejszymi regionami).
Średni serwer (4 GB RAM, 20-50 graczy)
java -Xms4G -Xmx4G -XX:+UseG1GC -XX:+ParallelRefProcEnabled -XX:MaxGCPauseMillis=200 -XX:+UnlockExperimentalVMOptions -XX:+DisableExplicitGC -XX:+AlwaysPreTouch -XX:G1NewSizePercent=30 -XX:G1MaxNewSizePercent=40 -XX:G1HeapRegionSize=8M -XX:G1ReservePercent=20 -XX:G1MixedGCLiveThresholdPercent=90 -XX:InitiatingHeapOccupancyPercent=15 -XX:SurvivorRatio=32 -XX:+PerfDisableSharedMem -XX:MaxTenuringThreshold=1 -XX:+UseStringDeduplication -jar server.jar --nogui
Duży serwer (8 GB RAM, 50-100 graczy)
java -Xms8G -Xmx8G -XX:+UseG1GC -XX:+ParallelRefProcEnabled -XX:MaxGCPauseMillis=200 -XX:+UnlockExperimentalVMOptions -XX:+DisableExplicitGC -XX:+AlwaysPreTouch -XX:G1NewSizePercent=40 -XX:G1MaxNewSizePercent=50 -XX:G1HeapRegionSize=16M -XX:G1ReservePercent=20 -XX:G1MixedGCLiveThresholdPercent=90 -XX:InitiatingHeapOccupancyPercent=15 -XX:SurvivorRatio=32 -XX:+PerfDisableSharedMem -XX:MaxTenuringThreshold=1 -XX:+UseStringDeduplication -XX:+UseLargePages -jar server.jar --nogui
Uwaga: zwiększone G1NewSizePercent do 40 i G1MaxNewSizePercent do 50 dla większego heapu. Dodano UseLargePages (wymaga konfiguracji OS).
Serwer korporacyjny (16 GB RAM, 200+ graczy)
java -Xms16G -Xmx16G -XX:+UseG1GC -XX:+ParallelRefProcEnabled -XX:MaxGCPauseMillis=200 -XX:+UnlockExperimentalVMOptions -XX:+DisableExplicitGC -XX:+AlwaysPreTouch -XX:G1NewSizePercent=40 -XX:G1MaxNewSizePercent=50 -XX:G1HeapRegionSize=16M -XX:G1ReservePercent=20 -XX:G1MixedGCLiveThresholdPercent=90 -XX:InitiatingHeapOccupancyPercent=15 -XX:SurvivorRatio=32 -XX:+PerfDisableSharedMem -XX:MaxTenuringThreshold=1 -XX:+UseStringDeduplication -XX:+UseLargePages -jar server.jar --nogui
Dla serwerów z 16 GB można też przetestować ZGC jako alternatywę:
java -Xms16G -Xmx16G -XX:+UseZGC -XX:+AlwaysPreTouch -XX:+DisableExplicitGC -XX:+UseLargePages -jar server.jar --nogui
ZGC wymaga mniej flag konfiguracyjnych, bo dostosowuje się sam. Przetestuj obie konfiguracje i porównaj przez profiler Spark.
Typowe błędy
Błąd 1: za dużo RAM. Heap 32 GB na serwerze z 20 graczami da ci dłuższe pauzy GC, nie lepszą wydajność. Garbage collector musi przeskanować cały heap. Trzymaj rozmiar optymalny.
Błąd 2: niewłaściwy garbage collector. CMS (Concurrent Mark Sweep) był popularny latami, ale usunięto go w Javie 14. Jeśli twój skrypt startowy wciąż zawiera -XX:+UseConcMarkSweepGC, zaktualizuj go natychmiast. G1GC to właściwy wybór.
Błąd 3: różne -Xms i -Xmx. Ustawienie -Xms512M -Xmx8G oznacza, że JVM będzie dziesiątki razy zmieniać rozmiar heapu w miarę ładowania serwera, powodując przycinki i pauzy w pierwszych minutach pracy.
Błąd 4: używanie Javy 8. Java 8 jest przestarzała. Każda nowa wersja Javy przynosi ulepszenia GC, patche bezpieczeństwa i optymalizacje wydajności. Używaj minimum Javy 21 LTS. W Javie 21 G1GC i ZGC są znacznie ulepszone w porównaniu ze starymi wersjami.
Błąd 5: ignorowanie logów GC. Dodaj -Xlog:gc*:file=gc.log:time do swoich flag. To stworzy plik logu pokazujący, co dokładnie robi garbage collector. Użyj narzędzi GCViewer albo GCEasy do analizy.
Poza JVM: wydajność sieci też ma znaczenie
Możesz dostroić JVM do perfekcji, ale jeśli twój serwer jest pod atakiem DDoS albo floodem botów, to wszystko nie ma znaczenia. Wydajność serwera i wydajność sieci to dwie strony tej samej monety.
W MineGuard bierzemy na siebie stronę sieciową. Nasz filtr działa na poziomie pakietów, weryfikując połączenia i blokując szkodliwy ruch, zanim dotrze do twojego serwera. Narzut? Mniej niż 1ms dodanego opóźnienia. Twoi gracze nie zauważą naszej ochrony, ale na pewno zauważą brak lag-spike'ów od floodów botów przeciążających serwer.
Optymalizuj flagi JVM pod wewnętrzną wydajność. Zagrożenia zewnętrzne zostaw nam. Razem to serwer, który trzyma stabilne 20 TPS w każdych warunkach.
Chroń swój serwer przed atakami DDoS
Darmowa ochrona z konfiguracją w 5 minut. 1 TB ruchu w zestawie.
Wypróbuj za darmoPowiązane artykuły
Jak chronić serwer Minecraft przed DDoS bez wiedzy technicznej
Nie znasz Linuxa i iptables? Żaden problem. Opowiadam, jak ochroniłem swój serwer Minecraft w 5 minut bez ani jednej komendy w konsoli. MineGuard wykonuje całą pracę techniczną za ciebie.
Profiler Spark: jak znaleźć przyczynę lagów na serwerze Minecraft (2026)
Spark zastąpił Timings po 1.21. Instalujemy plugin, odpalamy /spark profiler, czytamy flame-graph i szybko znajdujemy winowajcę: chunk gen, GC, słaby plugin albo redstone.
Layer 4 vs Layer 7 ataki DDoS - na czym polega różnica i dlaczego to ważne
Rozbieramy model OSI prostym językiem, wyjaśniamy różnicę między atakami L3/L4 a L7 na przykładach ze świata gier: SYN flood, UDP flood, HTTP flood, bot-joiny i tworzenie niepoprawnych pakietów. Dlaczego do prawdziwej ochrony potrzebne są oba poziomy.