主頁 > 後端開發 > JAVA專案啟動腳本撰寫的一些筆記整理

JAVA專案啟動腳本撰寫的一些筆記整理

2021-08-21 08:01:04 後端開發

寫在前面


  • 公司專案里看到,之前的專案都是在物理機部署的,而且大都是Server,沒搞過,這里整齊學習,
  • 博文分為兩部分: 專案啟動腳本總結,java常用啟動引數,,啟動引數部分參考

流年似水,有些事情一下子過去了,有的事情很久也過不去,
流年似水,過去的事過去了,未過去的事也不能叫我驚訝,
但是歲月如流,一切都已發生過,發生過的事再也沒有改變的余地,
雖然歲月如流,什么都會過去,但總有些東西發生了就不能抹煞,
似水流年是一個人所有的一切,只有這個東西,才真正歸你所有,其余的一切,都是片刻的歡娛和不幸,轉眼間就已跑到那似水流年里去了, --------王小波


小專案啟動腳本

定時任務型別的小專案

#!/bin/sh 
echo $path
mainclasspath="com.liruilong.uag.job.StartJob"
classpath="/demo/com_AAA/target/classes"
pathtmp='' 
for jarpath in `ls /demo/com_AAA/lib/*.jar` 
do 
classpath=$classpath:$jarpath 
done
classpath=$classpath:/demo/com_AAA/demo.jar
echo $classpath
echo $mainclasspath
 nohup java -Xmx1024m -classpath $classpath $mainclasspath > /dev/null  &

專案分開寫 start.sh

# 獲取腳本名字
PRG=$0
## 
while [ -h "$PRG" ] ; do
  ls=`ls -ld "$PRG"`
  link=`expr "$ls" : '.*-> \(.*\)$'`
  if expr "$link" : '.*/.*' > /dev/null; then
    PRG="$link"
  else
    PRG="`dirname $PRG`/$link"
  fi
done
 PRGDIR=`dirname ${PRG}`
MY_HOME=`cd .; pwd`
 OLDCLASSPATH=${CLASSPATH}
CLASSPATH=.
 for i in ./lib/*.jar ; do
  CLASSPATH=${CLASSPATH}:$i
done
 for i in ./jettyLib/*.jar ; do
  CLASSPATH=${CLASSPATH}:$i
done
 echo ${CLASSPATH}
 if [ -z "$JAVA_HOME" ] ; then
  JAVA=`which java`
  if [ -z "$JAVA" ] ; then
    echo "Cannot find JAVA. Please set your PATH."
    exit 1
  fi
  JAVA_BINDIR=`dirname $JAVA`
  JAVA_HOME=$JAVA_BINDIR/..
fi
if [ "$JAVACMD" = "" ] ; then
   JAVACMD=$JAVA_HOME/bin/java
   RMICMD=$JAVA_HOME/bin/rmiregistry
fi
if [ -f ${JAVA_HOME}/lib/tools.jar ] ; then
   CLASSPATH=${CLASSPATH}:${JAVA_HOME}/lib/tools.jar
fi
 if [ "$OLDCLASSPATH" != "" ]; then
  CLASSPATH=${CLASSPATH}:${OLDCLASSPATH}
fi
#start npi_app
MY_HOME=`pwd`/..
 instanceCount=`ps -ef|tr -s ' '|sort -n|grep PGM_ID=AZONE_NPI |awk '{print $2}'|wc -l`
if [ $instanceCount -gt 1 ]
then
  echo 'AZONE_NPI  already running !'
else
  echo 'AZONE_NPI  is starting ...'
 MEM_ARGS="-verbosegc  -Xms2048m  -Xmx2048m -Xloggc:./log/gc.log"
$JAVACMD -Dserver.ip=10.128.92.66 -DPGM_ID=AZONE_NPI -DAPP_NAME=AZONE_NPI  ${MEM_ARGS} -Dfile.encoding=GBK -Dconfigfile="./config/isap.xml" -cp .:./webRoot/WEB-INF/classes:log4j.properties:${CLASSPATH} com...xx.xx.xx.DispatcherCommand 4G_GROUP_NET >/dev/null & 
 fi

專案分開寫 stop.sh

pids=`ps -ef|grep java|grep AZONE_NPI |awk '{printf $2" "}'`
echo "will kill process ids:$pids"
kill -9 $pids
echo 'kill successed'

springboot 專案啟動腳本 ,沒有使用-jar 方式,

run.sh

#!/bin/sh
# ======JAVA 環境變數校驗========
# 宣告變數
ACTIVE_PROFILE=db,mq,redis,prod
TASK_GROUP_ID=1 
# 如果 ${JAVA_HOME}/bin/java 不存在,那么把 ${JAVA_HOME} 的值給 JAVA_HOME
[ ! -e "${JAVA_HOME}/bin/java" ] && JAVA_HOME=${JAVA_HOME}
# 如果 $JAVA_HOME/bin/java  還不存在,那么/usr/local/jdk1.8.0_144 給 JAVA_HOME
[ ! -e "$JAVA_HOME/bin/java" ] && JAVA_HOME=/usr/local/jdk1.8.0_144
[ ! -e "$JAVA_HOME/bin/java" ] && JAVA_HOME=/usr/local/java/jdk
[ ! -e "$JAVA_HOME/bin/java" ] && JAVA_HOME=/usr/local/jdk
# 如果 $JAVA_HOME 為空
if [ -z "$JAVA_HOME" ] ; then
  JAVA=${JAVA_HOME}/bin/java
# 如果當前用戶有可執行下面命令的權限
elif [ -x "$(command -v java)" ] ; then
# 把java命令的解釋器地址給 JAVA變數 
  JAVA=`command -v java`
else
#  提示錯誤,并重定向到標準錯誤
  echo 'Error: java is not installed.' >&2
#  指定退出狀態碼 1  一般性未知錯誤,
  exit 1
fi
# set ACTIVE_PROFILE default val, if ACTIVE_PROFILE is empty
#  active_profile 沒有值,警告賦值,
if [ ! $ACTIVE_PROFILE ]; then
    echo 'Warn: spring active profile[ACTIVE_PROFILE] not set in env, use default profile: dev'
    ACTIVE_PROFILE='dev'
fi
# switch to parent dir of shell script.
# cd到當前腳本目錄下的上一層目錄
cd $(dirname $0)/..
# 把當前目錄給BASE_DIR
export BASE_DIR=$(pwd)
export CLASSPATH=.:${BASE_DIR}/config:${CLASSPATH}
################# app options ###############
APP_ID="demo"
MAIN_CLASS="com.liruilong.demo.DemoApplication"
################# user options ###############
USER_OPT="-Dlogging.config=${DATA_FILE_DIR:-.}/logback.xml -Dspring.profiles.active=${ACTIVE_PROFILE} -Dspring.config.location=classpath:../config/ -Drocketmq.client.log.loadconfig=false -Dfile.encoding=UTF-8"
################# java options ###############
JAVA_OPT="-server -Xmx1024m  -Xms512m -Xmn512m"
# set JAVA_OPT_PARM default val, if JAVA_OPT_PARM is empty
if [ $JAVA_OPT_PARM ]; then
    echo 'Warn: use the new [JAVA_OPT_PARM] by set in env'
    JAVA_OPT="-server ${JAVA_OPT_PARM}"
fi
# jetty suggestion
JAVA_OPT="${JAVA_OPT} -verbose:gc"
JAVA_OPT="${JAVA_OPT} -Xloggc:./logs/gc.log -XX:-UseGCOverheadLimit -XX:+HeapDumpOnOutOfMemoryError -XX:+PrintGCDetails -XX:+PrintGCDateStamps"
# r&d suggestion
JAVA_OPT="${JAVA_OPT} -XX:HeapDumpPath=./logs/dumpfile.hprof"
JAVA_OPT="${JAVA_OPT} -XX:+HeapDumpOnOutOfMemoryError"
# other like rocketmq
#JAVA_OPT="${JAVA_OPT} -XX:+AlwaysPreTouch"
JAVA_OPT="${JAVA_OPT} -XX:MaxDirectMemorySize=1g"
JAVA_OPT="${JAVA_OPT} -XX:-UseLargePages -XX:-UseBiasedLocking"
JAVA_OPT="${JAVA_OPT} -Djava.ext.dirs=${JAVA_HOME}/jre/lib/ext:${BASE_DIR}/lib"
JAVA_OPT="${JAVA_OPT} -cp ${CLASSPATH}"
################# java options ###############
################# pid  ###############
#ONE JAR MORE INSTANCE
PID=$(ps -ef|grep "\\-DappId=${APP_ID}" | grep -v grep|awk '{print $2}')
#ONE JAR ONE INSTANCE
#PID=$(fuser ${JAR_FILE_NAME} 2>/dev/null | xargs echo)
################# pid  ###############
 start(){
    if ! kill -0 ${PID} 2>/dev/null ;then
        echo "${APP_ID} is starting!"
        ${JAVA} ${JAVA_OPT} ${USER_OPT} -DappId=${APP_ID}  -DTASK_GROUP_ID=${TASK_GROUP_ID} ${MAIN_CLASS} >/dev/null 2>&1 &
    else
        echo "Failed to start '${APP_ID}',because it is running (pid:${PID})."
    fi 
}
 stop(){
    if  kill -0 ${PID} 2>/dev/null ;then
        kill ${PID}
        echo "killing ${APP_ID}"
    else
        echo "Failed to stop '${APP_ID}',It is not running."
    fi
}
 status(){
    if kill -0 ${PID} 2>/dev/null ;then
        echo "${APP_ID} (pid:${PID}) is running."
    else
        echo "${APP_ID} is not running."
    fi 
}
 case $1 in 
    start)
        start;;
    stop)
        stop;;
    status)
        status;;
    *)
        echo "Usage: $0 start|stop|status"
esac
## 防止容器啟動后自動退出,導致應用無法啟動;
tail -f /dev/null

springboot 專案 容器類啟動腳本,使用 -jar方式

Dockerfile

#基礎鏡像docker build -t uncp-npi:v1.0.0 .
FROM centos7-java-pure:openjdk1.8.151
#維護人員
MAINTAINER liruilongs.github.io
#通過 ADD 指令復制代碼到目錄
ADD ./target/*.tar.gz /root/
#通過 RUN 指令創建日志目錄
RUN mkdir -p /root/logs/ \
&& touch  /root/nohup.out \
&& chmod u+x /root/bin/run.sh
#通過 VOLUME 指令創建的掛載點
#VOLUME ["/root/logs"]
#暴露埠
EXPOSE 8430
#啟動腳本
ENTRYPOINT ["sh","/root/bin/run.sh"]
#切換作業目錄
WORKDIR /root
#啟動引數,會跟在 ENTRYPOINT 后面,
CMD ["start"]

run.sh

#!/bin/sh
# shell directory
# cd到當前腳本下
SH_DIR=$(cd "$(dirname "$0")"; pwd)
cd ${SH_DIR}
# 判斷java環境是否存在,
[ ! -e "${JAVA_HOME}/bin/java" ]
# 宣告全域變數
export JAVA_HOME
# 宣告java相關命令的解釋器
JAVA="${JAVA_HOME}/bin/java"
#JAVA="/CloudResetPwdUpdateAgent/depend/jre1.8.0_131/bin/java"
#JAVA="/usr/lib/jvm/jre-1.8.0-openjdk.x86_64/bin/java"
#JAVA="/usr/lib/jvm/openjdk-8u40-b25-linux-x64-10_feb_2015/java-se-8u40-ri/bin/java"
#JAVA="/usr/lib/jvm/java-se-8u40-ri/bin/java"
################# user options ###############
## 應用名稱,全域環境變數獲取
APP_ID="${APP_NAME}"
## 應用編碼:appCode引數為專案啟動執行緒類
APP_CODE="${APP_CODE}"
# 應用對應的jar包
JAR_FILE_NAME="Demo-2.0.0-SNAPSHOT.jar"
# 應用對應的日志檔案
COMMON_LOG_FILE="./logs/demo-inf.log"
#appCode引數為專案啟動執行緒類
#USER_OPT="-DappCode=INF_NATIVE,TEST -Dspring.config.location=classpath:./ -Dfile.encoding=UTF-8"
# 應用組態檔,檔案編碼
USER_OPT="-DappCode=${APP_CODE} -Dspring.config.location=classpath:./ -Dfile.encoding=UTF-8"
#DEBUG_ARGS="-Xdebug -agentlib:jdwp=transport=dt_socket,address=9999,server=y,suspend=n"
################# user options ###############
################# java options ###############
JAVA_OPT="-server -Xmx256m  -Xms256m -Djasypt.encryptor.password=OSS3"
JAVA_OPT="${JAVA_OPT} -Xmn128m"
#JAVA_OPT="${JAVA_OPT} -Xbootclasspath/a:/home/iom_cloud_mysql/iom-cloud-inf-service/"
# jetty suggestion
JAVA_OPT="${JAVA_OPT} -verbose:gc"
#JAVA_OPT="${JAVA_OPT} -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -XX:+PrintGCDetails"
JAVA_OPT="${JAVA_OPT} -Xloggc:./logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=20m"
JAVA_OPT="${JAVA_OPT} -XX:+PrintTenuringDistribution"
JAVA_OPT="${JAVA_OPT} -XX:+PrintCommandLineFlags"
JAVA_OPT="${JAVA_OPT} -XX:+DisableExplicitGC"
JAVA_OPT="${JAVA_OPT} -XX:+UseConcMarkSweepGC"
JAVA_OPT="${JAVA_OPT} -XX:CMSInitiatingOccupancyFraction=80"
# r&d suggestion
JAVA_OPT="${JAVA_OPT} -XX:HeapDumpPath=./logs/dumpfile.hprof"
JAVA_OPT="${JAVA_OPT} -XX:+HeapDumpOnOutOfMemoryError"
# other like rocketmq
JAVA_OPT="${JAVA_OPT} -XX:-OmitStackTraceInFastThrow"
#JAVA_OPT="${JAVA_OPT} -XX:+AlwaysPreTouch"
JAVA_OPT="${JAVA_OPT} -XX:MaxDirectMemorySize=15g"
JAVA_OPT="${JAVA_OPT} -XX:-UseLargePages -XX:-UseBiasedLocking"
JAVA_OPT="${JAVA_OPT} ${EXTRAOPT}"
#JAVA_OPT="${JAVA_OPT}  -Djava.ext.dirs=.:lib:${JAVA_HOME}/jre/lib/ext"
#JAVA_OPT="${JAVA_OPT}  -Xbootclasspath/a:/home/iom_cloud_mysql/iom-cloud-inf-service/Demo-2.0.0-SNAPSHOT.jar"
#JAVA_OPT="${JAVA_OPT} -cp .:./lib:/home/iom_cloud_mysql/demo"
#echo ${JAVA_OPT}
# r&d
################# java options ###############
################# pid  ###############
#ONE JAR MORE INSTANCE 一個 jar 多實體
PID=$(ps -ef|grep "\\-DappId=${APP_ID}" | grep -v grep|awk '{print $2}')
#ONE JAR ONE INSTANCE  一個jar 單實體
#PID=$(fuser ${JAR_FILE_NAME} 2>/dev/null | xargs echo)
################# pid  ###############
## 啟動方法
## `kill -0 pid` 不發送任何信號,但是系統會進行錯誤檢查,所以經常用來檢查一個行程是否存在,存在回傳0 false ;不存在回傳1   true
start(){
    ## 判斷當前 行程是否存在
    if ! kill -0 ${PID} 2>/dev/null ;then
        ## 輸出 行程開始啟動及對應的檔案
        echo "${APP_ID} is starting! File is ${JAR_FILE_NAME}"
        ## 非控制臺下后臺啟動 將日志1&2輸出到指定位置
        nohup ${JAVA} ${JAVA_OPT} ${USER_OPT} -DappId=${APP_ID} -jar ${JAR_FILE_NAME}  >>  ${COMMON_LOG_FILE}  2>&1 &
    else
        echo "Failed to start '${APP_ID}',because it is running (pid:${PID})."
    fi 
}
## 停止方法
stop(){
    if  kill -0 ${PID} 2>/dev/null ;then
    # 正常結束行程,15是 kill 命令的默認信號,
        kill ${PID}
        echo "killing ${APP_ID}"
    else
        echo "Failed to stop '${APP_ID}',It is not running."
    fi
}
 status(){
    if kill -0 ${PID} 2>/dev/null ;then
        echo "${APP_ID} (pid:${PID}) is running."
    else
        echo "${APP_ID} is not running."
    fi 
}
 case $1 in 
    start)
        start;;
    stop)
        stop;;
    status)
        status;;
    *)
        echo "Usage: $0 start|stop|status"
esac
## 防止容器啟動后自動退出,導致應用無法啟動;
tail -f /dev/null
kill pid 和 kill -9 pid 的區別

在這里插入圖片描述

信號編號信號名含義
0EXIT程式退出時收到該資訊,
1HUP掛掉電話線或終端連接的掛起信號,這個信號也會造成某些行程在沒有終止的情況下重新初始化,
2INT表示結束行程,但并不是強制性的,常用的 “Ctrl+C” 組合鍵發出就是一個 kill -2 的信號,
3QUIT退出,
9KILL殺死行程,即強制結束行程,
11SEGV段錯誤,
15TERM正常結束行程,是 kill 命令的默認信號,
常用的kill 命令及其信號解釋
[kino@hadoop102 bin]$ jps
20097 Jps
19836 JobHistoryServer
19773 NodeManager
[kino@hadoop102 bin]$ kill 19836
# 殺死 PID 為 19836 的 JobHistoryServer 行程, 默認信號是 15, 正常停止
# 如果默認信號 15 不能殺死該行程, 則可以嘗試使用 信號9, 強制殺死行程
[kino@hadoop102 bin]$ jps
20115 Jps
19773 NodeManager
# PID 為 19836 的 JobHistoryServer 行程 已被殺死
使用“-1”信號,讓行程重啟,
[kino@hadoop102 bin]$ kill -1 19773 
使用 “-9” 強制殺死行程
[kino@hadoop102 bin]$ kill -9 19773 
我們在使用 kill 命令的時候, 可以傳入 信號編號,也可以傳入信號名
kill PID 等價于 kill -15 PID 等價于 kill -s TERM	
 kill -9 PID 等價與 kill -s SIGKILL PID
 kill -1 PID 等價于 kill -s SIGHUP PID

java 啟動引數整理

java啟動引數共分為三類

  • 標準引數(-),所有的JVM實作都必須實作這些引數的功能,而且向后兼容
  • 非標準引數(-X),默認jvm實作這些引數的功能,但是并不保證所有jvm實作都滿足,且不保證向后兼容;
  • Stable引數(-XX),此類引數各個jvm實作會有所不同,將來可能會隨時取消,需要慎重使用;

一.標準引數

在這里插入圖片描述

引數名稱描述
-client設定jvm使用client模式,特點是啟動速度比較快,但運行時性能記憶體管理效率不高,通常用于客戶端應用程式或者PC應用開發和除錯
-server設定jvm使server模式,特點是啟動速度比較慢,但運行時性能和記憶體管理效率很高,適用于生產環境,在具有64位能力的jdk環境下將默認啟用該模式,而忽略-client引數
-agentlib:libname[=options]用于裝載本地lib包; 其中 libname為本地代理庫檔案名,默認搜索路徑為環境變數PATH中的路徑,options為傳給本地庫啟動時的引數,多個引數之間用逗號分隔,在 Windows平臺上jvm搜索本地庫名為libname.dll的檔案,在linux上jvm搜索本地庫名為libname.so的檔案,搜索路徑環境變數在不同系統上有所不同,比如Solaries上就默認搜索LD_LIBRARY_PATH, 比如:
-agentlib:hprof用來獲取jvm的運行情況,包括CPU、記憶體、執行緒等的運行資料,并可輸出到指定檔案中;windows中搜索路徑為JRE_HOME/bin/hprof.dll,
-agentpath:pathname[=options]按全路徑裝載本地庫,不再搜索PATH中的路徑;其他功能和agentlib相同;更多的資訊待續,在后續的JVMTI部分會詳述,
-classpath classpath -cp classpath
告知jvm搜索目錄名、jar檔案名、zip檔案名,之間用分號;分隔;使用 -classpathjvm將不再使用 CLASSPATH中的類搜索路徑,如果 -classpathCLASSPATH都沒有設定,則jvm使用 當前路徑(.)作為 類搜索路徑jvm搜索類的方式和順序為: BootstrapExtensionUser
-Dproperty=value設定系統屬性名/值對,運行在此jvm之上的應用程式可用System.getProperty("property")得到value的值, 如果value中有空格,則需要用雙引號將該值括起來,如-Dname="space string", 該引數通常用于設定系統級全域變數值,如組態檔路徑,以便該屬性在程式中任何地方都可訪問,
-enableassertions[:<package name>"..." | :<classname> ] -ea[:<package name>"..." | :<class name> ]上述引數就用來設定jvm是否啟動斷言機制(從JDK 1.4開始支持),預設時jvm關閉斷言機制, 用-ea可打開斷言機制,不加和classname時運行所有包和類中的斷言,如果希望只運行某些包或類中的斷言,可將包名或類名加到-ea之后,例如要啟動包com.wombat.fruitbat中的斷言,可用命令java -ea:com.wombat.fruitbat…,
-disableassertions[:<package name>"..." | :<class ; ] -da[:<package name>"..." | :<class name> ]用來設定jvm關閉斷言處理,packagename和classname的使用方法和-ea相同,jvm默認就是關閉狀態,該引數一般用于相同package內某些class不需要斷言的場景,比如com.wombat.fruitbat需要斷言,但是com.wombat.fruitbat.Brickbat該類不需要,則可以如下運行: java -ea:com.wombat.fruitbat…-da:com.wombat.fruitbat.Brickbat , -enablesystemassertions -esa 激活系統類的斷言-disablesystemassertions -dsa 關閉系統類的斷言
-jar指定以jar包的形式執行一個應用程式, 要這樣執行一個應用程式,必須讓jar包的manifest檔案中宣告初始加載的Main-class,當然那Main-class必須有public static void main(String[] args)方法,
-javaagent:jarpath[=options]指定jvm啟動時裝入java語言設備代理Jarpath 檔案中的mainfest檔案必須有Agent-Class屬性,代理類也必須實作公共的靜態public static void premain(String agentArgs, Instrumentation inst)方法(和main方法類似),當jvm初始化時,將按代理類的說明順序呼叫premain方法;具體參見 java.lang.instrument軟體包的描述,
-verbose -verbose:class輸出jvm載入類的相關資訊,當jvm報告說找不到類或者類沖突時可此進行診斷,
-verbose:gc輸出每次GC的相關情況,
-verbose:jni輸出native方法呼叫的相關情況,一般用于診斷jni呼叫錯誤資訊,
-version輸出java的版本資訊,比如jdk版本、vendor、model,
-version:release指定class或者jar運行時需要的jdk版本資訊;若指定版本未找到,則以能找到的系統默認jdk版本執行;一般情況下,對于jar檔案,可以在manifest檔案中指定需要的版本資訊,而不是在命令列, release中可以指定單個版本,也可以指定一個串列,中間用空格隔開,且支持復雜組合,比如: -version:"1.5.0_04 1.5*&1.5.1_02+" 指定class或者jar需要jdk版本為1.5.0_04或者是1.5系列中比1.5.1_02更高的所有版本,
-showversion輸出java版本資訊(與-version相同)之后,繼續輸出java的標準引數串列及其描述,
-? -help輸出java標準引數串列及其描述
Bootstrap中的路徑是jvm自帶的jar或zip檔案,jvm首先搜索這些包檔案,用System.getProperty("sun.boot.class.path")可得到搜索路徑,
Extension是位于JRE_HOME/lib/ext目錄下的jar檔案,jvm在搜索完Bootstrap后就搜索該目錄下的jar檔案,用System.getProperty("java.ext.dirs")可得到搜索路徑,
User搜索順序為當前路徑.、CLASSPATH、-classpath,jvm最后搜索這些目錄,用`System.getProperty(“java.class.path”)可得到搜索路徑,

二.非標準引數

-X 輸出非標準的引數串列及其描述,

以上的這些引數我們經常會在很多情況下用到多個的組合,比如我們在用JProfiler進行跟蹤監控時,需要在被監控java啟動引數中加上如下配置:-agentlib:jprofilerti=port=8849 -Xbootclasspath/a:/usr/local/jprofiler5/bin/agent.jar其中就用到兩個-agentlib-X引數,bootclasspath引數的詳細資訊將會在非標準引數中詳細說明,

在這里插入圖片描述

引數名稱描述
-Xmixed混合模式執行 (默認)
-Xint設定jvm以解釋模式運行,所有的位元組碼將被直接執行,而不會編譯成本地碼,
-Xbatch關閉后臺代碼編譯,強制在前臺編譯,編譯完成之后才能進行代碼執行; 默認情況下,jvm在后臺進行編譯,若沒有編譯完成,則前臺運行代碼時以解釋模式運行,
-Xbootclasspath:bootclasspath讓jvm從指定路徑(可以是分號分隔的目錄、jar、或者zip)中加載bootclass,用來替換jdk的rt.jar;若非必要,一般不會用到;
-Xbootclasspath/a:path將指定路徑的所有檔案追加到默認bootstrap路徑中;
-Xbootclasspath/p:path讓jvm優先于bootstrap默認路徑加載指定路徑的所有檔案;
-Xcheck:jni對JNI函式進行附加check;此時jvm將校驗傳遞給JNI函式引數的合法性,在本地代碼中遇到非法資料時,jmv將報一個致命錯誤而終止;使用該引數后將造成性能下降,請慎用,
-Xfuture讓jvm對類檔案執行嚴格的格式檢查(默認jvm不進行嚴格格式檢查),以符合類檔案格式規范,推薦開發人員使用該引數,
-Xnoclassgc關閉針對class的gc功能;因為其阻止記憶體回收,所以可能會導致OutOfMemoryError錯誤,慎用;
-Xincgc 開啟增量gc(默認為關閉);這有助于減少長時間GC時應用程式出現的停頓;但由于可能和應用程式并發執行,所以會降低CPU對應用的處理能力,
-Xdiag顯示附加診斷訊息
-Xloggc:file與-verbose:gc功能類似,只是將每次GC事件的相關情況記錄到一個檔案中,檔案的位置最好在本地,以避免網路的潛在問題, 若與verbose命令同時出現在命令列中,則以-Xloggc為準,
-Xmsn指定jvm堆的初始大小,默認為物理記憶體的1/64,最小為1M;可以指定單位,比如k、m,若不指定,則默認為位元組,
-Xmxn指定jvm堆的最大值,默認為物理記憶體的1/4或者1G,最小為2M;單位與-Xms一致,
-Xrs減少jvm對作業系統信號(signals)的使用,該引數從1.3.1開始有效; 從jdk1.3.0開始,jvm允許程式在關閉之前還可以執行一些代碼(比如關閉資料庫的連接池),即使jvm被突然終止; jvm 關閉工具通過監控控制臺的相關事件而滿足以上的功能;更確切的說,通知在關閉工具執行之前,先注冊控制臺的控制handler,然后對 CTRL_C_EVENT, CTRL_CLOSE_EVENT,CTRL_LOGOFF_EVENT, and CTRL_SHUTDOWN_EVENT這幾類事件直接回傳true, 但如果jvm以服務的形式在后臺運行(比如servlet引擎),他能接收CTRL_LOGOFF_EVENT事件,但此時并不需要初始化關閉程式;為了避免類似沖突的再次出現,從jdk1.3.1開始提供-Xrs引數;當此引數被設定之后,jvm將不接收控制臺的控制handler,也就是說他不監控和處理CTRL_C_EVENT, CTRL_CLOSE_EVENT, CTRL_LOGOFF_EVENT, orCTRL_SHUTDOWN_EVENT事件,
-Xssn設定單個執行緒堆疊的大小,一般默認為512k,
-Xdiag顯示附加診斷訊息
-Xbatch禁用后臺編譯
-Xprof輸出 cpu 組態檔資料,跟蹤正運行的程式,并將跟蹤資料在標準輸出輸出;適合于開發環境除錯
-Xshare:off不嘗試使用共享類資料
-Xshare:auto在可能的情況下使用共享類資料 (默認)
-Xshare:on要求使用共享類資料, 否則將失敗,
-XshowSettings顯示所有設定并繼續
-XshowSettings:all顯示所有設定并繼續
-XshowSettings:vm顯示所有與 vm 相關的設定并繼續
-XshowSettings:properties顯示所有屬性設定并繼續
-XshowSettings:locale顯示所有與區域設定相關的設定并繼續

上面這些引數中,比如-Xmsn、-Xmxn……都是我們性能優化中很重要的引數; -Xprof、-Xloggc:file等都是在沒有專業跟蹤工具情況下排錯的好手;

三.非Stable(穩定)引數

-XX作為前綴的引數串列在jvm中可能是不健壯的,SUN也不推薦使用,后續可能會在沒有通知的情況下就直接取消了;但是由于這些引數中的確有很多是對我們很有用的,比如我們經常會見到的-XX:PermSize、-XX:MaxPermSize等等; 下面我們將就Java HotSpot VM-XX:的可配置引數串列進行描述; 這些引數可以被松散聚合成三類`:

  • 行為引數(Behavioral Options) :用于改變jvm的一些基礎行為;
  • 性能調優(Performance Tuning) :用于jvm的性能調優;
  • 除錯引數(Debugging Options) :一般用于打開跟蹤、列印、輸出等jvm引數,用于顯示jvm更加詳細的資訊;

由于sun官方檔案中對各引數的描述也都非常少(大多只有一句話),而且大多涉及OS層面的東西,很難描述清楚,所以以下是挑選了一些我們開發中可能會用得比較多的配置項,

行為引數:

引數及其默認值描述
-XX:-DisableExplicitGC禁止呼叫System.gc();但jvm的gc仍然有效
-XX:+MaxFDLimit最大化檔案描述符的數量限
-XX:+ScavengeBeforeFullG新生代GC優先于Full GC執
-XX:+UseGCOverheadLimi在拋出OOM之前限制jvm耗費在GC上的時間比
-XX:-UseConcMarkSweepG對老生代采用并發標記交換演算法進行GC
-XX:-UseParallelG啟用并行GC
-XX:-UseParallelOldG對Full GC啟用并行,當-XX:-UseParallelGC啟用時該項自動啟
-XX:-UseSerialG啟用串行GC
-XX:+UseThreadPrioritie啟用本地執行緒優先

上面表格中黑體的三個引數代表著jvm中GC執行的三種方式,即串行、并行、并發

  • 串行(SerialGC)是jvm的默認GC方式,一般適用于小型應用和單處理器,演算法比較簡單,GC效率也較高,但可能會給應用帶來停頓;
  • 并行(ParallelGC)是指GC運行時,對應用程式運行沒有影響,GC和app兩者的執行緒在并發執行,這樣可以最大限度不影響app的運行;
  • 并發(ConcMarkSweepGC)是指多個執行緒并發執行GC,一般適用于多處理器系統中,可以提高GC的效率,但演算法復雜,系統消耗較大;

性能調優引數串列

日常性能調優中基本上都會用到以下的這幾個屬性

引數及其默認值描述
-XX:LargePageSizeInBytes=4m設定用于Java堆的大頁面尺寸
-XX:MaxHeapFreeRatio=70GC后java堆中空閑量占的最大比例
-XX:MaxNewSize=size新生成物件能占用記憶體的最大值
-XX:MaxPermSize=64m老生代物件能占用記憶體的最大值
-XX:MinHeapFreeRatio=40GC后java堆中空閑量占的最小比例
-XX:NewRatio=2新生代記憶體容量與老生代記憶體容量的比例
-XX:NewSize=2.125m新生代物件生成時占用記憶體的默認值
-XX:ReservedCodeCacheSize=32m保留代碼占用的記憶體容量
-XX:ThreadStackSize=512設定執行緒堆疊大小,若為0則使用系統默認值
-XX:+UseLargePages使用大頁面記憶體

除錯引數串列:

引數及其默認值描述
-XX:-CITime列印消耗在JIT編譯的時間
-XX:ErrorFile=./hs_err_pid.log保存錯誤日志或者資料到檔案中
-XX:-ExtendedDTraceProbes開啟solaris特有的dtrace探針
-XX:HeapDumpPath=./java_pid.hprof指定匯出堆資訊時的路徑或檔案名
-XX:-HeapDumpOnOutOfMemoryError當首次遭遇OOM時匯出此時堆中相關資訊
-XX:OnError=";"出現致命ERROR之后運行自定義命令
-XX:OnOutOfMemoryError=";"當首次遭遇OOM時執行自定義命令
-XX:-PrintClassHistogram遇到Ctrl-Break后列印類實體的柱狀資訊,與jmap -histo功能相同
-XX:-PrintConcurrentLocks遇到Ctrl-Break后列印并發鎖的相關資訊,與jstack -l功能相同
-XX:-PrintCommandLineFlags列印在命令列中出現過的標記
-XX:-PrintCompilation當一個方法被編譯時列印相關資訊
-XX:-PrintGC每次GC時列印相關資訊
-XX:-PrintGC Details每次GC時列印詳細資訊
-XX:-PrintGCTimeStamps列印每次GC的時間戳
-XX:-TraceClassLoading跟蹤類的加載資訊
-XX:-TraceClassLoadingPreorder跟蹤被參考到的所有類的加載資訊
-XX:-TraceClassResolution跟蹤常量池
-XX:-TraceClassUnloading跟蹤類的卸載資訊
-XX:-TraceLoaderConstraints跟蹤類加載器約束的相關資訊

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/295165.html

標籤:java

上一篇:jmap的使用以及記憶體溢位分析

下一篇:springboot整合websocket實作群聊 + 私信,可提供原始碼

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more