Skip to content

Commit

Permalink
Updated java options manage. Fixes infinispan#229
Browse files Browse the repository at this point in the history
  • Loading branch information
rigazilla committed May 29, 2024
1 parent 6b1617d commit 0977d3c
Show file tree
Hide file tree
Showing 2 changed files with 203 additions and 94 deletions.
292 changes: 199 additions & 93 deletions modules/org/infinispan/distribution/jvm/added/bin/java-opts.sh
Original file line number Diff line number Diff line change
@@ -1,136 +1,242 @@
#!/bin/sh
# ===================================================================================
# Generic startup script for running arbitrary Java applications with
# being optimized for running in containers
#
# Modified version of https://github.com/fabric8io-images/run-java-sh/blob/master/fish-pepper/run-java-sh/fp-files/run-java.sh
# ===================================================================================

## Generic startup script for running arbitrary Java applications with
## being optimized for running in containers
##
## Modified version of https://github.com/fabric8io-images/run-java-sh/blob/master/fish-pepper/run-java-sh/fp-files/run-java.sh
## ===================================================================================
if [ -n "${DEBUG:-}" ]; then
set -x
set -x
fi

# ksh is different for defining local vars
if [ -n "${KSH_VERSION:-}" ]; then
alias local=typeset
fi

# Generic formula evaluation based on awk
calc() {
local formula="$1"
shift
echo "$@" | awk '
function ceil(x) {
return x % 1 ? int(x) + 1 : x
}
function log2(x) {
return log(x)/log(2)
}
function max2(x, y) {
return x > y ? x : y
}
function round(x) {
return int(x + 0.5)
}
{print '"int(${formula})"'}
'
#!/bin/bash

export JBOSS_CONTAINER_UTIL_LOGGING_MODULE="${JBOSS_CONTAINER_UTIL_LOGGING_MODULE-/opt/jboss/container/util/logging}"
export JBOSS_CONTAINER_JAVA_RUN_MODULE="${JBOSS_CONTAINER_JAVA_RUN_MODULE-/opt/jboss/container/java/run}"

# Default the application dir to the S2I deployment dir
if [ -z "$JAVA_APP_DIR" ]
then JAVA_APP_DIR=/deployments
fi

source "$JBOSS_CONTAINER_UTIL_LOGGING_MODULE/logging.sh"

# ==========================================================
# Generic run script for running arbitrary Java applications
#
# This has forked (and diverged) from:
# at https://github.com/fabric8io/run-java-sh
#
# ==========================================================

# Error is indicated with a prefix in the return value
check_error() {
local msg=$1
if echo ${msg} | grep -q "^ERROR:"; then
log_error ${msg}
exit 1
fi
}

max_memory() {
# High number which is the max limit until which memory is supposed to be
# unbounded.
local mem_file="/sys/fs/cgroup/memory.max"
if [ ! -r "${mem_file}" ]; then
mem_file="/sys/fs/cgroup/memory/memory.limit_in_bytes"
# detect Quarkus fast-jar package type (OPENJDK-631)
is_quarkus_fast_jar() {
if test -f quarkus-app/quarkus-run.jar; then
log_info "quarkus fast-jar package type detected"
echo quarkus-app/quarkus-run.jar
return 0
else
return 1
fi
if [ -r "${mem_file}" ]; then
local max_mem_cgroup="$(cat ${mem_file})"
local max_mem_meminfo_kb="$(cat /proc/meminfo | awk '/MemTotal/ {print $2}')"
local max_mem_meminfo="$(expr $max_mem_meminfo_kb \* 1024)"
if [ ${max_mem_cgroup:-0} != -1 ] && [ ${max_mem_cgroup:-0} -lt ${max_mem_meminfo:-0} ]
then
echo "${max_mem_cgroup}"
}

# Try hard to find a sane default jar-file
auto_detect_jar_file() {
local dir=$1

# Filter out temporary jars from the shade plugin which start with 'original-'
local old_dir=$(pwd)
cd ${dir}
if [ $? = 0 ]; then

if quarkus="$(is_quarkus_fast_jar)"; then
echo "$quarkus"
return
fi

local nr_jars=`ls *.jar 2>/dev/null | grep -v '^original-' | wc -l | tr -d '[[:space:]]'`
if [ ${nr_jars} = 1 ]; then
ls *.jar | grep -v '^original-'
exit 0
fi

log_error "Neither \$JAVA_MAIN_CLASS nor \$JAVA_APP_JAR is set and ${nr_jars} JARs found in ${dir} (1 expected)"
cd ${old_dir}
else
log_error "No directory ${dir} found for auto detection"
fi
}

init_limit_env_vars() {
# Read in container limits and export the as environment variables
local mem_limit="$(max_memory)"
if [ -n "${mem_limit}" ]; then
export CONTAINER_MAX_MEMORY="${mem_limit}"
# Check directories (arg 2...n) for a jar file (arg 1)
get_jar_file() {
local jar=$1
shift;

if [ "${jar:0:1}" = "/" ]; then
if [ -f "${jar}" ]; then
echo "${jar}"
else
log_error "No such file ${jar}"
fi
else
for dir in $*; do
if [ -f "${dir}/$jar" ]; then
echo "${dir}/$jar"
return
fi
done
log_error "No ${jar} found in $*"
fi
}

# ==========================================================================
# Check for memory options and set max heap size if needed
calc_max_memory() {
# Check whether -Xmx is already given in JAVA_OPTIONS
if echo "${JAVA_OPTIONS:-}" | grep -q -- "-Xmx"; then
return
load_env() {
# Configuration stuff is read from this file
local run_env_sh="run-env.sh"

# Load default default config
if [ -f "${JBOSS_CONTAINER_JAVA_RUN_MODULE}/${run_env_sh}" ]; then
source "${JBOSS_CONTAINER_JAVA_RUN_MODULE}/${run_env_sh}"
fi

if [ -z "${CONTAINER_MAX_MEMORY:-}" ]; then
return
# Check also $JAVA_APP_DIR. Overrides other defaults
# It's valid to set the app dir in the default script
if [ -f "${JAVA_APP_DIR}/${run_env_sh}" ]; then
source "${JAVA_APP_DIR}/${run_env_sh}"
fi

# Check for the 'real memory size' and calculate Xmx from the ratio
if [ -n "${JAVA_MAX_MEM_RATIO:-}" ]; then
if [ "${JAVA_MAX_MEM_RATIO}" -eq 0 ]; then
# Explicitely switched off
return
fi
calc_mem_opt "${CONTAINER_MAX_MEMORY}" "${JAVA_MAX_MEM_RATIO}" "mx"
export JAVA_APP_DIR

# JAVA_LIB_DIR defaults to JAVA_APP_DIR
export JAVA_LIB_DIR="${JAVA_LIB_DIR:-${JAVA_APP_DIR}}"
if [ -z "${JAVA_MAIN_CLASS}" ] && [ -z "${JAVA_APP_JAR}" ]; then
JAVA_APP_JAR="$(auto_detect_jar_file ${JAVA_APP_DIR})"
check_error "${JAVA_APP_JAR}"
fi
# When JAVA_MAX_MEM_RATIO not set and JVM >= 10 no max_memory
}

# Check for memory options and set initial heap size if requested
calc_init_memory() {
# Check whether -Xms is already given in JAVA_OPTIONS.
if echo "${JAVA_OPTIONS:-}" | grep -q -- "-Xms"; then
return
if [ "x${JAVA_APP_JAR}" != x ]; then
local jar="$(get_jar_file ${JAVA_APP_JAR} ${JAVA_APP_DIR} ${JAVA_LIB_DIR})"
check_error "${jar}"
export JAVA_APP_JAR=${jar}
else
export JAVA_MAIN_CLASS
fi
}

# Check if value set
if [ -z "${JAVA_INIT_MEM_RATIO:-}" ] || [ -z "${CONTAINER_MAX_MEMORY:-}" ] || [ "${JAVA_INIT_MEM_RATIO}" -eq 0 ]; then
return
# Combine all java options
get_java_options() {
local jvm_opts
local debug_opts
local proxy_opts
local opts
if [ -f "${JBOSS_CONTAINER_JAVA_JVM_MODULE}/java-default-options" ]; then
jvm_opts=$(${JBOSS_CONTAINER_JAVA_JVM_MODULE}/java-default-options)
fi
if [ -f "${JBOSS_CONTAINER_JAVA_JVM_MODULE}/debug-options" ]; then
debug_opts=$(${JBOSS_CONTAINER_JAVA_JVM_MODULE}/debug-options)
fi
if [ -f "${JBOSS_CONTAINER_JAVA_PROXY_MODULE}/proxy-options" ]; then
source "${JBOSS_CONTAINER_JAVA_PROXY_MODULE}/proxy-options"
proxy_opts="$(proxy_options)"
fi

# Calculate Xms from the ratio given
calc_mem_opt "${CONTAINER_MAX_MEMORY}" "${JAVA_INIT_MEM_RATIO}" "ms"
opts=${JAVA_OPTS-${debug_opts} ${proxy_opts} ${jvm_opts} ${JAVA_OPTS_APPEND}}
# Normalize spaces with awk (i.e. trim and eliminate double spaces)
echo "${opts}" | awk '$1=$1'
}

calc_mem_opt() {
local max_mem="$1"
local fraction="$2"
local mem_opt="$3"
# Read in a classpath either from a file with a single line, colon separated
# or given line-by-line in separate lines
# Arg 1: path to claspath (must exist), optional arg2: application jar, which is stripped from the classpath in
# multi line arrangements
format_classpath() {
local cp_file="$1"
local app_jar="$2"

local wc_out=`wc -l $1 2>&1`
if [ $? -ne 0 ]; then
log_error "Cannot read lines in ${cp_file}: $wc_out"
exit 1
fi

local val=$(calc 'round($1*$2/100/1048576)' "${max_mem}" "${fraction}")
echo "-X${mem_opt}${val}m"
local nr_lines=`echo $wc_out | awk '{ print $1 }'`
if [ ${nr_lines} -gt 1 ]; then
local sep=""
local classpath=""
while read file; do
local full_path="${JAVA_LIB_DIR}/${file}"
# Don't include app jar if include in list
if [ x"${app_jar}" != x"${full_path}" ]; then
classpath="${classpath}${sep}${full_path}"
fi
sep=":"
done < "${cp_file}"
echo "${classpath}"
else
# Supposed to be a single line, colon separated classpath file
cat "${cp_file}"
fi
}

# Switch on diagnostics except when switched off
diagnostics_options() {
if [ -n "${JAVA_DIAGNOSTICS:-}" ]; then
echo "-XX:NativeMemoryTracking=summary -Xlog:gc*:stdout:time -XX:+UnlockDiagnosticVMOptions"
# Fetch classpath from env or from a local "run-classpath" file
get_classpath() {
local cp_path="."
if [ "x${JAVA_LIB_DIR}" != "x${JAVA_APP_DIR}" ]; then
cp_path="${cp_path}:${JAVA_LIB_DIR}"
fi
if [ -z "${JAVA_CLASSPATH}" ] && [ "x${JAVA_MAIN_CLASS}" != x ]; then
if [ "x${JAVA_APP_JAR}" != x ]; then
cp_path="${cp_path}:${JAVA_APP_JAR}"
fi
if [ -f "${JAVA_LIB_DIR}/classpath" ]; then
# Classpath is pre-created and stored in a 'run-classpath' file
cp_path="${cp_path}:`format_classpath ${JAVA_LIB_DIR}/classpath ${JAVA_APP_JAR}`"
else
# No order implied
cp_path="${cp_path}:${JAVA_APP_DIR}/*"
fi
elif [ "x${JAVA_CLASSPATH}" != x ]; then
# Given from the outside
cp_path="${JAVA_CLASSPATH}"
fi
echo "${cp_path}"
}

gc_options() {
local gc_options="-XX:+ExitOnOutOfMemoryError"
if [ -n "${JAVA_GC_METASPACE_SIZE:-}" ] || [ "${JAVA_GC_METASPACE_SIZE//[!0-9]/}" -gt 0 ]; then
gc_options="${gc_options} -XX:MetaspaceSize=${JAVA_GC_METASPACE_SIZE}"
fi
# Mask secrets before printing
mask_passwords() {
local content="$1"
local result=""

if [ -n "${JAVA_GC_MAX_METASPACE_SIZE:-}" ] || [ "${JAVA_GC_MAX_METASPACE_SIZE//[!0-9]/}" -gt 0 ]; then
gc_options="${gc_options} -XX:MaxMetaspaceSize=${JAVA_GC_MAX_METASPACE_SIZE}"
fi
echo ${gc_options}
IFS=' ' read -r -a key_value_pairs <<< "$content"

for pair in "${key_value_pairs[@]}"; do
key=$(echo "$pair" | cut -d '=' -f 1)
value=$(echo "$pair" | cut -d '=' -f 2-)

if [[ $key =~ [Pp][Aa][Ss][Ss][Ww][Oo][Rr][Dd] ]]; then
result+="$key=***** "
else
result+="$pair "
fi
done

echo "${result% }"
}


java_opts() {
init_limit_env_vars
# Echo options, trimming trailing and multiple spaces
echo "${JAVA_OPTIONS:-} $(calc_init_memory) $(calc_max_memory) $(diagnostics_options) $(gc_options)" | awk '$1=$1'
get_java_options
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# Set jvm args reflecting container limits and configured env vars
. $ISPN_HOME/bin/java-opts.sh
JAVA_OPTS="$(java_opts)"

set +eo pipefail

JAVA_OPTS="$(java_opts) $JAVA_OPTIONS"

# Add java options required by Infinispan
export JAVA_OPTS="$JAVA_OPTS -Djava.net.preferIPv4Stack=true -Djava.awt.headless=true"
Expand Down

0 comments on commit 0977d3c

Please sign in to comment.