Hi,运维,你懂Java吗-No.3:java系统的启动
Posted 龙叔运维
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Hi,运维,你懂Java吗-No.3:java系统的启动相关的知识,希望对你有一定的参考价值。
作为运维,你不一定要会写Java代码,但是一定要懂Java在生产跑起来之后的各种机制。
本文为《Hi,运维,你懂Java吗》系列文章 第三篇,敬请关注后续系列文章
欢迎关注 龙叔运维(公众号) 持续分享运维经验
前言
本篇对生产中运行java系统的启动方式以及启动参数以及相关配置进行介绍。
1、java应用的启动管理
一般公司运行java系统,不管是打包成镜像发布(镜像部署),还是在服务器上替换程序包发布(包部署),都会有一个启动脚本(如起名叫start.sh),启动脚本负责维护java的启停以及启动的各种配置参数维护。
启动脚本一般都会包含启动(start)、停止(stop)、重启(restart)三个基本功能。
本文提供一个简单的脚本作为例子:
#!/bin/bash
APP_NAME=test.jar
#提示输入参数
use_help()
echo "Usage: sh demo.sh [start|stop|restart|status]"
exit 1
#检查程序是否在运行
is_run()
pid=`ps -ef | grep $APP_NAME | grep -v grep | grep -v start.sh | awk 'print $2' `
#如果不存在返回1,存在返回0
if [ -z "$pid" ]; then
return 1
else
return 0
fi
#启动方法
start()
is_run
if [ $? -eq "0" ]; then
echo "$APP_NAME is already running. pid=$pid ."
else
java -Xms8192m -Xmx8192m -XX:NewSize=1024m -XX:MaxNewSize=1024m -XX:PermSize=1024m -XX:MaxPermSize=4096m -XX:+UseG1GC -jar $APP_NAME 1>> log.log 2>&1 &
fi
#停止方法
stop()
is_exist
if [ $? -eq "0" ]; then
echo "$pid"
kill -9 $pid
else
echo "$APP_NAME is not running"
fi
#输出运行状态
status()
is_exist
if [ $? -eq "0" ]; then
echo "$APP_NAME is running. Pid is $pid"
else
echo "$APP_NAME is not running."
fi
#重启
restart()
echo "stop the old process"
stop
echo "finish"
echo "start the new process"
start
echo "finish"
#根据输入参数,选择执行对应方法
case "$1" in
"start")
start
;;
"stop")
stop
;;
"status")
status
;;
"restart")
restart
;;
*)
usage
;;
esac
然而,这个脚本只是最基本的脚本,还可以有很多优化的地方,例如:
A、增加环境检查(java环境等等)
B、将用到的环境变量单独一个文件,然后在最开始的时候source这个文件,就可以在脚本中使用这些环境变量,维护更清晰
C、JAVA启动参数可以加的更多,不同类型的启动参数可以分别用变量去指定,最后再java命令中合并到一起,如:
JAVA_OPTS_JVM="-Xms1024m -Xmx2048m -Xss256K"
JAVA_OPTS_GC="-XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintTenuringDistribution -XX:+PrintHeapAtGC -Xloggc:logs/gc.log"
java $jvm_options $JAVA_OPTS_GC -jar -jar aaa.jar 1>> log.log 2>&1 &
2、java应用的启动参数
这里讲的就是java程序的启动命令java的一些在生产运行中可以用到的一些参数(所以这里并不是介绍所有参数哈)。
这里的一些参数所关联的如JVM,GC等知识点的更深入的介绍会在后续专门对应的章节介绍。
本文只讲JAVA 1.8版本之后(所以不存在持久代)
2.1、JVM内存相关
a、-Xms & -XX:InitialHeapSize
初始堆大小
-Xms1560M
-XX:InitialHeapSize=1560M
默认值为物理内存的1/64(<1GB),建议初始堆大小和最大堆大小保持一致,以避免每次垃圾回收完成后JVM重新分配内存。
默认空余堆内存小于40%(MinHeapFreeRatio参数可以调整)时,JVM就会增大堆直到-Xmx的最大限制.
至于设置多大比较合适,这个其实要根据程序情况来看,但是一般可以直接配置为物理内存的1/4。
b、-Xmx & -XX:MaxHeapSize
最大堆大小
-Xmx1560M
-XX:MaxHeapSize=1560M
默认值为物理内存的1/4(<1GB),建议初始堆大小和最大堆大小保持一致,以避免每次垃圾回收完成后JVM重新分配内存。
默认空余堆内存大于70%(MaxHeapFreeRatio参数可以调整)时,JVM会减少堆直到 -Xms的最小限制
至于设置多大比较合适,这个其实要根据程序情况来看,但是一般可以直接配置为物理内存的1/4。
c、-Xss & -XX:ThreadStackSize
规定了每个线程虚拟机栈及堆栈的大小
-Xss256K
-XX:ThreadStackSize=256K
一般情况下,256k是足够的,此配置将会影响此进程中并发线程数的大小。
d、-XX:NewSize
设置年轻代的初始大小
-XX:NewSize=1G
e、-XX:MaxNewSize
设置年轻代的最大大小
-XX:MaxNewSize=1G
f、-Xmn
同事设置年轻代的初始大小和最大大小
-Xmn1G
整个堆大小=年轻代大小 + 年老代大小 + 持久代大小。持久代一般固定大小为64m,所以增大年轻代后,将会减小年老代大小。此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8。
g、-XX:NewRatio
新生代(Eden + 2*S)与老年代(不包括永久区)的比值
注意:设置了-Xmn,则-XX:NewRatio将被忽略
-XX:NewRatio=4
例如-XX:NewRatio=4 表示新生代:老年代 = 1:4 即老年代占整个对的4/5;默认值=2。
一般情况下,不允许-XX:Newratio值小于1,即Old要比Yong大。
h、-XX:SurvivorRatio
2个Survivor区和Eden区的比值
-XX:SurvivorRatio=8
例如:-XX:SurvivorRatio=8 表示 两个Survivor区:Eden区=2:8 ,每个Survivor占 1/10 ;JVM默认=8
i、-XX:MetaspaceSize
元空间初始大小
-XX:MetaspaceSize=512M
建议和-XX:MaxMetaspaceSize设置成一样大
j、-XX:MaxMetaspaceSize
元空间最大大小
-XX:MaxMetaspaceSize=512M
建议和-XX:MaxMetaspaceSize设置成一样大
建议最好设置上,因为和java8之前的永久代不一样,元空间是基于操作系统内存的,可以一直扩展到操作系统的极限。
k、-XX:MaxTenuringThreshold
垃圾的最大年龄. 默认为15
XX:MaxTenuringThreshold=15
新生代的From 区和To区 会来回的复制和交换位置. 每交换一次,就会增加一次年龄. 如果某些对象在 的年龄达到改参数配置的值, 就会从新生代到老年代中去.
l、-XX:MaxDirectMemorySize
堆外内存大小,JVM之外分配的内存
XX:MaxDirectMemorySize=2G
要避免-Xmx + MaxDirectMemorySize 大于物理内存
这一块虚拟地址空间并不是分配在jvm堆上,而是分配在native堆上。yong gc不能回收这部分空间,只能通过Full gc顺带进行回收
m、-XX:+AlwaysPreTouch
在服务启动的时候真实的分配物理内存给JVM
可以加快代码运行效率,但是毕竟把分配物理内存的事提前放到JVM进程启动时做了,自然就会影响JVM进程的启动时间,导致启动时间变长。
顺便提一下,可以用 jmap -heap 【PID】 查看java 进程堆相关的配置,看是否按照自己的配置分配了内存
2.2、GC设置相关
a、-XX:+PrintGCDetails
打印 gc 详细信息日志
b、-XX:+PrintGC
打印 gc 简单信息日志
c、-XX:+PrintGCDateStamps
输出GC的时间戳(以日期的形式,如 2013-05-04T21:53:59.234+0800)
d、-XX:+PrintTenuringDistribution
JVM在每次新生代GC时,打印出幸存区中对象的年龄分布。
e、-XX:+PrintHeapAtGC
在进行GC的前后打印出堆的信息
f、-Xloggc
指定GC日志文件
-Xloggc:/var/logs/gc.log
f、-XX:+DisableExplicitGC
禁止显示调用GC,代码中手动调用System.gc()就不会生效。
而有些框架中因为是使用的堆外内存,必须手动调用System.gc()来释放。如果禁用掉就会导致堆外内存使用一直增长,造成内存泄露。
2.3、程序运行记录相关
a、-XX:+HeapDumpOnOutOfMemoryError
当JVM发生OOM时,自动生成DUMP文件
b、-XX:HeapDumpPath
自动生成的DUMP文件路径
-XX:HeapDumpPath=/var/logs/oom.hprof
c、-XX:ErrorFile
应用程序中的错误而发生崩溃时生成日志文件
默认这个文件创建在工作路径下的hs_err_pid.log中
-XX:ErrorFile=/var/logs/hs_err_%p.log"
d、-XX:+PrintFlagsInitial
印所有的默认参数设置
e、-XX:+PrintFlagsFinal
打印最终值,如果某个默认值被新值覆盖,显示新值
f、-XX:+PrintCommandLineFlags
打印那些被新值覆盖的项
本篇结束 欢迎关注该系列后续文章,更多更深入的一些参数会在对应知识点的时候一并讲解
以上是关于Hi,运维,你懂Java吗-No.3:java系统的启动的主要内容,如果未能解决你的问题,请参考以下文章