Rendimiento y lag

Versiones de Java y Parámetros de Inicio Personalizados

Revisado el 6 de septiembre de 2026 3 min de lectura

Dos servidores pueden correr el mismo jar, los mismos plugins y la misma cantidad de jugadores, y uno da tirones cada par de minutos mientras el otro no. La diferencia muchas veces no está en el servidor en absoluto. Está en cómo se le dijo al recolector de basura de Java que se comportara.

Qué le hace de verdad el recolector de basura a tu tick

Java gestiona la memoria por ti: los objetos que tu código deja de referenciar acaban siendo recuperados por el recolector de basura, en automático. El problema es que recuperar memoria es trabajo en sí mismo, y por defecto la JVM decide cuándo hacer ese trabajo según sus propias reglas heurísticas, pensadas para software genérico y no para un programa que tiene 50 milisegundos para terminar un tick y ni uno más.

Cuando el recolector decide que hace falta una pausa, todos los hilos —incluido el que corre tu mundo— se paran hasta que termina. Una pausa pequeña y frecuente es invisible. Un recolector que deja que se acumule basura y luego hace una recolección grande produce justo el síntoma que la gente describe como «el servidor se congela un segundo cada pocos minutos», y es el propio diseño del recolector haciendo eso, no un fallo.

Qué está haciendo de verdad un buen conjunto de flags

ObjetivoCómo se consigue
Un recolector de basura modernoCambiar a G1GC (por defecto en Java reciente, pero conviene confirmarlo) en vez de un recolector viejo pensado para rendimiento total antes que latencia
Pausas cortas y predecibles en vez de pocas largasUn objetivo de tiempo de pausa máximo que le dice al recolector que haga recolecciones más frecuentes y pequeñas en vez de menos y grandes
Menos recolección en totalTamaño de regiones y umbrales de porcentaje de heap ajustados al patrón de acceso de un servidor de juego y no al de una aplicación Java genérica
Los flags no pueden compensar poca memoria

El recolector de basura tiene que esforzarse más según se llena el heap, y un heap que está constantemente casi lleno va a pausar por muy bien afinado que esté el recolector: los flags cambian con cuánta elegancia se degrada, no cuánta memoria hay. Si afinar los flags no arregló un tirón, la siguiente pregunta honesta es si el plan tiene memoria suficiente para lo que corre de verdad, no qué otro conjunto de flags probar.

Aplicar un conjunto de flags

  1. Ponlos como argumentos de la JVM, antes de -jar

    Configuran el propio proceso de Java, no el servidor de Minecraft: el orden en el comando de inicio importa, y tienen que ir antes de nombrar el jar.

  2. Iguala -Xms y -Xmx al mismo valor

    Un heap al que se le deja crecer y encoger provoca trabajo extra de recolección solo por redimensionarse. Fijar los dos a la asignación del plan elimina ese coste por completo.

  3. Cambia una cosa y observa, no cinco

    Los conjuntos de flags interactúan entre sí. Probar el conjunto entero de golpe te dice si ayudó; probar cada pieza por separado te dice cuál lo hizo.

Esto explica tirones que las gráficas de memoria solas no explican

Un servidor puede tener memoria de sobra según la gráfica del panel y aun así pausar, porque la pausa va de cómo está eligiendo el recolector recuperar memoria, no de si la memoria se acabó. Mirar la CPU junto a la memoria durante un tirón suele mostrar un pico breve en un núcleo —el recolector haciendo su trabajo—, que es la firma que hay que buscar.