在微服务架构越来越盛行的情况下,我们通常一个系统都会拆成很多个小的服务,但是最终部署的时候又因为没有那么多服务器只能把多个服务部署在同一台服务器上,这个时候问题就来了,服务器内存不够,这个时候我们就需要对每个服务的内存开始精细分配,以达到充分利用每一台服务器的目的
首先来看一下我们用来启动 jar 包的常用命令
bash
nohup java -Xms512m -Xmx512m -Xmn256m -Xss512k -server -XX:+HeapDumpOnOutOfMemoryError -jar your-application.jar > output.log 2>&1 &
下面我们来一点点的解析这行命令
nohup:
在后台运行命令并忽略挂起信号(这个应该都知道没什么好说的)。
-Xms512m:
含义:设置 JVM 初始堆内存大小为 512MB。
作用:JVM 启动时分配的初始内存大小,确保在应用程序启动时有足够的内存。
-Xmx512m:
含义:设置 JVM 最大堆内存大小为 512MB。
作用:JVM 运行过程中可以使用的最大内存限制,防止应用程序占用过多的系统内存。
-Xmn256m:
含义:设置新生代内存大小为 256MB。
作用:控制新生代(Young Generation)的大小,新生代用于存放新创建的对象。适当调整可以影响垃圾回收的频率和性能。
-Xss512k:
含义:设置每个线程的栈大小为 512KB。
作用:控制每个线程的栈内存大小。如果应用程序创建大量线程或有深度递归调用,需要适当调整该值。
-server:
含义:启用 JVM 的服务器模式。
作用:服务器模式针对长期运行的服务器应用程序进行了优化,包括更高级的编译优化和垃圾回收策略。
-XX:+HeapDumpOnOutOfMemoryError:
含义:在发生内存溢出错误(OutOfMemoryError)时生成堆转储文件。
作用:当应用程序由于内存不足而崩溃时,生成堆转储文件(heap dump),便于后续进行内存分析和调试。
知道了这些参数的含义以及作用,在使用的过程中还有些地方需要注意
调整堆内存大小:根据应用程序的实际内存需求,调整 -Xms 和 -Xmx的值。通常,初始堆大小(-Xms)和最大堆大小(-Xmx)应该设置为相同,以避免 JVM在运行过程中调整堆大小带来的开销。
-Xms1024m -Xmx1024m
新生代内存调整:新生代(-Xmn)的大小应该根据应用程序对象的生命周期进行调整。一般来说,新生代应占堆内存的 1/3 到1/4。
-Xmn512m
垃圾回收器选择:不同的垃圾回收器适用于不同类型的应用程序。常见的垃圾回收器有 G1、CMS 和 Parallel GC。可以根据应用程序的特点选择合适的垃圾回收器。
G1 垃圾回收器(适合具有低延迟要求的应用程序)
-XX:+UseG1GC
CMS 垃圾回收器(适合需要短暂停顿时间的应用程序)
-XX:+UseConcMarkSweepGC
并行垃圾回收器(适合高吞吐量要求的应用程序)
-XX:+UseParallelGC
元空间大小调整:调整元空间(Metaspace)大小,避免频繁的元空间扩展。
-XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m
垃圾回收日志:启用垃圾回收日志,以便于调试和优化垃圾回收。
-Xlog:gc*:file=gc.log:time,level,tags
线程栈大小调整:根据应用程序的线程使用情况调整线程栈大小。
-Xss1m
启用类数据共享
-XX:+UseAppCDS
启用自适应大小线程池:
-XX:+UseAdaptiveSizePolicy
综合一下就是下面这条命令
bash
nohup java -Xms1024m -Xmx1024m -Xmn512m -Xss1m -server -XX:+HeapDumpOnOutOfMemoryError -XX:+UseG1GC -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m -Xlog:gc*:file=gc.log:time,level,tags -jar your-application.jar > output.log 2>&1 &
接着我们再来说一下简洁版的启动命令
bash
nohup java -jar your-application.jar &
在没有指定任何 JVM 参数的情况下,使用 nohup java -jar your-application.jar & 启动 Java 应用程序时,JVM将使用默认的内存设置。这些默认值通常取决于 JVM 的版本、操作系统以及系统的可用内存。以下是一些默认设置的概述:
堆内存:
默认初始堆大小(-Xms):通常为物理内存的 1/64,但不超过 1GB。
默认最大堆大小(-Xmx):通常为物理内存的 1/4,但不超过32GB。
新生代内存:
新生代大小(-Xmn):默认情况下,新生代的大小会根据堆大小动态调整。
线程栈大小:
默认线程栈大小(-Xss):这取决于操作系统和 JVM 实现。通常在 Linux 上为 1MB,Windows 上为 320KB。
垃圾回收器:
JVM 会选择默认的垃圾回收器,这通常是并行垃圾回收器(Parallel GC),具体取决于 JVM 的版本。
元空间:
默认情况下,元空间(Metaspace)大小会动态调整。
这个呢大家也可以直接在服务器上查看
bash
java -XX:+PrintFlagsFinal -version
也可以在程序运行时查看
java
public static void main(String[] args) {
Runtime runtime = Runtime.getRuntime();
long maxMemory = runtime.maxMemory();
long allocatedMemory = runtime.totalMemory();
long freeMemory = runtime.freeMemory();
System.out.println("Max Memory: " + maxMemory / 1024 / 1024 + " MB");
System.out.println("Allocated Memory: " + allocatedMemory / 1024 / 1024 + " MB");
System.out.println("Free Memory: " + freeMemory / 1024 / 1024 + " MB");
}
我这个就是本机默认的,明显有些大了
好了,合理分配内存,节约服务器空间从你我做起