【JVM】JVM调优

1.OOM分析-堆内存

(1).jmap
jmap -dump:live,format=b,file=heap.bin pid

导出.bin文件使用MAT工具分析
MAT 下载
官网地址:https://www.eclipse.org/mat/
在这里插入图片描述

2.OOM分析-栈内存

问题:unable to create new native thread
1).查看当前运行线程数
$ cat /proc/loadavg
0.41 0.45 0.57 3/749 28174
# 输出结果第四列含有被“/”分割的两个数字。
# 第一个数字表示当前可执行的内核调度实体(进程、线程)数量,通常小于或等于Cpu的数量。
# 第二个数字表示当前存在的内核调度实体,如上例当前并行存在749个线程
 
$ ps -elf | wc -l
220
# 当前进程数220(实际上减一行应为219),不包含进程创建的线程
 
$ ps -elfT | wc -l
385
# 当前线程数385(实际上减一行应为384),包含所有进程及线程
 
$ ps -p PID -lfT | wc -l
# 指定PID查看线程数,该线程数应该与Jstack生成的Thread Dump上的线程数一致
 
$ jstack -l PID | grep tid | wc -l
# jstack位于Jdk安装目录bin下,用于输出线程快照
2).ulimit 检查OS是否允许用户申请足够多的进程(含线程)
$ ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 515005
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 4096
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 10240
cpu time               (seconds, -t) unlimited
max user processes              (-u) 1024
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited
# 通过ulimit -u,可见用户默认的最大进程(含线程)数是1024
# 通过ulimit -s,可见进程默认的最大栈大小是10M
 

3).设置用户线程数
  • 最大线程数计算方式
n = total_memory/128k;
  • 临时设置用户默认的最大进程(重启失效)
$ ulimit -u 32000
  • 永久设置用户默认的最大进程(重启生效)
1.切换到root

2.vi /etc/security/limits.conf ,查看是否有限制,若无限制不需要处理

3.vi /etc/security/limits.d/20-nproc.conf ,修改用户线程限制
*          soft    nproc     4096 (所有用户)
root       soft    nproc     60000 (root用户)

4).系统级最大进程ID
$ sysctl -a | grep kernel.pid_max
kernel.pid_max = 32768
# 输出结果表示当前系统允许的最大进程数为32768
 
$ cat /proc/sys/kernel/pid_max
# 命令功用与上述同样
 
$ echo 200000 > /proc/sys/kernel/pid_max
# 修改系统级最大进程数为200000,可通过sysctl查看修改
5).系统级最大线程数
# /proc/sys/kernel/threads-max 限制了系统级最大线程数
$ echo 120000 > /proc/sys/kernel/threads-max
# 修改系统级最大线程数为120000,可通过sysctl查看修改
# Linux没有每个进程单独的最大线程数限制
6).Linux对最大线程数的硬控制

number of threads = total virtual memory / (stack size10241024)
从上可知,最大线程数的增加可以通过增加虚拟内存或减少线程栈大小两种手段。
但是,减少线程栈大小可能会导致栈溢出的异常。

$ ulimit -v newValue
# 更改进程默认的虚拟内存大小
 
$ ulimit -s newValue
# 更改进程默认的栈大小
7).max_map_count 间接影响线程数量

max_map_count文件包含限制一个进程可以拥有的VMA(虚拟内存区域)的数量。默认值是65536。
虚拟内存区域是一个连续的虚拟地址空间区域。在进程的生命周期中,每当程序尝试在内存中映射文件,链接到共享内存段,或者分配堆空间的时候,这些区域将被创建。
调优这个值将限制进程可拥有VMA的数量。限制一个进程拥有VMA的总数可能导致应用程序出错,因为当进程达到了VMA上限但又只能释放少量的内存给其他的内核进程使用时,操作系统会抛出内存不足的错误。
如果你的操作系统在NORMAL区域仅占用少量的内存,那么调低这个值可以帮助释放内存给内核用。
因值过低抛错在JVM中可能会呈现Java.lang.OutOfMemoryError: Map failed。详情参见max_map_count超出导致的OOM

$ echo 'vm.max_map_count=655360' >> /etc/sysctl.conf
# rocketmq系统参数配置了默认值的10倍
 
$ echo 600000 > /proc/sys/vm/max_map_count
# 更改VMA映射数量为600000,可通过sysctl查看修改
8)参数之间的关联

线程本质上是进程,显著区别在于线程运行在共享内存空间,而进程运行在独立内存空间
/proc/sys/kernel/pid_max 决定的进程数是运行于独立内存空间的进程
/proc/sys/kernel/threads-max 决定的线程数是运行于共享内存空间的线程
ulimit -u 指的是一个用户在同一时间最多能拥有的总进程(含线程)

9).减少JVM的线程栈大小
  • 一般不这么做,线程栈过小可能抛出java.lang.StackOverflowError异常,常见于旧版Maven编译失败。
  • 减少每个线程的栈大小有助于生成更多的线程。
  • 先检查当前JVM默认的线程栈大小
    bash $ java -XX:+PrintFlagsFinal -version | grep ThreadStackSize intx ThreadStackSize = 1024 # 输出结果表示JVM默认线程栈大小为1M
  • 通过为JVM添加"-Xss",减少线程栈大小。
    bash JAVA_OPTS=“-Xms128m -Xmx1303m -Xss256k” # 上述JVM参数表示JVM最小内存大小为128M,最大内存大小为1303M,线程栈大小为256K

2.JVM三大性能调优参数Xms,Xmx,Xss

-Xss:规定了每个线程虚拟机栈及堆栈的大小,一般情况下,256k是足够的,此配置将会影响此进程中并发线程数的大小。

-Xms:表示初始化JAVA堆的大小及该进程刚创建出来的时候,他的专属JAVA堆的大小,一旦对象容量超过了JAVA堆的初始容量,JAVA堆将会自动扩容到-Xmx大小。

-Xmx:表示java堆可以扩展到的最大值,在很多情况下,通常将-Xms和-Xmx设置成一样的,因为当堆不够用而发生扩容时,会发生内存抖动影响程序运行时的稳定性。

3.调优工具-arthas

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值