JVM内存参数设置

简介: JVM内存参数设置

我们可以对运行时数据区的内存进行参数设置. 这是jvm调优的重点. 参数的变化将影响到整体效率

1187916-20200706125359526-1299569980.png

核心参数设置如下:

java -Xms2048M -Xmx1024M -Xss512k -XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=256M -jar microservice-eureka-server.jar

这里单独说一下spring boot项目启动的时候如何设置jvm参数?

tomcat启动直接加载bin目录下catalina.sh文件里面

一. 方法区(元空间)参数设置



在jdk8之前有各区域叫做永久代, 在jdk8及以后改名字了, 叫做元空间. 这块内存空间占用的是直接的物理内存.


元空间有一个特点: 可以动态扩容, 如果, 我们没有设置元空间的上限, 那么他可以扩大到整个内存. 比如内存条是8G的, 堆和栈分配了4G的空间, 那么元空间最多可以使用4G

我们可以通过参数来设置使用的最大内存

-XX:MetaspaceSize=256M     元空间的初始空间大小, 以字节位单位, 默认是21M,达到该值就会触发full GC, 同时收集器会对该值进行调整, 如果释放了大量的空间, 
                  就适当降低该值, 如果释放了很少的空间, 提升该值,但最到不超过-XX:MaxMetaspaceSize设置的值
-XX:MaxMetaspaceSize=256M   设置元空间的最大值, 默认是-1, 即不限制, 或者说只受限

对于64位的JVM来说, 元空间默认大小是21M, 元空间的默认最大值是无上限的, 他的上限就是内存空间


  • -XX:MetaspaceSize: 元空间的初始空间大小, 以字节位单位, 默认是21M,达到该值就会触发full GC, 同时收集器会对该值进行调整, 如果释放了大量的空间, 就适当降低该值, 如果释放了很少的空间, 提升该值,但最到不超过-XX:MaxMetaspaceSize设置的值


比如:


初始值是21M, 第一次回收了20M, 那么只有1M没有被回收, 下一次, 元空间会自动调整大小, 可能会调整到15M


初始大小依然是21M, 第二次回收发现回收了1M, 有20M没有被回收, 他就会自动扩大空间, 可能扩大到30M,也可能是40M


  • -XX:MaxMetaspaceSize: 设置元空间的最大值, 默认是-1, 即不限制, 或者说只受限于本地内存的大小


由于调整元空间的大小需要full GC, 这是非常昂贵的操作, 如果应用在启动的时候发生大量的full GC, 通常都是由于永久代或元空间发生了大小的调整, 基于这种情况, 一般建议在JVM参数中将-XX:MetaspaceSize和-XX:MaxMetaspaceSize设置成一样的值, 并设置的比初始值还要大, 对于8G物理内存的机器来说, 一般会将这两个值设置为256M或者512M都可以


建议: 设置元空间值, 不设置会怎么样?


不设置默认就是21M, 很容易就会放满, 通常我们的war可能都是几十M, 甚至几个G. 如果我们在启动程序的时候, 会启动几分钟. 这很有可能是没有设置元空间的大小.


放满后会发生full GC, 然后在扩大一点元空间, 扩大到25M, 重新开始, 过了一会又放满了, 再次full GC, 在扩大一点, 元空间扩大到30M, 就这样一直发生full GC, 然后一直扩大元空间, 直到扩大的元空间大小合适, 不再发生full gc, 程序才会正常启动运行. 这是个很耗时耗性能的操作, 这样的full GC也是没有必要的.

 

二. 栈参数设置



-Xss512k


这个参数就是用来设置栈空间的. 他是设置的一个线程栈占用的空间, 一个程序启动后可能有多个线程栈, 那么他们占用的空间都是512k

下面来看一个例子


package com.lxl.jvm;
public class StackOverflowTest {
    /**
     * jvm 设置-Xss128M, (默认是1M)
     */
    static int count = 0;
    public static void redo(){
        count ++;
        redo();
    }
    public static void main(String[] args) {
        try {
            redo();
        }catch (Throwable e) {
            e.printStackTrace();
            System.out.println(count);
        }
    }
}

这里定义了一个变量count, main方法里调用了redo()方法. 当我们执行main方法的时候, 线程栈模型是什么样的呢?

1187916-20200707092650055-381318040.png

当程序执行到main方法的时候, 会在线程栈中开辟一个main方法的栈帧

继续执行, 执行到redo()的时候, 会在线程栈在开辟一块redo方法栈帧

redo方法里又调用了redo方法. 继续开辟一块redo方法栈帧,

.......

栈帧是占用内存空间的. 总有一个时刻会把栈内存消耗完. 就会报栈内存溢出了

image.png

我们看到程序一共运行了16979次发生了栈溢出.


当栈空间设置的小一些呢?比如256k


1187916-20200707093109698-116793075.png

我们运行看效果

1187916-20200707093134731-990282592.png


当运行到2079次的时候, 发生了栈溢出


相关文章
|
9天前
|
运维 监控 Ubuntu
【运维】如何在Ubuntu中设置一个内存守护进程来确保内存不会溢出
通过设置内存守护进程,可以有效监控和管理系统内存使用情况,防止内存溢出带来的系统崩溃和服务中断。本文介绍了如何在Ubuntu中编写和配置内存守护脚本,并将其设置为systemd服务。通过这种方式,可以在内存使用超过设定阈值时自动采取措施,确保系统稳定运行。
27 4
|
21天前
|
存储 监控 算法
深入探索Java虚拟机(JVM)的内存管理机制
本文旨在为读者提供对Java虚拟机(JVM)内存管理机制的深入理解。通过详细解析JVM的内存结构、垃圾回收算法以及性能优化策略,本文不仅揭示了Java程序高效运行背后的原理,还为开发者提供了优化应用程序性能的实用技巧。不同于常规摘要仅概述文章大意,本文摘要将简要介绍JVM内存管理的关键点,为读者提供一个清晰的学习路线图。
|
1天前
|
存储 Java 程序员
【JVM】——JVM运行机制、类加载机制、内存划分
JVM运行机制,堆栈,程序计数器,元数据区,JVM加载机制,双亲委派模型
|
1月前
|
Java
JVM内存参数
-Xmx[]:堆空间最大内存 -Xms[]:堆空间最小内存,一般设置成跟堆空间最大内存一样的 -Xmn[]:新生代的最大内存 -xx[use 垃圾回收器名称]:指定垃圾回收器 -xss:设置单个线程栈大小 一般设堆空间为最大可用物理地址的百分之80
|
1月前
|
存储 监控 Java
合理设置JVM堆大小
合理设置JVM堆大小
39 4
|
1月前
|
Java
JVM运行时数据区(内存结构)
1)虚拟机栈:每次调用方法都会在虚拟机栈中产生一个栈帧,每个栈帧中都有方法的参数、局部变量、方法出口等信息,方法执行完毕后释放栈帧 (2)本地方法栈:为native修饰的本地方法提供的空间,在HotSpot中与虚拟机合二为一 (3)程序计数器:保存指令执行的地址,方便线程切回后能继续执行代码
22 3
|
1月前
|
存储 缓存 监控
Elasticsearch集群JVM调优堆外内存
Elasticsearch集群JVM调优堆外内存
49 1
|
1月前
|
缓存 Prometheus 监控
Elasticsearch集群JVM调优设置合适的堆内存大小
Elasticsearch集群JVM调优设置合适的堆内存大小
280 1
|
2月前
|
存储 安全 Java
jvm 锁的 膨胀过程?锁内存怎么变化的
【10月更文挑战第3天】在Java虚拟机(JVM)中,`synchronized`关键字用于实现同步,确保多个线程在访问共享资源时的一致性和线程安全。JVM对`synchronized`进行了优化,以适应不同的竞争场景,这种优化主要体现在锁的膨胀过程,即从偏向锁到轻量级锁,再到重量级锁的转变。下面我们将详细介绍这一过程以及锁在内存中的变化。
44 4
|
1月前
|
Arthas 监控 Java
JVM进阶调优系列(9)大厂面试官:内存溢出几种?能否现场演示一下?| 面试就那点事
本文介绍了JVM内存溢出(OOM)的四种类型:堆内存、栈内存、元数据区和直接内存溢出。每种类型通过示例代码演示了如何触发OOM,并分析了其原因。文章还提供了如何使用JVM命令工具(如jmap、jhat、GCeasy、Arthas等)分析和定位内存溢出问题的方法。最后,强调了合理设置JVM参数和及时回收内存的重要性。