From f0548a37defad384b6a23844111edbeee8ea2b6d Mon Sep 17 00:00:00 2001 From: Stefan Huehner Date: Thu, 13 Dec 2018 15:20:34 +0100 Subject: [PATCH] Fix jstat* plugins to work again with java 6+7, fix PU reporting for Java8. jstat column output is not stable across JVM versions (technically version of jstat binary used). New columns are added not add the end of column list but in the middle breaking access via constant index. Following table shows the known columns per version: Oracle JDK / OpenJDK 1.5 .. 1.7 S0C S1C S0U S1U EC EU OC OU PC PU YGC YGCT FGC FGCT GCT Openjdk 1.8 .. 10 S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT Openjdk 11 .. 12 S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT CGC CGCT GCT Earlier commit here added support for java8+ but using version checking if version == 1.5 > Use pre-java8 column format, else new format. As fixing java6+7 would mean more version comparison which is ugly this cmomit changes retrival logic to the following; a.) Parse first line jstat output to find position for each label b.) Then use that position to fetch value from 2nd line That way code auto-adjusts to any ordering change without needing any java version specific code or checks. On the way fix 'Permanent Used' value reporting for java8 which was broken (missing variable rename from PU -> MU when java8 support was added). --- plugins/jvm/jstat__gccount | 28 ++++++------ plugins/jvm/jstat__gctime | 36 ++++++--------- plugins/jvm/jstat__heap | 91 +++++++++++--------------------------- 3 files changed, 55 insertions(+), 100 deletions(-) diff --git a/plugins/jvm/jstat__gccount b/plugins/jvm/jstat__gccount index a6eae247..40215d50 100755 --- a/plugins/jvm/jstat__gccount +++ b/plugins/jvm/jstat__gccount @@ -25,6 +25,7 @@ # Target Java Virtual Machine to monitor are: # Sun JDK 5.0 (http://java.sun.com/javase/) # Sun JDK 8.0 (http://java.sun.com/javase/) +# OpenJDK 1.7 .. 11 (https://openjdk.java.net/) # BEA JRockit 5.0 (http://dev2dev.bea.com/jrockit/) # # Parameters: @@ -53,12 +54,7 @@ get_jdk_type() { if "${JAVA_HOME}/bin/java" -version 2>&1 | grep -qi 'jrockit'; then echo "bea" else - version=$("${JAVA_HOME}/bin/java" -version 2>&1 | grep '^java version' | awk '{print $3}' | sed -e 's/\"//g' | cut -d'_' -f 1) - if echo "$version" | grep -q '^1\.5\.'; then - echo "sun15" - else - echo "sun" - fi + echo "sun" fi } @@ -89,17 +85,21 @@ print_stats() { if [ "${JDK_TYPE}" = "bea" ]; then # shellcheck disable=SC2016 awk_script='{ YC = $4; OC = $5; print "Young_GC.value " YGC; print "Old_GC.value " FGC; }' - elif [ "${JDK_TYPE}" = "sun15" ]; then - # shellcheck disable=SC2016 - awk_script='{ YGC = $11; FGC = $13; print "Young_GC.value " YGC; print "Full_GC.value " FGC; }' else - # example output of jstat for Java 1.8: - # S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT - # 2048.0 2048.0 0.0 1344.0 694784.0 145013.5 1398272.0 414857.1 102400.0 96308.0 12544.0 11240.1 979 20.997 5 2.705 23.702 + # List & Order of columns of jstat changes with java versions + # idx["YGC"] is index of YGC column in output (i.e. 13) + # $idx["YGC"] then accesses the value at this position (taken from 2nd line of the output) # shellcheck disable=SC2016 - awk_script='{ YGC = $13; FGC = $15; print "Young_GC.value " YGC; print "Full_GC.value " FGC; }' + awk_script=' + NR==1 { + for (i=1;i<=NF;i++) idx[$i]=i + } + NR==2 { + print "Young_GC.value " $idx["YGC"]; + print "Full_GC.value " $idx["FGC"]; + }' fi - "${JAVA_HOME}/bin/jstat" -gc "$pid_num" | tail -1 | awk "$awk_script" + "${JAVA_HOME}/bin/jstat" -gc "$pid_num" | awk "$awk_script" } diff --git a/plugins/jvm/jstat__gctime b/plugins/jvm/jstat__gctime index 21cdec82..af5cd455 100755 --- a/plugins/jvm/jstat__gctime +++ b/plugins/jvm/jstat__gctime @@ -25,6 +25,7 @@ # Target Java Virtual Machine to monitor are: # Sun JDK 5.0 (http://java.sun.com/javase/) # Sun JDK 8.0 (http://java.sun.com/javase/) +# OpenJDK 1.7 .. 11 (https://openjdk.java.net/) # BEA JRockit 5.0 (http://dev2dev.bea.com/jrockit/) # # Parameters: @@ -53,12 +54,7 @@ get_jdk_type() { if "${JAVA_HOME}/bin/java" -version 2>&1 | grep -qi 'jrockit'; then echo "bea" else - version=$("${JAVA_HOME}/bin/java" -version 2>&1 | grep '^java version' | awk '{print $3}' | sed -e 's/\"//g' | cut -d'_' -f 1) - if echo "$version" | grep -q '^1\.5\.'; then - echo "sun15" - else - echo "sun" - fi + echo "sun" fi } @@ -101,25 +97,21 @@ print_stats() { print "Old_GC.value " OCTime; print "Young_Pause.value " YCPauseTime; print "Old_Pause.value " OCPauseTime; }' - elif [ "${JDK_TYPE}" = "sun15" ]; then - # shellcheck disable=SC2016 - awk_script='{ - YGCT = $12; - FGCT = $14; - print "Young_GC.value " YGCT; - print "Full_GC.value " FGCT; }' else - # example output of jstat for Java 1.8: - # S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT - # 2048.0 2048.0 0.0 1344.0 694784.0 145013.5 1398272.0 414857.1 102400.0 96308.0 12544.0 11240.1 979 20.997 5 2.705 23.702 + # List & Order of columns of jstat changes with java versions + # idx["YGC"] is index of YGC column in output (i.e. 13) + # $idx["YGC"] then accesses the value at this position (taken from 2nd line of the output) # shellcheck disable=SC2016 - awk_script='{ - YGCT = $14; - FGCT = $16; - print "Young_GC.value " YGCT; - print "Full_GC.value " FGCT; }' + awk_script=' + (NR==1) { + for (i=1;i<=NF;i++) idx[$i]=i + } + (NR==2) { + print "Young_GC.value " $idx["YGCT"]; + print "Full_GC.value " $idx["FGCT"]; + }' fi - "${JAVA_HOME}/bin/jstat" -gc "$pid_num" | tail -1 | awk "$awk_script" + "${JAVA_HOME}/bin/jstat" -gc "$pid_num" | awk "$awk_script" } diff --git a/plugins/jvm/jstat__heap b/plugins/jvm/jstat__heap index d6739662..8142273d 100755 --- a/plugins/jvm/jstat__heap +++ b/plugins/jvm/jstat__heap @@ -25,6 +25,7 @@ # Target Java Virtual Machine to monitor are: # Sun JDK 5.0 (http://java.sun.com/javase/) # Sun JDK 8.0 (http://java.sun.com/javase/) +# OpenJDK 1.7 .. 11 (https://openjdk.java.net/) # BEA JRockit 5.0 (http://dev2dev.bea.com/jrockit/) # # Parameters: @@ -53,12 +54,7 @@ get_jdk_type() { if "${JAVA_HOME}/bin/java" -version 2>&1 | grep -qi 'jrockit'; then echo "bea" else - version=$("${JAVA_HOME}/bin/java" -version 2>&1 | grep '^java version' | awk '{print $3}' | sed -e 's/\"//g' | cut -d'_' -f 1) - if echo "$version" | grep -q '^1\.5\.'; then - echo "sun15" - else - echo "sun" - fi + echo "sun" fi } @@ -114,67 +110,34 @@ print_stats() { print "NurserySize.value " NurserySize * 1024; print "HeapSize.value " HeapSize * 1024; print "UsedHeapSize.value " UsedHeapSize * 1024; }' - elif [ "${JDK_TYPE}" = "sun15" ]; then - # shellcheck disable=SC2016 - awk_script='{ - S0C = $1; - S1C = $2; - S0U = $3; - S1U = $4; - EC = $5; - EU = $6; - OC = $7; - OU = $8; - PC = $9; - PU = $10; - S0F = S0C - S0U; - S1F = S1C - S1U; - EF = EC - EU; - OF = OC - OU; - PF = PC - PU; - print "Eden_Used.value " EU * 1024; - print "Eden_Free.value " EF * 1024; - print "Survivor0_Used.value " S0U * 1024; - print "Survivor0_Free.value " S0F * 1024; - print "Survivor1_Used.value " S1U * 1024; - print "Survivor1_Free.value " S1F * 1024; - print "Old_Used.value " OU * 1024; - print "Old_Free.value " OF * 1024; - print "Permanent_Used.value " PU * 1024; - print "Permanent_Free.value " PF * 1024; }' else - # example output of jstat for Java 1.8: - # S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT - # 2048.0 2048.0 0.0 1344.0 694784.0 145013.5 1398272.0 414857.1 102400.0 96308.0 12544.0 11240.1 979 20.997 5 2.705 23.702 + # List & Order of columns of jstat changes with java versions + # idx["YGC"] is index of YGC column in output (i.e. 13) + # $idx["YGC"] then accesses the value at this position (taken from 2nd line of the output) # shellcheck disable=SC2016 - awk_script='{ - S0C = $1; - S1C = $2; - S0U = $3; - S1U = $4; - EC = $5; - EU = $6; - OC = $7; - OU = $8; - MC = $9; - MU = $10; - S0F = S0C - S0U; - S1F = S1C - S1U; - EF = EC - EU; - OF = OC - OU; - MF = MC - MU; - print "Eden_Used.value " EU * 1024; - print "Eden_Free.value " EF * 1024; - print "Survivor0_Used.value " S0U * 1024; - print "Survivor0_Free.value " S0F * 1024; - print "Survivor1_Used.value " S1U * 1024; - print "Survivor1_Free.value " S1F * 1024; - print "Old_Used.value " OU * 1024; - print "Old_Free.value " OF * 1024; - print "Permanent_Used.value " PU * 1024; - print "Permanent_Free.value " MF * 1024; }' + awk_script=' + NR==1 { + for (i=1;i<=NF;i++) idx[$i]=i + } + NR==2 { + S0F = $idx["S0C"] - $idx["S0U"]; + S1F = $idx["S1C"] - $idx["S1U"]; + EF = $idx["EC"] - $idx["EU"]; + OF = $idx["OC"] - $idx["OU"]; + MF = $idx["MC"] - $idx["MU"]; + print "Eden_Used.value " $idx["EU"] * 1024; + print "Eden_Free.value " EF * 1024; + print "Survivor0_Used.value " $idx["S0U"] * 1024; + print "Survivor0_Free.value " S0F * 1024; + print "Survivor1_Used.value " $idx["S1U"] * 1024; + print "Survivor1_Free.value " S1F * 1024; + print "Old_Used.value " $idx["OU"] * 1024; + print "Old_Free.value " OF * 1024; + print "Permanent_Used.value " $idx["MU"] * 1024; + print "Permanent_Free.value " MF * 1024; + }' fi - "${JAVA_HOME}/bin/jstat" -gc "$pid_num" | tail -1 | awk "$awk_script" + "${JAVA_HOME}/bin/jstat" -gc "$pid_num" | awk "$awk_script" }