Java相關腳本

 

本人摘自:https://github.com/oldratlee/useful-scripts/blob/master/docs/java.md#beer-show-busy-java-threadsshcss

:beer: show-busy-java-threads

用於快速排查JavaCPU性能問題(top us值太高),自動查出運行的Java進程中消耗CPU多的線程,並打印出其線程棧,從而肯定致使性能問題的方法調用。
目前只支持Linux。緣由是MacWindowsps命令不支持列出線程線程,更多信息參見#33,歡迎提供解法。html

PS,如何操做能夠參見@bluedavy的《分佈式Java應用》的【5.1.1 cpu消耗分析】一節,說得很詳細:java

  1. top命令找出有問題Java進程及線程id
    1. 開啓線程顯示模式
    2. CPU使用率排序
    3. 記下Java進程id及其CPU高的線程id
  2. 用進程id做爲參數,jstack有問題的Java進程
  3. 手動轉換線程id成十六進制(能夠用printf %x 1234
  4. 查找十六進制的線程id(能夠用grep
  5. 查看對應的線程棧

查問題時,會要屢次這樣操做以肯定問題,上面過程太繁瑣太慢了。linux

用法

show-busy-java-threads
# 從全部運行的Java進程中找出最消耗CPU的線程(缺省5個),打印出其線程棧 # 缺省會自動從全部的Java進程中找出最消耗CPU的線程,這樣用更方便 # 固然你能夠手動指定要分析的Java進程Id,以保證只會顯示出那個你關心的Java進程的信息 show-busy-java-threads -p <指定的Java進程Id> show-busy-java-threads -c <要顯示的線程棧數> show-busy-java-threads <重複執行的間隔秒數> [<重複執行的次數>] # 屢次執行;這2個參數的使用方式相似vmstat命令 show-busy-java-threads -a <輸出記錄到的文件> # 記錄到文件以方便回溯查看 ############################## # 注意: ############################## # 若是Java進程的用戶 與 執行腳本的當前用戶 不一樣,則jstack不了這個Java進程 # 爲了能切換到Java進程的用戶,須要加sudo來執行,便可以解決: sudo show-busy-java-threads show-busy-java-threads -s <指定jstack命令的全路徑> # 對於sudo方式的運行,JAVA_HOME環境變量不能傳遞給root, # 而root用戶每每沒有配置JAVA_HOME且不方便配置, # 顯式指定jstack命令的路徑就反而顯得更方便了 # -m選項:執行jstack命令時加上-m選項,顯示上Native的棧幀,通常應用排查不須要使用 show-busy-java-threads -m # -F選項:執行jstack命令時加上 -F 選項(若是直接jstack無響應時,用於強制jstack),通常狀況不須要使用 show-busy-java-threads -F # -l選項:執行jstack命令時加上 -l 選項,顯示上更多相關鎖的信息,通常狀況不須要使用 # 注意:和 -m -F 選項一塊兒使用時,可能會大大增長jstack操做的耗時 show-busy-java-threads -l # 幫助信息 $ show-busy-java-threads -h Usage: show-busy-java-threads [OPTION]... [delay [count]] Find out the highest cpu consumed threads of java, and print the stack of these threads. Example: show-busy-java-threads # show busy java threads info show-busy-java-threads 1 # update every 1 seconds, (stop by eg: CTRL+C) show-busy-java-threads 3 10 # update every 3 seconds, update 10 times Options: -p, --pid <java pid> find out the highest cpu consumed threads from the specifed java process, default from all java process. -c, --count <num> set the thread count to show, default is 5 -a, --append-file <file> specify the file to append output as log -s, --jstack-path <path> specify the path of jstack command -F, --force set jstack to force a thread dump use when jstack <pid> does not respond (process is hung) -m, --mix-native-frames set jstack to print both java and native frames (mixed mode) -l, --lock-info set jstack with long listing. Prints additional information about locks -h, --help display this help and exit delay the delay between updates in seconds count the number of updates delay/count arguments imitates style of vmstat command

示例

$ show-busy-java-threads
[1] Busy(57.0%) thread(23355/0x5b3b) stack of java process(23269) under user(admin):
"pool-1-thread-1" prio=10 tid=0x000000005b5c5000 nid=0x5b3b runnable [0x000000004062c000] java.lang.Thread.State: RUNNABLE at java.text.DateFormat.format(DateFormat.java:316) at com.xxx.foo.services.common.DateFormatUtil.format(DateFormatUtil.java:41) at com.xxx.foo.shared.monitor.schedule.AppMonitorDataAvgScheduler.run(AppMonitorDataAvgScheduler.java:127) at com.xxx.foo.services.common.utils.AliTimer$2.run(AliTimer.java:128) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) at java.lang.Thread.run(Thread.java:662) [2] Busy(26.1%) thread(24018/0x5dd2) stack of java process(23269) under user(admin): "pool-1-thread-2" prio=10 tid=0x000000005a968800 nid=0x5dd2 runnable [0x00000000420e9000] java.lang.Thread.State: RUNNABLE at java.util.Arrays.copyOf(Arrays.java:2882) at java.lang.AbstractStringBuilder.expandCapacity(AbstractStringBuilder.java:100) at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:572) at java.lang.StringBuffer.append(StringBuffer.java:320) - locked <0x00000007908d0030> (a java.lang.StringBuffer) at java.text.SimpleDateFormat.format(SimpleDateFormat.java:890) at java.text.SimpleDateFormat.format(SimpleDateFormat.java:869) at java.text.DateFormat.format(DateFormat.java:316) at com.xxx.foo.services.common.DateFormatUtil.format(DateFormatUtil.java:41) at com.xxx.foo.shared.monitor.schedule.AppMonitorDataAvgScheduler.run(AppMonitorDataAvgScheduler.java:126) at com.xxx.foo.services.common.utils.AliTimer$2.run(AliTimer.java:128) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) ...

上面的線程棧能夠看出,CPU消耗最高的2個線程都在執行java.text.DateFormat.format,業務代碼對應的方法是shared.monitor.schedule.AppMonitorDataAvgScheduler.run。能夠基本肯定:android

  • AppMonitorDataAvgScheduler.run調用DateFormat.format次數比較頻繁。
  • DateFormat.format比較慢。(這個能夠由DateFormat.format的實現肯定。)

多執行幾回show-busy-java-threads,若是上面狀況高几率出現,則能夠肯定上面的斷定。
由於調用越少代碼執行越快,則出如今線程棧的機率就越低。
腳本有自動屢次執行的功能,指定 重複執行的間隔秒數/重複執行的次數 參數。git

分析shared.monitor.schedule.AppMonitorDataAvgScheduler.run實現邏輯和調用方式,以優化實現解決問題。github

貢獻者

:beer: show-duplicate-java-classes

找出Java LibJava庫,即Jar文件)或Class目錄(類目錄)中的重複類。
全系統支持(Python實現,安裝Python便可),如LinuxMacWindowsweb

Java開發的一個麻煩的問題是Jar衝突(即多個版本的Jar),或者說重複類。會出NoSuchMethod等的問題,還不見得當時出問題。找出有重複類的Jar,能夠防患未然。正則表達式

用法

  • 經過腳本參數指定Libs目錄,查找目錄下Jar文件,收集Jar文件中Class文件以分析重複類。能夠指定多個Libs目錄。
    注意,只會查找這個目錄下Jar文件,不會查找子目錄下Jar文件。由於Libs目錄通常不會用子目錄再放Jar,這樣也避免把去查找不指望Jar
  • 經過-c選項指定Class目錄,直接收集這個目錄下的Class文件以分析重複類。能夠指定多個Class目錄。
# 查找當前目錄下全部Jar中的重複類 show-duplicate-java-classes # 查找多個指定目錄下全部Jar中的重複類 show-duplicate-java-classes path/to/lib_dir1 /path/to/lib_dir2 # 查找多個指定Class目錄下的重複類。 Class目錄 經過 -c 選項指定 show-duplicate-java-classes -c path/to/class_dir1 -c /path/to/class_dir2 # 查找指定Class目錄和指定目錄下全部Jar中的重複類的Jar show-duplicate-java-classes path/to/lib_dir1 /path/to/lib_dir2 -c path/to/class_dir1 -c path/to/class_dir2 # 幫助信息 $ show-duplicate-java-classes -h Usage: show-duplicate-java-classes [-c class-dir1 [-c class-dir2] ...] [lib-dir1|jar-file1 [lib-dir2|jar-file2] ...] Options: -h, --help show this help message and exit -c CLASS_DIRS, --class-dir=CLASS_DIRS add class dir

JDK開發場景使用說明

Maven做爲構建工程示意過程。spring

對於通常的工程
# 在項目模塊目錄下執行,拷貝依賴Jar到目錄target/dependency下 $ mvn dependency:copy-dependencies -DincludeScope=runtime ... # 檢查重複類 $ show-duplicate-java-classes target/dependency ...
對於Web工程

對於Web工程,即war maven模塊,會打包生成war文件。

# 在war模塊目錄下執行,生成war文件 $ mvn install ... # 解壓war文件,war文件中包含了應用的依賴的Jar文件 $ unzip target/*.war -d target/war ... # 檢查重複類 $ show-duplicate-java-classes -c target/war/WEB-INF/classes target/war/WEB-INF/lib ...

Android開發場景使用說明

Android開發,有重複類在編譯打包時會報[Dex Loader] Unable to execute dex: Multiple dex files define Lorg/foo/xxx/Yyy

但只會給出一個重複類名,若是重複類比較多時,上面打包/報錯/排查會要進行屢次,而Android的打包比較費時,這個過程比較麻煩,但願能夠一次把全部重複類都列出來,一塊兒排查掉。

Gradle做爲構建工程示意過程。

Appbuild.gradle中添加拷貝庫到目錄build/dependencies下。

task copyDependencies(type: Copy) { def dest = new File(buildDir, "dependencies") // clean dir dest.deleteDir() dest.mkdirs() // fill dir with dependencies from configurations.compile into dest }
# 拷貝依賴 $ ./gradlew app:copyDependencies ... # 檢查重複類 $ show-duplicate-java-classes app/build/dependencies ...

示例

$ show-duplicate-java-classes WEB-INF/lib
COOL! No duplicate classes found! ================================================================================ class paths to find: ================================================================================ 1 : WEB-INF/lib/sourceforge.spring.modules.context-2.5.6.SEC02.jar 2 : WEB-INF/lib/misc.htmlparser-0.0.0.jar 3 : WEB-INF/lib/normandy.client-1.0.2.jar ... $ show-duplicate-java-classes -c WEB-INF/classes WEB-INF/lib Found duplicate classes in below class path: 1 (293@2): WEB-INF/lib/sourceforge.spring-2.5.6.SEC02.jar WEB-INF/lib/sourceforge.spring.modules.orm-2.5.6.SEC02.jar 2 (2@3): WEB-INF/lib/servlet-api-3.0-alpha-1.jar WEB-INF/lib/jsp-api-2.1-rev-1.jar WEB-INF/lib/jstl-api-1.2-rev-1.jar 3 (104@2): WEB-INF/lib/commons-io-2.2.jar WEB-INF/lib/jakarta.commons.io-2.0.jar 4 (6@3): WEB-INF/lib/jakarta.commons.logging-1.1.jar WEB-INF/lib/commons-logging-1.1.1.jar WEB-INF/lib/org.slf4j.jcl104-over-slf4j-1.5.6.jar 5 (344@2): WEB-INF/lib/sourceforge.spring-2.5.6.SEC02.jar WEB-INF/lib/sourceforge.spring.modules.context-2.5.6.SEC02.jar ... ================================================================================ Duplicate classes detail info: ================================================================================ 1 (293@2): WEB-INF/lib/sourceforge.spring-2.5.6.SEC02.jar WEB-INF/lib/sourceforge.spring.modules.orm-2.5.6.SEC02.jar 1 org/springframework/orm/toplink/TopLinkTemplate$13.class 2 org/springframework/orm/hibernate3/HibernateTemplate$24.class 3 org/springframework/orm/jpa/vendor/HibernateJpaDialect.class 4 org/springframework/orm/hibernate3/TypeDefinitionBean.class 5 org/springframework/orm/hibernate3/SessionHolder.class ... 2 (2@3): WEB-INF/lib/servlet-api-3.0-alpha-1.jar WEB-INF/lib/jsp-api-2.1-rev-1.jar WEB-INF/lib/jstl-api-1.2-rev-1.jar 1 javax/servlet/ServletException.class 2 javax/servlet/ServletContext.class 3 (104@2): WEB-INF/lib/commons-io-2.2.jar WEB-INF/lib/jakarta.commons.io-2.0.jar 1 org/apache/commons/io/input/ProxyReader.class 2 org/apache/commons/io/output/FileWriterWithEncoding.class 3 org/apache/commons/io/output/TaggedOutputStream.class 4 org/apache/commons/io/filefilter/NotFileFilter.class 5 org/apache/commons/io/filefilter/TrueFileFilter.class ... ... ================================================================================ class paths to find: ================================================================================ 1 : WEB-INF/lib/sourceforge.spring.modules.context-2.5.6.SEC02.jar 2 : WEB-INF/lib/misc.htmlparser-0.0.0.jar 3 : WEB-INF/lib/normandy.client-1.0.2.jar 4 : WEB-INF/lib/xml.xmlgraphics__batik-css-1.7.jar-1.7.jar 5 : WEB-INF/lib/jakarta.ecs-1.4.2.jar ...

貢獻者

tgic提供此腳本。友情貢獻者的連接commandlinefu.cn|微博linux命令行精選

:beer: find-in-jars

在當前目錄下全部jar文件裏,查找類或資源文件。
支持LinuxMacWindowscygwinMSSYS)。

用法

# 在當前目錄下全部`jar`文件裏,查找類或資源文件。 find-in-jars 'log4j\.properties' find-in-jars 'log4j\.xml$' find-in-jars log4j\\.xml$ # 和上面命令同樣,Shell轉義的不一樣寫法而已 find-in-jars 'log4j(\.properties|\.xml)$' # -d選項 指定 查找目錄(覆蓋缺省的當前目錄) find-in-jars 'log4j\.properties$' -d /path/to/find/directory # 支持多個查找目錄 find-in-jars 'log4j\.properties' -d /path/to/find/directory1 -d /path/to/find/directory2 # 幫助信息 $ find-in-jars -h Usage: find-in-jars [OPTION]... PATTERN Find file in the jar files under specified directory(recursive, include subdirectory). The pattern default is *extended* regex. Example: find-in-jars 'log4j\.properties' find-in-jars '^log4j(\.properties|\.xml)$' # search file log4j.properties/log4j.xml at zip root find-in-jars 'log4j\.properties$' -d /path/to/find/directory find-in-jars 'log4j\.properties' -d /path/to/find/dir1 -d /path/to/find/dir2 Options: -d, --dir the directory that find jar files, default is current directory. this option can specify multiply times to find in multiply directory. -E, --extended-regexp PATTERN is an extended regular expression (*default*) -F, --fixed-strings PATTERN is a set of newline-separated strings -G, --basic-regexp PATTERN is a basic regular expression -P, --perl-regexp PATTERN is a Perl regular expression -i, --ignore-case ignore case distinctions -h, --help display this help and exit

注意,Pattern缺省是grep的 擴展正則表達式。

示例

# 在當前目錄下的全部Jar文件中,查找出 log4j.properties文件 $ find-in-jars 'log4j\.properties$' ./hadoop-core-0.20.2-cdh3u3.jar!log4j.properties # 查找出 以Service結尾的類 $ ./find-in-jars 'Service.class$' ./WEB-INF/libs/spring-2.5.6.SEC03.jar!org/springframework/stereotype/Service.class ./rpc-benchmark-0.0.1-SNAPSHOT.jar!com/taobao/rpc/benchmark/service/HelloService.class ...... # 在指定的多個目錄的Jar文件中,查找出 properties文件 $ find-in-jars '\.properties$' -d ../WEB-INF/lib -d ../deploy/lib | grep -v '/pom\.properties$' ../WEB-INF/lib/aspectjtools-1.6.2.jar!org/aspectj/ajdt/ajc/messages.properties ../WEB-INF/lib/aspectjtools-1.6.2.jar!org/aspectj/ajdt/internal/compiler/parser/readableNames.properties ../WEB-INF/lib/aspectjweaver-1.8.8.jar!org/aspectj/weaver/XlintDefault.properties ../WEB-INF/lib/aspectjweaver-1.8.8.jar!org/aspectj/weaver/weaver-messages.properties ../deploy/lib/groovy-all-1.1-rc-1.jar!groovy/ui/InteractiveShell.properties ../deploy/lib/groovy-all-1.1-rc-1.jar!org/codehaus/groovy/tools/shell/CommandAlias.properties ../deploy/lib/httpcore-4.3.3.jar!org/apache/http/version.properties ../deploy/lib/httpmime-4.2.2.jar!org/apache/http/entity/mime/version.properties ../deploy/lib/javax.servlet-api-3.0.1.jar!javax/servlet/LocalStrings_fr.properties ../deploy/lib/javax.servlet-api-3.0.1.jar!javax/servlet/http/LocalStrings_es.properties ......

參考資料

在多個Jar(Zip)文件查找Log4J配置文件的Shell命令行

相關文章
相關標籤/搜索