# TLjvm.ctl: Collects Oracle Java Virtual Machine Information # $Id: TLjvm.ctl,v 1.5 2015/09/25 00:35:35 RDA Exp $ # ARCS: $Header: /home/cvs/cvs/RDA_8/src/scripting/lib/collect/OFM/TLjvm.ctl,v 1.5 2015/09/25 00:35:35 RDA Exp $ # # Change History # 20150924 MSC Eliminate trailing spaces. =head1 NAME OFM:TLjvm - Collects Oracle Java Virtual Machine Information =head1 DESCRIPTION This tool collects information about an Oracle Java Virtual Machine (JVM). The tool covers the following versions: =over 4 =item o Oracle Java Development Kit HotSpot 1.6 and later =item o Oracle JRockit R27 and later =back =head1 USAGE This tool can be used in two ways: =over 3 =item a) Runs interactively. It requests the user to enter the required information. -T jvm run jvm =item b) Runs from the command line. The input can be given in the command line using the following syntax: -T jvm:||,|| -XRda run jvm -h -n -i -d run jvm -h -n -i -d Where: =over 9 =item S< >EdurE is the duration (in minutes) for collecting Java Flight Recording (JFR) diagnostics =item S< >EintE is the interval (in seconds) between the thread dumps =item S< >EjdkE is the Oracle JVM home directory =item S< >EmenuE is the comma-separated list of data to collect (valid types are C, C, and C) =item S< >EnumE is the maximum number of thread dumps to capture =item S< >EpidE is the process identifier of the Oracle JVM process to analyze =item S< >EreqE is the space-separated list of data to collect (valid types are C, C, and C) =back =back The tool collects Oracle Java Virtual Machine data, generates reports, and displays key information about the results. The reports can be viewed in the C submenu of the final RDA output package also. If it is not disabled, you can refresh that section by the following command: -vCRP LOAD -v collect -RP LOAD =cut options d:h:i:n: section tool if !match(${RDA.T_OS},'(cygwin|linux|solaris|MSWin32|MSWin64)') die 'Platform not supported' echo tput('bold'),'Collecting Oracle Java Virtual Machine data ...',tput('off') # Set the abbreviation and purge old reports call setAbbr('OFM_JVM_') call purge('E','.',15,0) # Get the arguments if @arg {if match($arg[0],'\|') {var ($PID,$mnu,$thd,$JFR_DUR,$JDK) = split('\|',$arg[0]) var @MENU = split('[,\s]',$mnu) var ($THD_NUM,$THD_INT) = split(',',$thd) } else {var ($PID,@MENU) = @arg var $JDK = nvl($opt{'n'},${ENV.JAVA_HOME}) var $JFR_DUR = $opt{'d'} var $THD_INT = $opt{'i'} var $THD_NUM = $opt{'n'} } # Validate the JDK home if !?testFile('f',catFile($JDK,'bin',${AS.EXE:'java'})) die 'Invalid JDK location' if loadCommand(concat(lastTestCommand(),' -version 2>&1')) {var @lin = getLines() if match($lin[-1],'^Java\sHotSpot') {var $TYPE = 'hotspot' var ($ver) = match($lin[1],'build\s(\d+\.\d+)\.') if !compare('VALID',$ver,'1.6') die 'The specified JDK directory does not contain either HotSpot 1.6 or \ later / JRockit R27 or later. Without a valid directory, the \ collection will be disabled.' } elsif match($lin[-1],'^(BEA|Oracle)\sJRockit') {var $TYPE = 'jrockit' var ($ver) = match($lin[-1],'build\sR(\d+)\.') if !compare('VALID',$ver,'27') die 'The specified JDK directory does not contain either HotSpot 1.6 or \ later / JRockit R27 or later. Without a valid directory, the \ collection will be disabled.' } } # Validate the number of thread dumps to collect if !match($THD_NUM,'^\d+$') var $THD_NUM = 2 # Validate the thread dump interval if !match($THD_INT,'^\d+$') var $THD_INT = 5 # Validate the JFR duration if !match($JFR_DUR,'^\d+$') var $JFR_DUR = 1 } else {call requestInput('TLjvm') var $JDK = ${RUN.REQUEST.D_JDK} var $TYPE = ${RUN.REQUEST.T_TYPE} var $PID = ${RUN.REQUEST.N_PID} var @MENU = @{RUN.REQUEST.W_MENU} var $JFR_DUR = ${RUN.REQUEST.N_JFR_DURATION:1} var $THD_NUM = ${RUN.REQUEST.N_THREAD_DUMP:2} var $THD_INT = ${RUN.REQUEST.N_THREAD_INTERVAL:5} } # Validate the JDK home if !?$JDK die 'Invalid JDK location' # Validate the process identifier if !match($PID,'^\d+$') die 'Invalid or missing process identifier' # Validate the request if grep(@MENU,'TD','f') {var $THREAD = true call push(@ttl,'Thread Dumps Information') } if grep(@MENU,'^FR$','f') {var $JFR = true call push(@ttl,'Java Flight Recording Information') } if grep(@MENU,'^HD$','f') {var $HEAP = true call push(@ttl,'Heap Dumps Information') } if !@ttl die 'No data requested' # Initialization var $MOD = cond(isUnix(),'fx','fr') var $TOC = '%TOC%' var $TOP = '[[#Top][Back to top]]' if compare('eq',$TYPE,'jrockit') {if ?testFile($MOD,catFile($JDK,'bin',${AS.EXE:'jrcmd'})) var $JRCMD = lastTestCommand() } # Set the report prefix and initiate the result report call setPrefix(concat('p',$PID)) output E,result title '---+!! Oracle Java Virtual Machine Data Collection' title $TOC title '---+ Parameters' title '|*Java Virtual Machine Home*|',encode($JDK),' |' title '|*Process Identifier*| ',$PID,'|' title '|*Java Virtual Machine Type*|',uc($TYPE),' |' title '|*Diagnostic Information Requested*|',join('%BR%',@ttl),' |' if ?$THREAD {title '|*Number of Thread Dumps to Capture*|',$THD_NUM,' |' title '|*Thread Dumps Interval (in seconds)*|',$THD_INT,' |' } if ?$JFR title '|*JFR Duration (in minutes)*|',$JFR_DUR,' |' title $TOP =head2 Thread Dump Information Collects Java Virtual Machine thread dump information. =cut if ?$THREAD {debug ' Inside TLjvm tool, gathering thread dump information' # Macro to collect the thread dumps macro col_thd_dmp {var ($cmd,$nam) = @arg import $THD_NUM,$THD_INT,$TOP prefix {write '---+ Thread Dump Information' write '| *Iteration*|' } var ($itr,$max) = (0,$THD_NUM) while true {var $rpt = $[OUT]->add_report('e',concat($nam,incr($itr)),0) prefix $rpt {write {$rpt} '---+ Thread Dump Information (Iteration ',$itr,')' write {$rpt} '---## Using: ',encode($cmd) } call writeCommand($rpt,$cmd) if $rpt->has_output(true) {write {$rpt} $TOP write '| [[',$rpt->get_html(true),'][_blank][',$itr,']]|' call $rpt->render } end $rpt break !decr($max) sleep $THD_INT } if hasOutput(true) write $TOP } # Collect the thread dumps based on JDK type if compare('eq',$TYPE,'hotspot') {if ?testFile($MOD,catFile($JDK,'bin',${AS.EXE:'jstack'})) call col_thd_dmp(join(' ',lastTestCommand(),'-l',$PID),'jstack') } elsif compare('eq',$TYPE,'jrockit') {if ?$JRCMD call col_thd_dmp(join(' ',last,$PID,'print_threads'),'jrcmd') } } =head2 Flight Recording Information Collects Java Virtual Machine flight recording information. =cut if ?$JFR {debug ' Inside TLjvm tool, gathering flight recording information' var $rpt = $[OUT]->add_report('e','jfrrec',0,'.jfr') var $fil = $rpt->get_file(true) var ($sec,$dur) = (60,expr('*',$JFR_DUR,60)) if compare('eq',$TYPE,'hotspot') {if ?testFile($MOD,catFile($JDK,'bin',${AS.EXE:'jcmd'})) call command(concat(lastTestCommand(),' ',$PID,' JFR.start \ duration=',$dur,'s filename=',quote($fil),' 2>&1')) } elsif compare('eq',$TYPE,'jrockit') {if ?$JRCMD call command(concat(last,' ',$PID,' start_flightrecording name=Rda \ duration=',$dur,'s filename=',quote($fil),' 2>&1')) } var $max = time() incr $max,$dur while ?testFile('f',$fil) {debug ' - please wait (',$dur,' seconds remaining) ...' sleep $sec var $dur = $max decr $dur,time() break expr('<=',$dur,0) if expr('<',$dur,$sec) var $sec = $dur } prefix {write '---+ Flight Recording Information' write ' * Links point to files that have been collected in their \ original format. Opening them directly in your browser can \ present security risks. To prevent them, access the file \ outside the browser or use the link to save them and use an \ adequate viewer.' write '|*File Name*| *Size*|*Last Modification*|' } if ?testFile('s',$fil) {var $lnk = concat('[[',$rpt->get_raw(true),'][_blank][',encode($fil),']]') write '|',$lnk,'| ',getSize($fil),'|',getLastModify($fil,''),' |' } end $rpt if hasOutput(true) write $TOP } =head2 Heap Dump Information Collects Java Virtual Machine heap dump information. =cut if ?$HEAP {debug ' Inside TLjvm tool, gathering heap dump information' var $rpt = $[OUT]->add_report('e','hprofdump',0,'.hprof') var $fil = $rpt->get_file(true) if compare('eq',$TYPE,'hotspot') {if ?testFile($MOD,catFile($JDK,'bin',${AS.EXE:'jmap'})) call command($cmd = concat(lastTestCommand(),\ ' -dump:live,file=',quote($fil),' ',$PID,' 2>&1')) } elsif compare('eq',$TYPE,'jrockit') {if ?$JRCMD call command($cmd = concat(last,\ ' ',$PID,' hprofdump filename=',quote($fil),' 2>&1')) } prefix {write '---+ Heap Dump Information' write '---## Using: ',encode($cmd) write ' * Links point to files that have been collected in their \ original format. Opening them directly in your browser can \ present security risks. To prevent them, access the file \ outside the browser or use the link to save them and use an \ adequate viewer.' write '|*File Name*| *Size*|*Last Modification*|' } if ?testFile('s',$fil) {var $lnk = concat('[[',$rpt->get_raw(true),'][_blank][',encode($fil),']]') write '|',$lnk,'| ',getSize($fil),'|',getLastModify($fil,''),' |' } end $rpt if hasOutput(true) write $TOP } # Render the report if isCreated(true) {call renderFile() dump 'Result file: ',last } else echo 'No information collected' =head1 SEE ALSO L =begin credits =over 10 =item RDA 8.06: Daniel Mortimer. =back =end credits =head1 COPYRIGHT NOTICE Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. =head1 TRADEMARK NOTICE Oracle and Java are registered trademarks of Oracle and/or its affiliates. Other names may be trademarks of their respective owners. =cut