jmaps 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. #!/bin/bash
  2. #
  3. # jmaps - creates java /tmp/perf-PID.map symbol maps for all java processes.
  4. #
  5. # This is a helper script that finds all running "java" processes, then executes
  6. # perf-map-agent on them all, creating symbol map files in /tmp. These map files
  7. # are read by perf_events (aka "perf") when doing system profiles (specifically,
  8. # the "report" and "script" subcommands).
  9. #
  10. # USAGE: jmaps [-u]
  11. # -u # unfoldall: include inlined symbols
  12. #
  13. # My typical workflow is this:
  14. #
  15. # perf record -F 99 -a -g -- sleep 30; jmaps
  16. # perf script > out.stacks
  17. # ./stackcollapse-perf.pl out.stacks | ./flamegraph.pl --color=java --hash > out.stacks.svg
  18. #
  19. # The stackcollapse-perf.pl and flamegraph.pl programs come from:
  20. # https://github.com/brendangregg/FlameGraph
  21. #
  22. # REQUIREMENTS:
  23. # Tune two environment settings below.
  24. #
  25. # 13-Feb-2015 Brendan Gregg Created this.
  26. # 20-Feb-2017 " " Added -u for unfoldall.
  27. JAVA_HOME=${JAVA_HOME:-/usr/lib/jvm/java-8-oracle}
  28. AGENT_HOME=${AGENT_HOME:-/usr/lib/jvm/perf-map-agent} # from https://github.com/jvm-profiling-tools/perf-map-agent
  29. debug=0
  30. if [[ "$USER" != root ]]; then
  31. echo "ERROR: not root user? exiting..."
  32. exit
  33. fi
  34. if [[ ! -x $JAVA_HOME ]]; then
  35. echo "ERROR: JAVA_HOME not set correctly; edit $0 and fix"
  36. exit
  37. fi
  38. if [[ ! -x $AGENT_HOME ]]; then
  39. echo "ERROR: AGENT_HOME not set correctly; edit $0 and fix"
  40. exit
  41. fi
  42. if [[ "$1" == "-u" ]]; then
  43. opts=unfoldall
  44. fi
  45. # figure out where the agent files are:
  46. AGENT_OUT=""
  47. AGENT_JAR=""
  48. if [[ -e $AGENT_HOME/out/attach-main.jar ]]; then
  49. AGENT_JAR=$AGENT_HOME/out/attach-main.jar
  50. elif [[ -e $AGENT_HOME/attach-main.jar ]]; then
  51. AGENT_JAR=$AGENT_HOME/attach-main.jar
  52. fi
  53. if [[ -e $AGENT_HOME/out/libperfmap.so ]]; then
  54. AGENT_OUT=$AGENT_HOME/out
  55. elif [[ -e $AGENT_HOME/libperfmap.so ]]; then
  56. AGENT_OUT=$AGENT_HOME
  57. fi
  58. if [[ "$AGENT_OUT" == "" || "$AGENT_JAR" == "" ]]; then
  59. echo "ERROR: Missing perf-map-agent files in $AGENT_HOME. Check installation."
  60. exit
  61. fi
  62. # Fetch map for all "java" processes
  63. echo "Fetching maps for all java processes..."
  64. for pid in $(pgrep -x java); do
  65. mapfile=/tmp/perf-$pid.map
  66. [[ -e $mapfile ]] && rm $mapfile
  67. cmd="cd $AGENT_OUT; $JAVA_HOME/bin/java -Xms32m -Xmx128m -cp $AGENT_JAR:$JAVA_HOME/lib/tools.jar net.virtualvoid.perf.AttachOnce $pid $opts"
  68. (( debug )) && echo $cmd
  69. user=$(ps ho user -p $pid)
  70. group=$(ps ho group -p $pid)
  71. if [[ "$user" != root ]]; then
  72. if [[ "$user" == [0-9]* ]]; then
  73. # UID only, likely GID too, run sudo with #UID:
  74. cmd="sudo -u '#'$user -g '#'$group sh -c '$cmd'"
  75. else
  76. cmd="sudo -u $user -g $group sh -c '$cmd'"
  77. fi
  78. fi
  79. echo "Mapping PID $pid (user $user):"
  80. if (( debug )); then
  81. time eval $cmd
  82. else
  83. eval $cmd
  84. fi
  85. if [[ -e "$mapfile" ]]; then
  86. chown root $mapfile
  87. chmod 666 $mapfile
  88. else
  89. echo "ERROR: $mapfile not created."
  90. fi
  91. echo "wc(1): $(wc $mapfile)"
  92. echo
  93. done