Merge pull request #1 from alibaba/master

pull upstream
This commit is contained in:
earayu
2018-10-08 17:18:10 +08:00
committed by GitHub
68 changed files with 1458 additions and 275 deletions
+38
View File
@@ -0,0 +1,38 @@
language: generic
sudo: false
jdk:
- openjdk7
- openjdk8
- openjdk9
- openjdk10
- openjdk11
- oraclejdk7
- oraclejdk8
- oraclejdk9
- oraclejdk10
- oraclejdk11
cache:
directories:
- "$HOME/.m2/repository"
- "$HOME/.m2/wrapper"
script:
- ./mvnw clean cobertura:cobertura package -P full -Dsphinx.binUrl=https://github.com/hengyunabc/sphinx-binary/releases/download/v0.4.0.1/sphinx.linux-x86_64
after_success:
- bash <(curl -s https://codecov.io/bash)
notifications:
email: false
deploy:
provider: releases
api_key:
- secure: "V+omzrcAJ/awN3EsDkiELejjInz/rpgPLdyb4uZrcQnqhagbHYE+nY2KcjPEtRBVNkqlh6dxIIsUFvKrs5kxe5EVvI6rLQeZLFMqWUeNfWuhbuQWCV9ZPyQiqXCqNicj+LLHArzQRLx5w5YBvxdzMuXSWo1ZE4wy+c3koprulUSjr6XhNPKyyasq4EXKMXuLCjcvBVPHhXviG59Jbshb2lRHbkxMqYeLhWi/gUOBRbNC1CmcGGAMviFX7HpBOx5fMaVKPR7rzcULw3lXnLhdSwhXJ6ybnsN/osfN8zAx6XZIwvwvVQ12yM8S9eVthnjblFh+WKwOT1AS6hHFXkMTjh1FE5CtUVu+sFbGIngJ4C4O78VzWCKvH/IrIi4p2IkF+fcu8USnm7YZGuyoAwe3O5PqmWBuQV0iCEx0IGo/nPwVzj1+jnz38Go/DP1aVDJZMenysBNxi4l45d3J3CgMPvF00DDQKvxYrkBjdnByANrOisZPjIeUOc7GsWoDLCK9jZtXMID2NM+ehQnDbOJ3BS2Bjg7ojPc0Rw2yJjbzwNqaMiOPXp2ym/5DpaB/l5k2gSi2NCRUFCXhFNRCq9ChFXv+pYJwk0e17sleGvo6tnFDVCR6lFcXrYo/vGC43bL1dT4rY8E6VSRlE0jfoXdFFp4jw3v3a+DqVLGVC9UcTpw="
file_glob: true
file: "packaging/target/*.zip"
skip_cleanup: true
on:
tags: true
+79
View File
@@ -1,5 +1,84 @@
## Issue
Welcome to use [issue tracker](https://github.com/alibaba/arthas/issues) to give us :bowtie::
* feedbacks - what you would like to have;
* usage tips - what usages you have found splendid;
* experiences - how you use Arthas to do **effective** troubleshooting;
## Documentation
Welcome PR to further improve English [documentation](https://github.com/alibaba/arthas/tree/master/site/src/site/sphinx/en).
## Developer
Compilation requires JDK 7 and above since we are `java.lang.management.BufferPoolMXBean` while runtime requires JDK 6.
### Local Installation
Recommend to use [`as-package.sh`](as-package.sh) to package, which will auto-install the latest Arthas to local `~/.arthas` and when debugging, Arthas will auto-load the latest version.
F.Y.I
1. when using [`as.sh`](https://github.com/alibaba/arthas/blob/master/bin/as.sh) to start Arthas, it will get the latest version under `~/.arthas/lib`;
2. when [`as-package.sh`](as-package.sh) packaging, it will get the version from `pom.xml` and suffix it with the current timestamp e.g. `3.0.5.20180917161808`.
You can also use `./mvnw clean package -DskipTests` to package and generate a `zip` under `packaging/target/` but remember when `as.sh` starts, it load the version under `~/.arthas/lib`.
### Start Arthas in specified version
When there are several different version, you can use `--use-version` to specify the version of Arthas to start your debug.
```bash
./as.sh --use-version 3.0.5.20180919185025
```
Tip: you can use `--versions` to list all available versions.
```bash
./as.sh --versions
```
### Debug
There are two stages when booting Arthas:
#### Stage 1
Execute `com.taobao.arthas.core.Arthas`, locate a proper JVM and attach to it.
If you intend to debug this part, you can:
```bash
./as.sh debug pid
```
The JPDA port is `8888`, you can connect to it from remote to debug; if you want to make it suspend after start, you can:
```bash
JPDA_SUSPEND=y ./as.sh debug pid
```
#### Stage 2
After attaching, Arthas agent runs inside the target process. If you want to debug agent, you have to make sure the target process is started in debug mode too. If so, then you can directly import the Arthas source code, and debug it.
### Packaging All
* Arthas is using [Sphinx](http://www.sphinx-doc.org/en/master/) to generate the static site
* `sphinx-maven-plugin` configured in [`site/pom.xml`](https://github.com/alibaba/arthas/tree/master/site)
* `sphinx-maven-plugin` executes by downloading`sphinx-binary/`
* a [bug](https://github.com/rtfd/recommonmark/issues/93) in Sphinx plugin `recommonmark`; we fix it by packaging another [version](https://github.com/hengyunabc/sphinx-binary/releases/tag/v0.4.0.1)
* when packaging the whole project (Packaging All), you need to (Only Unix/Linux/Mac supported):
```bash
./mvnw clean package -DskipTests -P full -Dsphinx.binUrl=https://github.com/hengyunabc/sphinx-binary/releases/download/v0.4.0.1/sphinx.osx-x86_64
```
---
## issue
+30 -23
View File
@@ -2,34 +2,41 @@
![arthas](site/src/site/sphinx/arthas.png)
`Arthas` is an Java Diagnostic tool open sourced by Alibaba.
[![Build Status](https://travis-ci.org/alibaba/arthas.svg?branch=master)](https://travis-ci.org/alibaba/arthas)
[![codecov](https://codecov.io/gh/alibaba/arthas/branch/master/graph/badge.svg)](https://codecov.io/gh/alibaba/arthas)
![maven](https://img.shields.io/maven-central/v/com.taobao.arthas/arthas-packaging.svg)
![license](https://img.shields.io/github/license/alibaba/arthas.svg)
[![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/alibaba/arthas.svg)](http://isitmaintained.com/project/alibaba/arthas "Average time to resolve an issue")
[![Percentage of issues still open](http://isitmaintained.com/badge/open/alibaba/arthas.svg)](http://isitmaintained.com/project/alibaba/arthas "Percentage of issues still open")
Arthas can help developer trouble-shooting production issues for Java applications without modifying your code or restating your server.
`Arthas` is a Java Diagnostic tool open sourced by Alibaba.
[中文说明](README_CN.md)
Arthas help developers in trouble-shooting production issues for Java applications without modifying code or restarting servers.
[中文说明](README_CN.md) (For Chinese Documentation)
### Background
In production system, sometimes the networks is unreachable from local development environment. If you encounter some issues in production system, it is impossible to use IDE to debug the application remotely. More importantly, debugging in production is unacceptable, because it will suspend all the threads, which leads to business unavailability.
Often times, the production system network is inaccessible from local development environment. If issues are encountered in production systems, it is impossible to use IDE to debug the application remotely. More importantly, debugging in production environment is unacceptable, as it will suspend all the threads, which leads to blocking of business services.
Some may think of reproducing the same issue on the test/staging environment, however, some tricky issue either can hardly be reproduced on a different environment, or even disappeared once restarted.
Developers could always try to reproduce the same issue on the test/staging environment. However, this is tricky as some issues cannot be be reproduced easily on a different environment, or even disappear once restarted.
Thinking of adding some logs to your code? You have to go through test, staging, and then on to production. Time is money! That is a lot inefficient! Besides, the issue may not be reproducible once restart your JVM, as described above.
And if you're thinking of adding some logs to your code to help trouble-shoot the issue, you will have to go through the following lifecycle; test, staging, and then to production. Time is money! This approach is inefficient! Besides, the issue may not be reproducible once the JVM is restarted, as described above.
Arthas is born to solve these issues. You can trouble-shoot your production issue on-the-fly. No JVM restart, no additional code changes. Arthas works as an observer, which will never suspend your existing threads.
Arthas was built to solve these issues. A developer can trouble-shoot your production issues on-the-fly. No JVM restart, no additional code changes. Arthas works as an observer, which will never suspend your existing threads.
### Key features
* Check whether a class is loaded? And whether is class loaded from? (Useful for trouble-shooting jar file conflicts)
* Check whether a class is loaded? Or where the class is loaded from? (Useful for trouble-shooting jar file conflicts)
* Decompile a class to ensure the code is running as expected.
* View classloader statistics, e.g. how may classloaders are there? how many class is loaded per classloader? What is the classloader hierarchy? Is there possible classloader leaks?
* View classloader statistics, e.g. the number of classloaders, the number of classes loaded per classloader, the classloader hierarchy, possible classloader leaks, etc.
* View the method invocation details, e.g. method parameter, return object, thrown exception, and etc.
* Check the stack trace of specified method invocation. This is useful when you would like to know who is calling your method?
* Check the stack trace of specified method invocation. This is useful when a developers wants to know the caller of the said method.
* Trace the method invocation to find slow sub-invocations.
* Monitor method invcation statistics, e.g. qps, rt, success rate and etc.
* Monitoring your system metrics, thread states and cpu usage, gc statistics, and etc.
* Support command line interactive mode, with auto completed feature enabled.
* Support telnet and websocket, which enables both local and remote diagnostics with command line and browsers.
* Monitor method invocation statistics, e.g. qps, rt, success rate and etc.
* Monitor system metrics, thread states and cpu usage, gc statistics, and etc.
* Supports command line interactive mode, with auto-complete feature enabled.
* Supports telnet and websocket, which enables both local and remote diagnostics with command line and browsers.
### Quick start
@@ -49,10 +56,10 @@ Start Arthas:
#### Windows
1. Click [here](http://search.maven.org/classic/#search%7Cga%7C1%7Cg%3A%22com.taobao.arthas%22%20AND%20a%3A%22arthas-packaging%22) to Download the latest binary releases.
1. Click [![Arthas](https://img.shields.io/maven-central/v/com.taobao.arthas/arthas-packaging.svg "Arthas")](http://search.maven.org/classic/#search%7Cga%7C1%7Cg%3A%22com.taobao.arthas%22%20AND%20a%3A%22arthas-packaging%22) to download the latest binary releases of `bin.zip`.
2. Unzip the file.
3. Go to the bin directory
4. run the following command `as.bat $PID`
4. Run the following command `as.bat $PID`
### Documentation
@@ -71,13 +78,13 @@ English version is on the way, if you would like to contribute, please leave a m
#### Dashboard
* https://alibaba.github.io/arthas/dashboard
* https://alibaba.github.io/arthas/en/dashboard
![dashboard](site/src/site/sphinx/_static/dashboard.png)
#### Thread
See who is eating your cpu (ranked by top cpu usage) and what is going on there in one glance:
See what is eating your cpu (ranked by top cpu usage) and what is going on there in one glance:
```
$ thread -n 3
@@ -218,7 +225,7 @@ ts=2018-09-18 10:11:45;thread_name=http-bio-8080-exec-10;id=d9;is_daemon=true;pr
#### Trace
See who is slowing down your method invocation with trace command:
See what is slowing down your method invocation with trace command:
![trace](site/src/site/sphinx/_static/trace.png)
@@ -259,7 +266,7 @@ Affect(class-cnt:1 , method-cnt:1) cost in 109 ms.
#### Time Tunnel(tt)
Recording method invocation data, so that you can check the method invacation parameters, returned value and thrown exception later. It works as if you could come back and replay the past method invacation via time tunnel.
Record method invocation data, so that you can check the method invacation parameters, returned value and thrown exception later. It works as if you could come back and replay the past method invocation via time tunnel.
```
$ tt -t org.apache.dubbo.demo.provider.DemoServiceImpl sayHello
@@ -297,7 +304,7 @@ $ classloader
#### Web Console
* https://alibaba.github.io/arthas/web-console
* https://alibaba.github.io/arthas/en/web-console
![web console](site/src/site/sphinx/_static/web-console-local.png)
@@ -305,6 +312,6 @@ $ classloader
### Credit
* [greys-anatomy](https://github.com/oldmanpushcart/greys-anatomy): The Arthas code base has derived from Greys, we thank for the excellent work done by Greys.
* [termd](https://github.com/termd/termd): Arthas's termnial implementation is based on termd, an open source library for writing terminal applications in Java.
* [termd](https://github.com/termd/termd): Arthas's terminal implementation is based on termd, an open source library for writing terminal applications in Java.
* [crash](https://github.com/crashub/crash): Arthas's text based user interface rendering is based on codes extracted from [here](https://github.com/crashub/crash/tree/1.3.2/shell)
* [cli](https://github.com/eclipse-vertx/vert.x/tree/master/src/main/java/io/vertx/core/cli): Arthas's command line interface implementation is based on cli, open sourced by vert.x
* [cli](https://github.com/eclipse-vertx/vert.x/tree/master/src/main/java/io/vertx/core/cli): Arthas's command line interface implementation is based on cli, open sourced by vert.x
+13 -2
View File
@@ -4,6 +4,13 @@
![arthas](site/src/site/sphinx/arthas.png)
[![Build Status](https://travis-ci.org/alibaba/arthas.svg?branch=master)](https://travis-ci.org/alibaba/arthas)
[![codecov](https://codecov.io/gh/alibaba/arthas/branch/master/graph/badge.svg)](https://codecov.io/gh/alibaba/arthas)
![maven](https://img.shields.io/maven-central/v/com.taobao.arthas/arthas-packaging.svg)
![license](https://img.shields.io/github/license/alibaba/arthas.svg)
[![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/alibaba/arthas.svg)](http://isitmaintained.com/project/alibaba/arthas "Average time to resolve an issue")
[![Percentage of issues still open](http://isitmaintained.com/badge/open/alibaba/arthas.svg)](http://isitmaintained.com/project/alibaba/arthas "Percentage of issues still open")
English version goes [here](README.md).
`Arthas` 是Alibaba开源的Java诊断工具,深受开发者喜爱。
@@ -40,7 +47,7 @@ curl -L https://alibaba.github.io/arthas/install.sh | sh
#### Windows
1. 点击 [这里](http://search.maven.org/classic/#search%7Cga%7C1%7Cg%3A%22com.taobao.arthas%22%20AND%20a%3A%22arthas-packaging%22) 下载最新的Arthas zip包
1. 点击 [![Arthas](https://img.shields.io/maven-central/v/com.taobao.arthas/arthas-packaging.svg "Arthas")](http://search.maven.org/classic/#search%7Cga%7C1%7Cg%3A%22com.taobao.arthas%22%20AND%20a%3A%22arthas-packaging%22) 下载最新的Arthas `bin.zip`包
2. 解压缩zip包.
3. 进入bin目录
4. 执行以下命令 `as.bat $PID`
@@ -302,4 +309,8 @@ $ classloader
* [greys-anatomy](https://github.com/oldmanpushcart/greys-anatomy): Arthas代码基于Greys二次开发而来,非常感谢Greys之前所有的工作,以及Greys原作者对Arthas提出的意见和建议!
* [termd](https://github.com/termd/termd): Arthas的命令行实现基于termd开发,是一款优秀的命令行程序开发框架,感谢termd提供了优秀的框架。
* [crash](https://github.com/crashub/crash): Arthas的文本渲染功能基于crash中的文本渲染功能开发,可以从[这里](https://github.com/crashub/crash/tree/1.3.2/shell)看到源码,感谢crash在这方面所做的优秀工作。
* [cli](https://github.com/eclipse-vertx/vert.x/tree/master/src/main/java/io/vertx/core/cli): Arthas的命令行界面基于vert.x提供的cli库进行开发,感谢vert.x在这方面做的优秀工作。
* [cli](https://github.com/eclipse-vertx/vert.x/tree/master/src/main/java/io/vertx/core/cli): Arthas的命令行界面基于vert.x提供的cli库进行开发,感谢vert.x在这方面做的优秀工作。
### 仓库镜像
* [码云Arthas](https://gitee.com/arthas/arthas)
@@ -35,9 +35,9 @@ public class AgentBootstrap {
static {
try {
File log = new File(System.getProperty("user.home") + File.separator + "logs" + File.separator
+ ".arthas" + File.separator + "arthas.log");
+ "arthas" + File.separator + "arthas.log");
if (!log.exists()) {
log.getParentFile().mkdir();
log.getParentFile().mkdirs();
log.createNewFile();
}
ps = new PrintStream(new FileOutputStream(log, true));
@@ -146,6 +146,13 @@ public class AgentBootstrap {
}
private static void bind(Instrumentation inst, ClassLoader agentLoader, String args) throws Throwable {
/**
* <pre>
* Configure configure = Configure.toConfigure(args);
* int javaPid = configure.getJavaPid();
* ArthasBootstrap bootstrap = ArthasBootstrap.getInstance(javaPid, inst);
* </pre>
*/
Class<?> classOfConfigure = agentLoader.loadClass(ARTHAS_CONFIGURE);
Object configure = classOfConfigure.getMethod(TO_CONFIGURE, String.class).invoke(null, args);
int javaPid = (Integer) classOfConfigure.getMethod(GET_JAVA_PID).invoke(configure);
+3 -2
View File
@@ -4,7 +4,8 @@ DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
get_local_maven_project_version()
{
$DIR/mvnw org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate -Dexpression=project.version | grep -e '^[^\[]' | cut -b 1-5
$DIR/mvnw org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate \
-Dexpression=project.version -f $DIR/pom.xml | grep -e '^[^\[]' | cut -b 1-5
}
CUR_VERSION=$(get_local_maven_project_version)
@@ -40,7 +41,7 @@ rm -r $DIR/core/src/main/resources/com/taobao/arthas/core/res/version
# install to local
mkdir -p ${NEWEST_ARTHAS_LIB_HOME}
unzip ${packaging_bin_path} -d ${NEWEST_ARTHAS_LIB_HOME}/
unzip ${packaging_bin_path} -d "${NEWEST_ARTHAS_LIB_HOME}/"
# print ~/.arthas directory size
arthas_dir_size="$(du -hs ${HOME}/.arthas | cut -f1)"
+3 -2
View File
@@ -76,7 +76,7 @@ default()
check_permission()
{
[ ! -w ${HOME} ] \
&& exit_on_err 1 "permission denied, ${HOME} is not writeable."
&& exit_on_err 1 "permission denied, ${HOME} is not writable."
}
@@ -179,7 +179,8 @@ update_if_necessary()
|| return 1
# unzip arthas lib
unzip ${temp_target_lib_zip} -d ${temp_target_lib_dir} || (rm -rf ${temp_target_lib_dir} && return 1)
unzip ${temp_target_lib_zip} -d ${temp_target_lib_dir} || (rm -rf ${temp_target_lib_dir} \
${ARTHAS_LIB_DIR}/${update_version} && return 1)
# rename
mv ${temp_target_lib_dir} ${target_lib_dir} || return 1
@@ -14,6 +14,7 @@ import com.taobao.text.ui.TableElement;
import com.taobao.text.util.RenderUtil;
import java.lang.management.*;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
@@ -74,12 +75,27 @@ public class JvmCommand extends AnnotatedCommand {
table.row("", "");
table.row(true, label("THREAD").style(Decoration.bold.bold()));
drawThreadTable(table);
table.row("", "");
table.row(true, label("FILE-DESCRIPTOR").style(Decoration.bold.bold()));
drawFileDescriptorTable(table);
process.write(RenderUtil.render(table, process.width()));
process.write(affect.toString()).write("\n");
process.end();
}
private void drawFileDescriptorTable(TableElement table) {
table.row("MAX-FILE-DESCRIPTOR-COUNT", "" + invokeFileDescriptor(operatingSystemMXBean, "getMaxFileDescriptorCount"))
.row("OPEN-FILE-DESCRIPTOR-COUNT", "" + invokeFileDescriptor(operatingSystemMXBean, "getOpenFileDescriptorCount"));
}
private long invokeFileDescriptor(OperatingSystemMXBean os, String name) {
try {
final Method method = os.getClass().getDeclaredMethod(name);
method.setAccessible(true);
return (Long) method.invoke(os);
} catch (Exception e) {
return -1;
}
}
private String toCol(Collection<String> strings) {
final StringBuilder colSB = new StringBuilder();
if (strings.isEmpty()) {
@@ -0,0 +1,32 @@
package com.taobao.arthas.core.util;
import java.lang.management.ManagementFactory;
/**
*
* @author hengyunabc 2018-09-30
*
*/
public class ApplicationUtils {
private static String PID = "-1";
static {
// https://stackoverflow.com/a/7690178
String jvmName = ManagementFactory.getRuntimeMXBean().getName();
int index = jvmName.indexOf('@');
if (index > 0) {
try {
PID = Long.toString(Long.parseLong(jvmName.substring(0, index)));
} catch (Throwable e) {
// ignore
}
}
}
public static String getPid() {
return PID;
}
}
@@ -1,7 +1,6 @@
package com.taobao.arthas.core.util;
import java.io.File;
import java.lang.management.ManagementFactory;
import com.taobao.arthas.core.view.Ansi;
@@ -46,7 +45,7 @@ public interface Constants {
/**
* 当前进程PID
*/
String PID = ManagementFactory.getRuntimeMXBean().getName().split("@")[0];
String PID = ApplicationUtils.getPid();
/**
* 缓存目录
@@ -5,55 +5,52 @@ import java.net.NetworkInterface;
import java.util.Enumeration;
/**
* @author weipeng2k 2015年1月30日 下午3:06:47
* @author weipeng2k 2015-01-30 15:06:47
*/
public class IPUtils {
private static final String WINDOWS = "windows";
private static final String OS_NAME = "os.name";
/**
* 判断当前操作是否Windows.
*
* @return true---是Windows操作系统
* check: whether current operating system is windows
*
* @return true---is windows
*/
public static boolean isWindowsOS() {
boolean isWindowsOS = false;
String osName = System.getProperty("os.name");
if (osName.toLowerCase().indexOf("windows") > -1) {
isWindowsOS = true;
}
return isWindowsOS;
String osName = System.getProperty(OS_NAME);
return osName.toLowerCase().contains(WINDOWS);
}
/**
* 获取本机IP地址,并自动区分Windows还是Linux操作系统
*
* get IP address, automatically distinguish the operating system.(windows or linux)
*
* @return String
*/
public static String getLocalIP() {
String sIP = null;
InetAddress ip = null;
try {
if (isWindowsOS()) {
ip = InetAddress.getLocalHost();
} else {
// 如果是回环地址则扫描所有的NetWorkInterface
//scan all NetWorkInterfaces if it's loopback address
if (!InetAddress.getLocalHost().isLoopbackAddress()) {
ip = InetAddress.getLocalHost();
} else {
boolean bFindIP = false;
Enumeration<NetworkInterface> netInterfaces = (Enumeration<NetworkInterface>) NetworkInterface.getNetworkInterfaces();
Enumeration<NetworkInterface> netInterfaces = NetworkInterface.getNetworkInterfaces();
while (netInterfaces.hasMoreElements()) {
if (bFindIP) {
break;
}
NetworkInterface ni = (NetworkInterface) netInterfaces.nextElement();
NetworkInterface ni = netInterfaces.nextElement();
// ----------特定情况,可以考虑用ni.getName判断
// 遍历所有ip
// iterator all IPs
Enumeration<InetAddress> ips = ni.getInetAddresses();
while (ips.hasMoreElements()) {
ip = (InetAddress) ips.nextElement();
// 127.开头的都是lookback地址
if (ip.isSiteLocalAddress() && !ip.isLoopbackAddress()
&& ip.getHostAddress().indexOf(":") == -1) {
ip = ips.nextElement();
// IP starts with 127. is loopback address
if (ip.isSiteLocalAddress() && !ip.isLoopbackAddress() && !ip.getHostAddress().contains(":")) {
bFindIP = true;
break;
}
@@ -65,13 +62,7 @@ public class IPUtils {
} catch (Exception e) {
}
if (ip != null) {
sIP = ip.getHostAddress();
}
return sIP;
return ip == null ? null : ip.getHostAddress();
}
public static void main(String[] args) {
System.out.println(getLocalIP());
}
}
@@ -1,20 +1,27 @@
package com.taobao.arthas.core.util;
import java.util.List;
import com.taobao.arthas.core.shell.cli.CliToken;
/**
* tokens处理的辅助类
* tokenizer helper
*
* @author gehui 2017年7月27日 上午11:39:56
* @author gehui 2017-07-27 11:39:56
*/
public class TokenUtils {
/**
* find the first text token
* @param tokens
* @return
*/
public static CliToken findFirstTextToken(List<CliToken> tokens) {
if(tokens==null || tokens.isEmpty()){
return null;
}
CliToken first = null;
for (CliToken token : tokens) {
if (token.isText()) {
if (token!=null && token.isText()) {
first = token;
break;
}
@@ -22,20 +29,37 @@ public class TokenUtils {
return first;
}
/**
* find the last text token
* @param tokens
* @return
*/
public static CliToken findLastTextToken(List<CliToken> tokens) {
for (int i = tokens.size() - 1; i > 0; i--) {
if(tokens==null || tokens.isEmpty()){
return null;
}
//#165
for (int i = tokens.size() - 1; i >= 0; i--) {
CliToken token = tokens.get(i);
if (token.isText()) {
if (token!=null && token.isText()) {
return token;
}
}
return null;
}
/**
* find the second text token's text
* @param tokens
* @return
*/
public static String findSecondTokenText(List<CliToken> tokens) {
if(tokens==null || tokens.isEmpty()){
return null;
}
boolean first = true;
for (CliToken token : tokens) {
if (token.isText()) {
if (token!=null && token.isText()) {
if (first) {
first = false;
} else {
@@ -5,6 +5,11 @@ package com.taobao.arthas.core.util.matcher;
*/
public class FalseMatcher<T> implements Matcher<T> {
/**
* always return false
* @param target
* @return true/false
*/
@Override
public boolean matching(T target) {
return false;
@@ -1,7 +1,7 @@
package com.taobao.arthas.core.util.matcher;
/**
* 正则表达式匹配
* regex matcher
* @author ralf0131 2017-01-06 13:16.
*/
public class RegexMatcher implements Matcher<String> {
@@ -5,6 +5,11 @@ package com.taobao.arthas.core.util.matcher;
*/
public final class TrueMatcher<T> implements Matcher<T> {
/**
* always return true
* @param target
* @return
*/
@Override
public boolean matching(T target) {
return true;
@@ -1,13 +1,19 @@
package com.taobao.arthas.core.util.matcher;
/**
* 通配符表达式匹配
* wildcard matcher
* @author ralf0131 2017-01-06 13:17.
*/
public class WildcardMatcher implements Matcher<String> {
private final String pattern;
private static final Character ASTERISK = '*';
private static final Character QUESTION_MARK = '?';
private static final Character ESCAPE = '\\';
public WildcardMatcher(String pattern) {
this.pattern = pattern;
}
@@ -21,51 +27,61 @@ public class WildcardMatcher implements Matcher<String> {
/**
* Internal matching recursive function.
*/
private boolean match(String string, String pattern, int stringStartNdx, int patternStartNdx) {
private boolean match(String target, String pattern, int stringStartNdx, int patternStartNdx) {
//#135
if(target==null || pattern==null){
return false;
}
int pNdx = patternStartNdx;
int sNdx = stringStartNdx;
int pLen = pattern.length();
if (pLen == 1) {
if (pattern.charAt(0) == '*') { // speed-up
// speed-up
if (pattern.charAt(0) == ASTERISK) {
return true;
}
}
int sLen = string.length();
int sLen = target.length();
boolean nextIsNotWildcard = false;
while (true) {
// check if end of string and/or pattern occurred
if ((sNdx >= sLen)) { // end of string still may have pending '*' callback pattern
while ((pNdx < pLen) && (pattern.charAt(pNdx) == '*')) {
if ((sNdx >= sLen)) {
// end of string still may have pending '*' callback pattern
while ((pNdx < pLen) && (pattern.charAt(pNdx) == ASTERISK)) {
pNdx++;
}
return pNdx >= pLen;
}
if (pNdx >= pLen) { // end of pattern, but not end of the string
// end of pattern, but not end of the string
if (pNdx >= pLen) {
return false;
}
char p = pattern.charAt(pNdx); // pattern char
// pattern char
char p = pattern.charAt(pNdx);
// perform logic
if (!nextIsNotWildcard) {
if (p == '\\') {
if (p == ESCAPE) {
pNdx++;
nextIsNotWildcard = true;
continue;
}
if (p == '?') {
if (p == QUESTION_MARK) {
sNdx++;
pNdx++;
continue;
}
if (p == '*') {
char pnext = 0; // next pattern char
if (p == ASTERISK) {
// next pattern char
char pnext = 0;
if (pNdx + 1 < pLen) {
pnext = pattern.charAt(pNdx + 1);
}
if (pnext == '*') { // double '*' have the same effect as one '*'
// double '*' have the same effect as one '*'
if (pnext == ASTERISK) {
pNdx++;
continue;
}
@@ -74,8 +90,8 @@ public class WildcardMatcher implements Matcher<String> {
// find recursively if there is any substring from the end of the
// line that matches the rest of the pattern !!!
for (i = string.length(); i >= sNdx; i--) {
if (match(string, pattern, i, pNdx)) {
for (i = target.length(); i >= sNdx; i--) {
if (match(target, pattern, i, pNdx)) {
return true;
}
}
@@ -86,7 +102,7 @@ public class WildcardMatcher implements Matcher<String> {
}
// check if pattern char and string char are equals
if (p != string.charAt(sNdx)) {
if (p != target.charAt(sNdx)) {
return false;
}
@@ -0,0 +1,126 @@
package com.taobao.arthas.core.util;
import com.taobao.arthas.core.shell.cli.CliToken;
import com.taobao.arthas.core.shell.cli.impl.CliTokenImpl;
import org.junit.Assert;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* @author earayu
*/
public class TokenUtilsTest {
private List<CliToken> newCliTokenList(CliToken ... tokens){
List<CliToken> cliTokens = new ArrayList<CliToken>();
if(tokens!=null) {
Collections.addAll(cliTokens, tokens);
}
return cliTokens;
}
@Test
public void testFindFirstTextToken(){
CliToken textCliToken = new CliTokenImpl(true,"textCliToken");
CliToken nonTextCliToken = new CliTokenImpl(false,"nonTextCliToken");
//null list
Assert.assertEquals(null, TokenUtils.findFirstTextToken(null));
//empty list
Assert.assertEquals(null, TokenUtils.findFirstTextToken(new ArrayList<CliToken>()));
//list with null value
Assert.assertEquals(null,
TokenUtils.findFirstTextToken(newCliTokenList(new CliToken[]{null})));
Assert.assertEquals(textCliToken,
TokenUtils.findFirstTextToken(newCliTokenList(new CliToken[]{null, textCliToken})));
Assert.assertEquals(textCliToken,
TokenUtils.findFirstTextToken(newCliTokenList(new CliToken[]{null, nonTextCliToken, textCliToken})));
Assert.assertEquals(textCliToken,
TokenUtils.findFirstTextToken(newCliTokenList(new CliToken[]{nonTextCliToken, null, textCliToken})));
//list with normal inputs
Assert.assertEquals(textCliToken,
TokenUtils.findFirstTextToken(newCliTokenList(new CliToken[]{textCliToken})));
Assert.assertEquals(textCliToken,
TokenUtils.findFirstTextToken(newCliTokenList(new CliToken[]{nonTextCliToken, textCliToken})));
Assert.assertEquals(textCliToken,
TokenUtils.findFirstTextToken(newCliTokenList(new CliToken[]{textCliToken, nonTextCliToken})));
}
@Test
public void testFindLastTextToken(){
CliToken textCliToken = new CliTokenImpl(true,"textCliToken");
CliToken nonTextCliToken = new CliTokenImpl(false,"nonTextCliToken");
//null list
Assert.assertEquals(null, TokenUtils.findLastTextToken(null));
//empty list
Assert.assertEquals(null, TokenUtils.findLastTextToken(new ArrayList<CliToken>()));
//list with null value
Assert.assertEquals(null,
TokenUtils.findLastTextToken(newCliTokenList(new CliToken[]{null})));
Assert.assertEquals(textCliToken,
TokenUtils.findLastTextToken(newCliTokenList(new CliToken[]{null, textCliToken})));
Assert.assertEquals(textCliToken,
TokenUtils.findLastTextToken(newCliTokenList(new CliToken[]{null, nonTextCliToken, textCliToken})));
Assert.assertEquals(textCliToken,
TokenUtils.findLastTextToken(newCliTokenList(new CliToken[]{nonTextCliToken, null, textCliToken})));
Assert.assertEquals(textCliToken,
TokenUtils.findLastTextToken(newCliTokenList(new CliToken[]{textCliToken, null, nonTextCliToken})));
//list with normal inputs
Assert.assertEquals(textCliToken,
TokenUtils.findLastTextToken(newCliTokenList(new CliToken[]{textCliToken})));
Assert.assertEquals(null,
TokenUtils.findLastTextToken(newCliTokenList(new CliToken[]{nonTextCliToken})));
Assert.assertEquals(textCliToken,
TokenUtils.findLastTextToken(newCliTokenList(new CliToken[]{nonTextCliToken, textCliToken})));
Assert.assertEquals(textCliToken,
TokenUtils.findLastTextToken(newCliTokenList(new CliToken[]{textCliToken, nonTextCliToken})));
}
@Test
public void testFindSecondTextToken(){
CliToken textCliToken = new CliTokenImpl(true,"textCliToken");
CliToken nonTextCliToken = new CliTokenImpl(false,"nonTextCliToken");
//null list
Assert.assertEquals(null, TokenUtils.findSecondTokenText(null));
//empty list
Assert.assertEquals(null, TokenUtils.findSecondTokenText(new ArrayList<CliToken>()));
//list with null value
Assert.assertEquals(null,
TokenUtils.findSecondTokenText(newCliTokenList(new CliToken[]{null})));
Assert.assertEquals(null,
TokenUtils.findSecondTokenText(newCliTokenList(new CliToken[]{null, textCliToken})));
Assert.assertEquals(null,
TokenUtils.findSecondTokenText(newCliTokenList(new CliToken[]{null, nonTextCliToken, textCliToken})));
Assert.assertEquals(textCliToken.value(),
TokenUtils.findSecondTokenText(newCliTokenList(new CliToken[]{null, nonTextCliToken, textCliToken, textCliToken})));
//list with normal inputs
Assert.assertEquals(null,
TokenUtils.findSecondTokenText(newCliTokenList(new CliToken[]{textCliToken})));
Assert.assertEquals(null,
TokenUtils.findSecondTokenText(newCliTokenList(new CliToken[]{nonTextCliToken})));
Assert.assertEquals(null,
TokenUtils.findSecondTokenText(newCliTokenList(new CliToken[]{nonTextCliToken, textCliToken})));
Assert.assertEquals(textCliToken.value(),
TokenUtils.findSecondTokenText(newCliTokenList(new CliToken[]{textCliToken, nonTextCliToken, textCliToken})));
}
}
@@ -0,0 +1,117 @@
package com.taobao.arthas.core.util;
import org.junit.Test;
import java.io.Serializable;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
public class TypeRenderUtilsTest {
public class TestClass implements Serializable {
private int testField;
public char anotherTestField;
public int testMethod(int i, boolean b) {
return 0;
}
public void anotherTestMethod() throws NullPointerException {
}
}
@Test
public void testDrawInterface() {
assertThat(TypeRenderUtils.drawInterface(String.class), is(equalTo("java.io.Serializable,java.lang.Comparable,java.lang.CharSequence")));
assertThat(TypeRenderUtils.drawInterface(TestClass.class), is(equalTo("java.io.Serializable")));
assertThat(TypeRenderUtils.drawInterface(Serializable.class), is(equalTo("")));
}
@Test
public void testDrawParametersForMethod() throws NoSuchMethodException {
Class[] classesOfParameters = new Class[2];
classesOfParameters[0] = int.class;
classesOfParameters[1] = boolean.class;
assertThat(TypeRenderUtils.drawParameters(TestClass.class.getMethod("testMethod", classesOfParameters)), is(equalTo("int\nboolean")));
assertThat(TypeRenderUtils.drawParameters(TestClass.class.getMethod("anotherTestMethod")), is(equalTo("")));
assertThat(TypeRenderUtils.drawParameters(String.class.getMethod("charAt", int.class)), is(equalTo("int")));
assertThat(TypeRenderUtils.drawParameters(String.class.getMethod("isEmpty")), is(equalTo("")));
}
@Test(expected = NoSuchMethodException.class)
public void testDrawParametersForMethodThrowsException() throws NoSuchMethodException {
assertThat(TypeRenderUtils.drawParameters(TestClass.class.getMethod("method")), is(equalTo("")));
}
@Test
public void testDrawParametersForConstructor() throws NoSuchMethodException {
Class[] classesOfParameters = new Class[3];
classesOfParameters[0] = char[].class;
classesOfParameters[1] = int.class;
classesOfParameters[2] = int.class;
assertThat(TypeRenderUtils.drawParameters(String.class.getConstructor(classesOfParameters)), is(equalTo("[]\nint\nint")));
assertThat(TypeRenderUtils.drawParameters(String.class.getConstructor()), is(equalTo("")));
}
@Test(expected = NoSuchMethodException.class)
public void testDrawParametersForConstructorThrowsException() throws NoSuchMethodException {
assertThat(TypeRenderUtils.drawParameters(TestClass.class.getConstructor()), is(equalTo("")));
}
@Test
public void testDrawReturn() throws NoSuchMethodException {
Class[] classesOfParameters = new Class[2];
classesOfParameters[0] = int.class;
classesOfParameters[1] = boolean.class;
assertThat(TypeRenderUtils.drawReturn(TestClass.class.getMethod("testMethod", classesOfParameters)), is(equalTo("int")));
assertThat(TypeRenderUtils.drawReturn(TestClass.class.getMethod("anotherTestMethod")), is(equalTo("void")));
assertThat(TypeRenderUtils.drawReturn(String.class.getMethod("isEmpty")), is(equalTo("boolean")));
}
@Test(expected = NoSuchMethodException.class)
public void testDrawReturnThrowsException() throws NoSuchMethodException {
assertThat(TypeRenderUtils.drawReturn(TestClass.class.getMethod("method")), is(equalTo("")));
}
@Test
public void testDrawExceptionsForMethod() throws NoSuchMethodException {
Class[] classesOfParameters = new Class[2];
classesOfParameters[0] = int.class;
classesOfParameters[1] = boolean.class;
assertThat(TypeRenderUtils.drawExceptions(TestClass.class.getMethod("testMethod", classesOfParameters)), is(equalTo("")));
assertThat(TypeRenderUtils.drawExceptions(TestClass.class.getMethod("anotherTestMethod")), is(equalTo("java.lang.NullPointerException")));
assertThat(TypeRenderUtils.drawExceptions(String.class.getMethod("getBytes", String.class)), is(equalTo("java.io.UnsupportedEncodingException")));
}
@Test(expected = NoSuchMethodException.class)
public void testDrawExceptionsForMethodThrowsException() throws NoSuchMethodException {
assertThat(TypeRenderUtils.drawExceptions(TestClass.class.getMethod("method")), is(equalTo("")));
}
@Test
public void testDrawExceptionsForConstructor() throws NoSuchMethodException {
Class[] classesOfConstructorParameters = new Class[2];
classesOfConstructorParameters[0] = byte[].class;
classesOfConstructorParameters[1] = String.class;
assertThat(TypeRenderUtils.drawExceptions(String.class.getConstructor()), is(equalTo("")));
assertThat(TypeRenderUtils.drawExceptions(String.class.getConstructor(classesOfConstructorParameters)), is(equalTo("java.io.UnsupportedEncodingException")));
}
@Test(expected = NoSuchMethodException.class)
public void testDrawExceptionsForConstructorThrowsException() throws NoSuchMethodException {
assertThat(TypeRenderUtils.drawExceptions(TestClass.class.getConstructor()), is(equalTo("")));
}
}
@@ -0,0 +1,20 @@
package com.taobao.arthas.core.util.matcher;
import org.junit.Assert;
import org.junit.Test;
/**
* @author earayu
*/
public class EqualsMatcherTest {
@Test
public void testMatching(){
Assert.assertTrue(new EqualsMatcher<String>(null).matching(null));
Assert.assertTrue(new EqualsMatcher<String>("").matching(""));
Assert.assertTrue(new EqualsMatcher<String>("foobar").matching("foobar"));
Assert.assertFalse(new EqualsMatcher<String>("").matching(null));
Assert.assertFalse(new EqualsMatcher<String>("abc").matching("def"));
}
}
@@ -0,0 +1,19 @@
package com.taobao.arthas.core.util.matcher;
import org.junit.Assert;
import org.junit.Test;
/**
* @author earayu
*/
public class FalseMatcherTest {
@Test
public void testMatching(){
Assert.assertFalse(new FalseMatcher<String>().matching(null));
Assert.assertFalse(new FalseMatcher<Integer>().matching(1));
Assert.assertFalse(new FalseMatcher<String>().matching(""));
Assert.assertFalse(new FalseMatcher<String>().matching("foobar"));
}
}
@@ -0,0 +1,63 @@
package com.taobao.arthas.core.util.matcher;
import org.junit.Assert;
import org.junit.Test;
/**
* @author earayu
*/
public class RegexMatcherTest {
@Test
public void testMatchingWithNullInputs(){
Assert.assertFalse(new RegexMatcher(null).matching(null));
Assert.assertFalse(new RegexMatcher(null).matching("foobar"));
Assert.assertFalse(new RegexMatcher("foobar").matching(null));
Assert.assertTrue(new RegexMatcher("foobar").matching("foobar"));
}
/**
* test regux with . | * + ? \s \S \w \W and so on...
*/
@Test
public void testMatchingWithRegularGrammar(){
Assert.assertTrue(new RegexMatcher("foo?").matching("fo"));
Assert.assertTrue(new RegexMatcher("foo?").matching("foo"));
Assert.assertTrue(new RegexMatcher("foo.").matching("fooo"));
Assert.assertTrue(new RegexMatcher("foo*").matching("fooooo"));
Assert.assertTrue(new RegexMatcher("foo.*").matching("foobarbarbar"));
Assert.assertFalse(new RegexMatcher("foo+").matching("fo"));
Assert.assertTrue(new RegexMatcher("foo+").matching("fooooo"));
Assert.assertTrue(new RegexMatcher("foo\\s").matching("foo "));
Assert.assertFalse(new RegexMatcher("foo\\S").matching("foo "));
Assert.assertTrue(new RegexMatcher("foo\\w").matching("fooo"));
Assert.assertTrue(new RegexMatcher("foo\\W").matching("foo "));
Assert.assertFalse(new RegexMatcher("foo\\W").matching("fooo"));
Assert.assertTrue(new RegexMatcher("foo[1234]").matching("foo1"));
Assert.assertFalse(new RegexMatcher("foo[1234]").matching("foo5"));
Assert.assertTrue(new RegexMatcher("foo\\\\").matching("foo\\"));
Assert.assertTrue(new RegexMatcher("foo\\d").matching("foo5"));
Assert.assertTrue(new RegexMatcher("fo{1,3}").matching("fo"));
Assert.assertFalse(new RegexMatcher("fo{1,3}").matching("foooo"));
}
@Test
public void testMatchingComplexRegex(){
String ipAddressPattern = "((2[0-4]\\d|25[0-5]|[01]?\\d\\d?)\\.){3}(2[0-4]\\d|25[0-5]|[01]?\\d\\d?)";
Assert.assertTrue(new RegexMatcher(ipAddressPattern).matching("1.1.1.1"));
Assert.assertFalse(new RegexMatcher(ipAddressPattern).matching("255.256.255.0"));
Assert.assertFalse(new RegexMatcher(ipAddressPattern).matching("1.1.1"));
Assert.assertTrue(new RegexMatcher("^foobar$").matching("foobar"));
Assert.assertFalse(new RegexMatcher("^foobar$").matching("\nfoobar"));
Assert.assertFalse(new RegexMatcher("^foobar$").matching("foobar\n"));
String emailAddressPattern = "[a-z\\d]+(\\.[a-z\\d]+)*@([\\da-z](-[\\da-z])?)+(\\.{1,2}[a-z]+)+";
Assert.assertTrue(new RegexMatcher(emailAddressPattern).matching("foo@bar.com"));
Assert.assertFalse(new RegexMatcher(emailAddressPattern).matching("asdfghjkl"));
}
}
@@ -0,0 +1,19 @@
package com.taobao.arthas.core.util.matcher;
import org.junit.Assert;
import org.junit.Test;
/**
* @author earayu
*/
public class TrueMatcherTest {
@Test
public void testMatching(){
Assert.assertTrue(new TrueMatcher<String>().matching(null));
Assert.assertTrue(new TrueMatcher<Integer>().matching(1));
Assert.assertTrue(new TrueMatcher<String>().matching(""));
Assert.assertTrue(new TrueMatcher<String>().matching("foobar"));
}
}
@@ -0,0 +1,36 @@
package com.taobao.arthas.core.util.matcher;
import org.junit.Assert;
import org.junit.Test;
/**
* @author earayu
*/
public class WildcardMatcherTest {
@Test
public void testMatching(){
Assert.assertFalse(new WildcardMatcher(null).matching(null));
Assert.assertFalse(new WildcardMatcher(null).matching("foo"));
Assert.assertFalse(new WildcardMatcher("foo").matching(null));
Assert.assertTrue(new WildcardMatcher("foo").matching("foo"));
Assert.assertFalse(new WildcardMatcher("foo").matching("bar"));
Assert.assertTrue(new WildcardMatcher("foo*").matching("foo"));
Assert.assertTrue(new WildcardMatcher("foo*").matching("fooooooobar"));
Assert.assertTrue(new WildcardMatcher("f*r").matching("fooooooobar"));
Assert.assertFalse(new WildcardMatcher("foo*").matching("fo"));
Assert.assertFalse(new WildcardMatcher("foo*").matching("bar"));
Assert.assertFalse(new WildcardMatcher("foo?").matching("foo"));
Assert.assertTrue(new WildcardMatcher("foo?").matching("foob"));
Assert.assertTrue(new WildcardMatcher("foo\\*").matching("foo*"));
Assert.assertFalse(new WildcardMatcher("foo\\*").matching("foooooo"));
Assert.assertTrue(new WildcardMatcher("foo\\?").matching("foo?"));
Assert.assertFalse(new WildcardMatcher("foo\\?").matching("foob"));
}
}
@@ -8,6 +8,7 @@ import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;
/**
* @author ralf0131 2018-07-10 10:55.
@@ -190,13 +191,14 @@ public class ObjectViewTest {
@Test
public void testDate() {
Date d = new Date(1531204354961L);
Date d = new Date(1531204354961L - TimeZone.getDefault().getRawOffset()
+ TimeZone.getTimeZone("GMT+8").getRawOffset());
ObjectView objectView = new ObjectView(d, 3);
String expected = "@Date[2018-07-10 14:32:34,961]";
Assert.assertEquals(expected, objectView.draw());
}
@Test
@Test
public void testNestedClass() {
ObjectView objectView = new ObjectView(new NestedClass(100), 3);
+13
View File
@@ -225,6 +225,19 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<version>2.7</version>
<configuration>
<formats>
<format>html</format>
<format>xml</format>
</formats>
<check />
</configuration>
</plugin>
</plugins>
</build>
</project>
@@ -4,4 +4,7 @@
{% set github_repo = 'arthas' %}
{% set theme_vcs_pageview_mode = 'blob' %}
{% set github_version = 'master' %}
{% set conf_py_path = '/site/src/site/sphinx/' %}
{% set conf_py_path = "/site/src/site/sphinx/" %}
{% if language == 'en' %}
{% set conf_py_path = "/site/src/site/sphinx/en/" %}
{% endif %}
+1 -1
View File
@@ -19,7 +19,7 @@ Arthas 3.0开始支持管道, 率先提供了`grep`,`wc`,`plaintext`的支持。
groovy表达式在arthas2.0中大量使用,例如watch表达式
```sh
```bash
watch com.alibaba.sample.petstore.web.store.module.screen.ItemList add "params + ' ' + returnObj" params.size()==2
```
@@ -16,7 +16,7 @@ Arthas 3.0最重要的特性,通过Arthas在线诊断平台,无需再登陆
Arthas 3.0开始支持管道, 率先提供了`grep`,`wc`,`plaintext`的支持。
```sh
```bash
java.vendor.url http://java.oracle.com/
java.vm.vendor Oracle Corporation
java.runtime.name Java(TM) SE Runtime Environment
@@ -55,7 +55,7 @@ To solve this, choose one of the following command:
groovy表达式在arthas2.0中大量使用,例如watch表达式
```sh
```bash
watch com.alibaba.sample.petstore.web.store.module.screen.ItemList add "params + ' ' + returnObj" params.size()==2
```
+7 -7
View File
@@ -6,14 +6,14 @@ arthas中的异步调用,使用了仿linux系统任务相关的命令。[linux
## 1. 使用&在后台执行任务
比如希望执行后台执行trace命令,那么调用下面命令
```sh
```bash
trace Test t &
```
这时命令在后台执行,可以在console中继续执行其他命令。
## 2. 通过jobs查看任务
如果希望查看当前有哪些arthas任务在执行,可以执行jobs命令,执行结果如下
```sh
```bash
$ jobs
[10]*
Stopped watch com.taobao.container.Test test "params[0].{? #this.name == null }" -x 2
@@ -36,20 +36,20 @@ $ jobs
* ‘ctrl + d’:按照linux语义应当是退出终端,目前arthas中是空实现,不处理
## 4. fg、bg命令,将命令转到前台、后台继续执行
* 任务在后台执行或者暂停状态(‘ctrl + z’暂停任务)时,执行fg <job-id>将可以把对应的任务转到前台继续执行。在前台执行时,无法在console中执行其他命令
* 当任务处于暂停状态时(‘ctrl + z’暂停任务),执行bg <job-id>将可以把对应的任务在后台继续执行
* 任务在后台执行或者暂停状态(`ctrl + z`暂停任务)时,执行`fg <job-id>`将可以把对应的任务转到前台继续执行。在前台执行时,无法在console中执行其他命令
* 当任务处于暂停状态时(`ctrl + z`暂停任务),执行`bg <job-id>`将可以把对应的任务在后台继续执行
* 非当前session创建的job,只能由当前session fg到前台执行
## 5. 任务输出重定向
可通过`>`或者`>>`将任务输出结果输出到指定的文件中,可以和`&`一起使用,实现arthas命令的异步调用。比如:
```sh
```bash
$ trace Test t >> test.out &
```
这时trace命令会在后台执行,并且把结果输出到~/logs/arthas-cache/test.out。可继续执行其他命令。并可查看文件中的命令执行结果。
当远程调用时,可能无法确定机器文件路径,arthas同时支持了自动重定向到缓存路径。使用方法如下:
```sh
当连接到远程的arthas server时,可能无法查看远程机器的文件,arthas同时支持了自动重定向到本地缓存路径。使用方法如下:
```bash
$ trace Test t >> &
job id : 2
cache location : /Users/gehui/logs/arthas-cache/28198/2
+2 -2
View File
@@ -28,12 +28,12 @@ sc -d org.apache.commons.lang.StringUtils
通过`-b`开启批处理模式, `-f`执行脚本文件, 批处理脚本默认会输出到标准输出中,可以将结果重定向到文件中。
```sh
```bash
./as.sh -b -f /var/tmp/test.as 56328 > test.out
```
#### 第三步: 查看运行结果
```sh
```bash
cat test.out
```
+1 -1
View File
@@ -41,7 +41,7 @@ Affect(row-cnt:11) cost in 66 ms.
* 按类加载实例查看统计信息
```sh
```bash
$ classloader -l
name loadedCount hash parent
BootstrapClassLoader 3711 null null
+37 -37
View File
@@ -3,74 +3,74 @@ Advanced Usage
## Basic
- help
- cls - clear out the current screen
- session - check details of the current session
- [reset](reset.md) - reset all empowered classes
- version - print the version of the Arthas attaching to the current target process
- quit/exit - exit the current Arthas client without affecting other clients
- shutdown - terminate the Arthas server and all clients
* help - display Arthas help
* cls - clear the screen
* session - display current session information
* [reset](reset.md) - reset all the enhanced classes. All enhanced classes will also be reset when Arthas server is closed by `shutdown`
* version - print the version for the Arthas attached to the current Java process
* quit/exit - exit the current Arthas session, without effecting other sessions
* shutdown - terminate the Arthas server, all Arthas sessions will be destroyed
* [keymap](keymap.md) - keymap for Arthas keyboard shortcut
## JVM-related
## JVM
* [dashboard](dashboard.md) - real-time dashboard for the current system
* [thread](thread.md) - thread profile
* [jvm](jvm.md) - JVM profile
* [sysprop](sysprop.md) - check or modify JVM system properties
* **New!** [getstatic](getstatic.md) - check the static properties of some class
* [dashboard](dashboard.md) - dashboard for the system's real-time data
* [thread](thread.md) - show java thread information
* [jvm](jvm.md) - show JVM information
* [sysprop](sysprop.md) - show/modify system properties
* **New!** [getstatic](getstatic.md) :clap: - examine class's static properties
## class/classloader - related
## class/classloader
* [sc](sc.md) - methods' profile of the classes loaded by JVM
* [sm](sm.md) - methods' profile of the loaded classes
* [dump](dump.md) - dump out the byte code of the loaded class to specified location
* [redefine](redefine.md) - load external `*.class` files and re-define the JVM
* [sc](sc.md) - check the info for the classes loaded by JVM
* [sm](sm.md) - check methods info for the loaded classes
* [dump](dump.md) - dump the loaded classes in byte code to the specified location
* [redefine](redefine.md) - load external `*.class` files and re-define it into JVM
* [jad](jad.md) - de-compile the specified loaded classes
* [classloader](classloader.md) - check the inheritance structure, urls, class loading info of class cloader; using classloader to getResource
* [classloader](classloader.md) - check the inheritance structure, urls, class loading info for the specified class; using classloader to get the url of the resource e.g. `java/lang/String.class`
## monitor/watch/trace - related
> **Attention**: commands here are taking advantage of `byte code injection`, which means we are using [AOP](https://en.wikipedia.org/wiki/Aspect-oriented_programming) to monitor and analyze the classes. So when using it for online troubleshooting, you'd better *explicitly specifically* specify the classes and also remember to remove the injected code by `shutdown` or `reset` (for specific classes).
> **Attention**: commands here are taking advantage of byte-code-injection, which means we are injecting some [aspects](https://en.wikipedia.org/wiki/Aspect-oriented_programming) into the current classes for monitoring and statistics purpose. Therefore when use it for online troubleshooting in your production environment, you'd better **explicitly specify** classes/methods/criteria, and remember to remove the injected code by `shutdown` or `reset`.
* [monitor](monitor.md)
* [watch](watch.md)
* [trace](trace.md) - track the call stack trace and collect the time cost for each method call
* [stack](stack.md) - print the call stack trace of the current method
* [tt](tt.md) - record the arguments and returned value for the methods, history included
* [monitor](monitor.md) - monitor method execution statistics
* [watch](watch.md) - display the input/output parameter, return object, and thrown exception of specified method invocation
* [trace](trace.md) - trace the execution time of specified method invocation
* [stack](stack.md) - display the stack trace for the specified class and method
* [tt](tt.md) - time tunnel, record the arguments and returned value for the methods and replay
## options
* [options](options.md) - check or set Arthas global options
* [options](options.md) - check/set Arthas global options
## pipe
`pipe` is supported in Arthas, e.g. `sm org.apache.log4j.Logger | grep <init>`
Arthas provides `pipe` to process the result returned from commands further, e.g. `sm org.apache.log4j.Logger | grep <init>`. Commands supported in `pipe`:
* grep
* grep - filter the result with the given keyword
* plaintext - remove the color
* wc
* wc - count lines
## async in background
[async](async.md) will be a great help, when the `incident` seldom occurs and you are `[watch](watch.md)`ing it.
[async](async.md) can be handy when a problem is hardly to reproduce in the production enviornment, e.g. one `watch` condition may happen only once in one single day.
* job control - use `>` to redirect result into the log file, use `&` to put the job to the background. Job keeps running even if the session is disconnected (the session lifecycle is 1 day by default)
* jobs - list all jobs
* kill - forcibly terminate the job
* fg - bring the paused job back to the front
* bg - put the paused job to the background
* tips - a) use `>` to redirect the output; b) use `&` to put the job to the background; c) disconnecting the session will not influence the job (the default life is 1 day)
* fg - bring the suspend job to the foreground
* bg - put the job to run in the background
## Web Console
Using websocket to connect Arthas
Arthas supports living inside a browser. The communication between arthas and browser is via websocket.
* [Web Console](web-console.md)
## Others
## Other features
* [Async support](async.md)
* [log the output](save-log.md)
* [batch](batch-support.md)
* [how to use ognl](https://github.com/alibaba/arthas/issues/11)
+44
View File
@@ -0,0 +1,44 @@
Critical Fields in Expressions
==============================
There is a very fundamental class `Advice` for the expressions used in filtering, tracing or monitoring and other aspects in commands.
```java
public class Advice {
private final ClassLoader loader;
private final Class<?> clazz;
private final ArthasMethod method;
private final Object target;
private final Object[] params;
private final Object returnObj;
private final Throwable throwExp;
private final boolean isBefore;
private final boolean isThrow;
private final boolean isReturn;
...
// getter/setter
}
```
|Name|Specification|
|---:|:---|
|loader|class loader of the class|
|clazz|the reference of the class|
|method|the reflective reference of the method|
|target|the instance of the class|
|params|the parameters of the method, which is an array (when there is no argument in the method, it will be an empty array)|
|returnObj|the return value of the method - only when `isReturn==true`, it's a valid result but if the return value is `void` then it will be a `null`|
|throwExp|the exceptions thrown by the method invoking - only when `isThrow==true`, it's a valid thrown exception|
|isBefore|assistant checking flag used in [`before-watching` point](watch.md) and at this very moment: `isBefore==true`, `isThrow==false` and `isReturn==false` since it's before we invoke the method|
|isThrow|assistant checking flag: whether the current method invoking ends with exceptions|
|isReturn|assistant checking flag: whether the method invoking exits normally without exceptions|
F.Y.I
1. all the *fields* mentioned in the table above can be used directly in the `expressions`;
2. if the expressions are [invalid OGNL](https://en.wikipedia.org/wiki/OGNL), the command will be cancelled automatically with hints to correct the expressions;
3. [typical use cases](https://github.com/alibaba/arthas/issues/71);
4. [OGNL official usage guide](https://commons.apache.org/proper/commons-ognl/language-guide.html).
+83
View File
@@ -0,0 +1,83 @@
Arthas Async Jobs
===
Asynchronous jobs in arthas, using commands related to linux jobs.[linux man jobs](http://man7.org/linux/man-pages/man1/jobs.1p.html)。
## 1. Use & to run the command in the background
For example, execute the trace command in the background:
```bash
trace Test t &
```
## 2. List background jobs
If you want to list all background jobs, you can execute the `jobs` command and the results are as follows:
```bash
$ jobs
[10]*
Stopped watch com.taobao.container.Test test "params[0].{? #this.name == null }" -x 2
execution count : 19
start time : Fri Sep 22 09:59:55 CST 2017
timeout date : Sat Sep 23 09:59:55 CST 2017
session : 3648e874-5e69-473f-9eed-7f89660b079b (current)
```
You can see that there is currently a background job executing.
* job id is 10, `*` indicates that this job is created by the current session.
* status is `Stopped`
* execution count is the number of executions, which have been executed 19 times since the start.
* timeout date: After this time, the job will automatically timeout and exit.
## 3. Suspend and Cannel job
When the job is executing in the foreground, such as directly calling the command `trace Test t` or calling the background job command `trace Test t &`, the job is transferred to the foreground through the `fg` command. At this point, the console cannot continue to execute the command, but can receive and process the following keyboard events:
* ‘ctrl + z’: Suspend the job, the job status will change to `Stopped`, and the job can be restarted by `bg <job-id>` or `fg <job-id>`
* ‘ctrl + c’: Stop the job
* ‘ctrl + d’: According to linux semantics should be the exit terminal, currently arthas ignore this input.
## 4. fg/bg, Bring a background job to the foreground/Restart a stopped background job
* When the job is executed in the background or suspended (`ctrl + z` to suspend job), executing `fg <job-id>` will transfer the corresponding job to the foreground to continue execution.
* When the job is suspended (`ctrl + z` to suspend job), executing `bg <job-id>` will continue the corresponding job in the background.
* A job created by a non-current session can only be executed by the current session fg to the foreground.
## 5. Redirect the job output
The job output can be redirect to the specified file by `>` or `>>`, and can be used together with `&` to implement the asynchronous job of the arthas command. such as:
```bash
$ trace Test t >> test.out &
```
The trace command will be executed in the background and the output will be redirect to `~/logs/arthas-cache/test.out`. You can continue to execute other commands in the console.
When connecting to a remote arthas server, you may not be able to view the files of the remote machine. Arthas also supports automatic redirection to the local cache file. Examples are as follows:
```bash
$ trace Test t >> &
job id : 2
cache location : /Users/gehui/logs/arthas-cache/28198/2
```
You can see that does not specify the redirect file after `>>`, arthas will automatically redirect the job output to the `~/logs/arthas-cache`.
In the above example, pid is `28198` and job id is `2`.
## 6. Stop job
If you want to stop background job, just `kill <job-id>`.
## 7. Others
* Support up to 8 commands at the same time redirect the output to the log file.
* Do not open too many background asynchronous commands at the same time to avoid affecting the performance of the target JVM.
+39
View File
@@ -0,0 +1,39 @@
Batch Processing
================
With the help of `Batch Processing`, you can run several commands in one line and get the results.
### Usage
#### Step-1: Create the script
Creating a `test.as` script suffixed with `as` here for consistency (actually any suffix is acceptable).
```
➜ arthas git:(develop) cat /var/tmp/test.as
help
dashboard -b -n 1
session
thread
sc -d org.apache.commons.lang.StringUtils
```
Attention:
* each command takes each independent line;
* `dashboard` command should include `-b` to turn on batch mode and `-n` to ensure the script ends;
* commands as `watch/tt/trace/monitor/stack` should include `-n` option to ensure the script ends;
* [asynchronous](async.md) can also be used as `watch c.t.X test returnObj > &`;
#### Step-2: Run the script
Using `-b` to turn on script mode, and `-f` to run it and you can also *redirect* the output as:
```bash
./as.sh -b -f /var/tmp/test.as 56328 > test.out
```
#### Step-3: Check the outputs
```bash
cat test.out
```
+8 -8
View File
@@ -9,17 +9,17 @@ It can be a great help for `ResourceNotFoundException` when you can use command
|Name|Specification|
|---:|:---|
|[l]|count based on the class loader instance|
|[t]|print all the inheritance structure of the class loaders|
|[l]|list all class loader instances based on thread count|
|[t]|print the inheritance structure of the class loaders|
|[a]|list all the classes loaded by all the class loaders (use it with great caution since the output can be huge)|
|`[c:]`|get the hashcode of the class loader|
|`[c: r:]`|using class loader to search resource|
|[c:]|get the hashcode of the class loader|
|[c: r:]|using class loader to search resource|
### Usage
* categorised by class loader
* Categorised by class loader
```s
```bash
$ classloader
name numberOfInstances loadedCountTotal
com.taobao.pandora.service.loader.ModuleClassLoader 29 11659
@@ -38,7 +38,7 @@ Affect(row-cnt:11) cost in 66 ms.
* Categorized by class loader instance
```sh
```bash
$ classloader -l
name loadedCount hash parent
BootstrapClassLoader 3711 null null
@@ -100,7 +100,7 @@ $ classloader -t
| | +-sun.reflect.DelegatingClassLoader@73f44f24
```
* Check the real urls of `URLClassLoader`
* Check URL of the class loader
```shell
$ classloader -c 5ffe9775
+8 -2
View File
@@ -1,6 +1,8 @@
Commands List
All Commands
=============
* [dashboard](dashboard.md)
* [thread](thread.md)
* [jvm](jvm.md)
@@ -25,7 +27,8 @@ Commands List
* [options](options.md)
### Arthas Basic Commands
### Basic Commands
* help - check the assistant info for the command
* cls - clear out the current screen area
@@ -35,3 +38,6 @@ Commands List
* quit - exit the current Arthas client without affecting other clients
* shutdown - terminate the Arthas server and all clients
* [keymap](keymap.md) - shortcuts for Arthas and also you can define your own
+2 -2
View File
@@ -78,7 +78,7 @@ release = version
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
# language = u'zh_CN'
language = u'en'
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
@@ -203,7 +203,7 @@ html_static_path = ['_static']
# Sphinx supports the following languages:
# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja'
# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr'
#html_search_language = 'en'
html_search_language = 'en'
# A dictionary with options for the search language support, empty by default.
# Now only 'ja' uses this config value
+4 -4
View File
@@ -8,13 +8,13 @@ Dump the bytecode the loaded classes to a specified directory.
|Name|Specification|
|---:|:---|
|*class-pattern*|pattern for the class name|
|`[c:]`|hashcode of the class loader that loaded the class|
|[E]|turn on regx matching while the default is wildcards matching|
|[c:]|hashcode of the [class loader](classloader.md) that loaded the class|
|[E]|turn on regex matching while the default is wildcard matching|
### Usage
```shell
$ dump -E org\.apache\.commons\.lang\.StringUtils
```bash
$ dump org.apache.commons.lang.StringUtils
HASHCODE CLASSLOADER LOCATION
29505d69 +-tddl-client's ModuleClassLoader /Users/zhuyong/middleware/taobao-tomcat/output/build/bin/classdump/com.taobao.pandora
.service.loader.ModuleClassLoader-29505d69/org.apache.commons.lang.StringUtils.class
+14 -14
View File
@@ -5,38 +5,38 @@ Arthas Documentation
![arthas](arthas.png)
`Arthas` is an Java Diagnostic tool open sourced by Alibaba.
`Arthas` is a Java Diagnostic tool open sourced by Alibaba.
Arthas can help developer trouble-shooting production issues for Java applications without modifying your code or restating your server.
Arthas help developers in trouble-shooting production issues for Java applications without modifying code or restarting servers.
### Background
In production system, sometimes the networks is unreachable from local development environment. If you encounter some issues in production system, it is impossible to use IDE to debug the application remotely. More importantly, debugging in production is unacceptable, because it will suspend all the threads, which leads to business unavailability.
Often times, the production system network is inaccessible from local development environment. If issues are encountered in production systems, it is impossible to use IDE to debug the application remotely. More importantly, debugging in production environment is unacceptable, as it will suspend all the threads, which leads to blocking of business services.
Some may think of reproducing the same issue on the test/staging environment, however, some tricky issue either can hardly be reproduced on a different environment, or even disappeared once restarted.
Developers could always try to reproduce the same issue on the test/staging environment. However, this is tricky as some issues cannot be be reproduced easily on a different environment, or even disappear once restarted.
Thinking of adding some logs to your code? You have to go through test, staging, and then on to production. Time is money! That is a lot inefficient! Besides, the issue may not be reproducible once restart your JVM, as described above.
And if you're thinking of adding some logs to your code to help trouble-shoot the issue, you will have to go through the following lifecycle; test, staging, and then to production. Time is money! This approach is inefficient! Besides, the issue may not be reproducible once the JVM is restarted, as described above.
Arthas is born to solve these issues. You can trouble-shoot your production issue on-the-fly. No JVM restart, no additional code changes. Arthas works as an observer, which will never suspend your existing threads.
Arthas was built to solve these issues. A developer can trouble-shoot your production issues on-the-fly. No JVM restart, no additional code changes. Arthas works as an observer, which will never suspend your existing threads.
### Key features
* Check whether a class is loaded? And whether is class loaded from? (Useful for trouble-shooting jar file conflicts)
* Check whether a class is loaded? Or where the class is loaded from? (Useful for trouble-shooting jar file conflicts)
* Decompile a class to ensure the code is running as expected.
* View classloader statistics, e.g. how may classloaders are there? how many class is loaded per classloader? What is the classloader hierarchy? Is there possible classloader leaks?
* View classloader statistics, e.g. the number of classloaders, the number of classes loaded per classloader, the classloader hierarchy, possible classloader leaks, etc.
* View the method invocation details, e.g. method parameter, return object, thrown exception, and etc.
* Check the stack trace of specified method invocation. This is useful when you would like to know who is calling your method?
* Check the stack trace of specified method invocation. This is useful when a developers wants to know the caller of the said method.
* Trace the method invocation to find slow sub-invocations.
* Monitor method invcation statistics, e.g. qps, rt, success rate and etc.
* Monitoring your system metrics, thread states and cpu usage, gc statistics, and etc.
* Support command line interactive mode, with auto completed feature enabled.
* Support telnet and websocket, which enables both local and remote diagnostics with command line and browsers.
* Monitor method invocation statistics, e.g. qps, rt, success rate and etc.
* Monitor system metrics, thread states and cpu usage, gc statistics, and etc.
* Supports command line interactive mode, with auto-complete feature enabled.
* Supports telnet and websocket, which enables both local and remote diagnostics with command line and browsers.
Contents
--------
English version is on the way, if you would like to contribute, please leave a message [here](https://github.com/alibaba/arthas/issues/51)
English version has just been finished. If you would like to make it better, please check [here](https://github.com/alibaba/arthas/issues/51) and submit your PM.
* [Installation](install-detail.md)
* [Quick start](quick-start.md)
+10 -6
View File
@@ -6,22 +6,22 @@ De-compile specified loaded classes.
`jad` helps to *de-compile* the byte code in JVM to the source code to assist you to better understand the logic behind.
F.Y.I
* the de-compiled code will be grammatically highlighted for readability in Arthas Console;
* you have to understand there might be some trivial grammar errors but it won't affect the logic understanding.
* the de-compiled code will be grammatically highlighted for readability in Arthas console;
* there might be some trivial grammar errors but it won't affect the logic understanding.
### Options
|Name|Specification|
|---:|:---|
|*class-pattern*|pattern for the class name|
|`[c:]`|hashcode of the class loader that loaded the class|
|[E]|turn on regx matching while the default is wildcards matching|
|[c:]|hashcode of the class loader that loaded the class|
|[E]|turn on regex matching while the default is wildcard matching|
### Usage
When several class loaders loaded the same class:
1. `jad` to get the hashcode of the class loader;
2. `jad -c <hashcode>` to get the de-compiled class loaded by the class loader.
2. `jad -c <hashcode>` to get the de-compiled class loaded by the specified class loader.
```java
$ jad org.apache.log4j.Logger
@@ -122,7 +122,7 @@ Affect(row-cnt:1) cost in 190 ms.
De-compile the specified method:
```sh
```bash
$ jad com.taobao.container.web.arthas.rest.MetricsController directMetrics
ClassLoader:
@@ -156,3 +156,7 @@ private Map<String, Object> directMetrics(String ip, String[] metrics) {
Affect(row-cnt:1) cost in 1508 ms.
```
F.Y.I
Inner class is not yet supported, you can just check the *outer* class to further check the inner class.
+15 -2
View File
@@ -84,8 +84,14 @@ $ jvm
THREAD COUNT 16
DAEMON-COUNT 10
LIVE-COUNT 18
PEAK-COUNT 18
STARTED-COUNT 19
DEADLOCK-COUNT 0
FILE-DESCRIPTOR
MAX-FILE-DESCRIPTOR-COUNT 10240
OPEN-FILE-DESCRIPTOR-COUNT 648
Affect cost in 2 ms.
```
@@ -93,5 +99,12 @@ Affect cost in 2 ms.
* COUNT: the count of active threads
* DAEMON-COUNT: the count of active daemon threads
* LIVE-COUNT: the maximum count of the live threads since JVM starts
* PEAK-COUNT: the maximum count of the live threads since JVM starts
* STARTED-COUNT: the total count of the created threads since JVM starts
* DEADLOCK-COUNT: the count of deadlock threads
### fileDescriptor-related
* MAX-FILE-DESCRIPTOR-COUNT:the count of max file descriptor JVM process can open
* OPEN-FILE-DESCRIPTOR-COUNT:the current count of file descriptor JVM process open
+75
View File
@@ -0,0 +1,75 @@
Arthas Console Keymap
===
`keymap` command print current keymap.
The default keymap is:
| Shortcut | Shortcut Description | Command Name | Command Description |
| ------------- | ---------------- | -------------------- | ---------------- |
| `"\C-a"` | ctrl + a | beginning-of-line | go to the beginning of the line |
| ` "\C-e"` | ctrl + e | end-of-line | go to the end of the line|
| `"\C-f"` | ctrl + f | forward-word | forward a word |
| `"\C-b"` | ctrl + b | backward-word | backward a word |
| `"\e[D"` | left arrow | backward-char | backward a character |
| `"\e[C"` | right arrow | forward-char | forward a character |
| `"\e[B"` | down arrow | next-history | show next history command |
| `"\e[A"` | up arrow | previous-history | show previous history command |
| `"\C-h"` | ctrl + h | backward-delete-char | backward delete a character |
| `"\C-?"` | ctrl + shift + / | backward-delete-char | backward delete a character |
| `"\C-u"` | ctrl + u | undo | clear current line |
| `"\C-d"` | ctrl + d | delete-char | delete the character of the current cursor |
| `"\C-k"` | ctrl + k | kill-line | delete all characters from the current cursor to the end of the line |
| `"\C-i"` | ctrl + i | complete | Auto completion, equivalent to `TAB` |
| `"\C-j"` | ctrl + j | accept-line | end the current line, equivalent to `enter` |
| `"\C-m"` | ctrl + m | accept-line | end the current line, equivalent to `enter` |
| `"\C-w"` | | backward-delete-word | |
| `"\C-x\e[3~"` | | backward-kill-line | |
| `"\e\C-?"` | | backward-kill-word | |
* You can enter `Tab` to get automatic prompts at any time.
* After typing the command, type `-` or `--`, then press `tab` to display the specific options of this command.
#### Custom shortcuts
Create a new `$USER_HOME/.arthas/conf/inputrc` file in the current user home directory and add a custom configuration.
Suppose I am a heavy user of vim. I want to set `ctrl+h` to the cursor forward character. Set it as follows, first copy the default configuration.
```
"\C-a": beginning-of-line
"\C-e": end-of-line
"\C-f": forward-word
"\C-b": backward-word
"\e[D": backward-char
"\e[C": forward-char
"\e[B": next-history
"\e[A": previous-history
"\C-h": backward-delete-char
"\C-?": backward-delete-char
"\C-u": undo
"\C-d": delete-char
"\C-k": kill-line
"\C-i": complete
"\C-j": accept-line
"\C-m": accept-line
"\C-w": backward-delete-word
"\C-x\e[3~": backward-kill-line
"\e\C-?": backward-kill-word
```
Then replace `"\C-h": backward-delete-char` with `"\C-h": backward-char`, then reconnect.
#### Shortcuts about async
* ctrl + c: Terminate current command
* ctrl + z: Suspend the current command, you can restore this command with bg/fg, or kill it.
* ctrl + a: Go to the beginning the line
* ctrl + e: Go to the end of the line
+31
View File
@@ -0,0 +1,31 @@
Manual Installation
===================
### Download
Latest `bin.zip `: [![Arthas](https://img.shields.io/maven-central/v/com.taobao.arthas/arthas-packaging.svg?style=flat-square "Arthas")](http://search.maven.org/classic/#search%7Cga%7C1%7Cg%3A%22com.taobao.arthas%22%20AND%20a%3A%22arthas-packaging%22)
If the downloading is rather clumsy, try to download from the [repository in AliYun](https://maven.aliyun.com/); the downloading URL template is (remember to fill up the version `3.x.x` template to your needs)
`https://maven.aliyun.com/repository/public/com/taobao/arthas/arthas-packaging/3.x.x/arthas-packaging-3.x.x-bin.zip`
### Unzip
```bash
unzip arthas-packaging-bin.zip
```
### Install
```bash
sudo su admin
rm -rf /home/admin/.arthas/lib/* # remove all the leftover of the old outdated Arthas
cd arthas
./install-local.sh # switch the user based on the owner of the target Java process.
```
### Start
```bash
./as.sh # make sure the old Arthas has been shut down (using command shutdown);
```
+7 -7
View File
@@ -1,14 +1,14 @@
monitor
=======
Monitor the `class-pattern` & `method-pattern` matched methods invoking traces.
Monitor methods calling stack traces.
F.Y.I
1. `monitor` is a persistent command, it never returns until `Ctrl+C` to manually stop it.
2. the server runs the tasks in the background;
3. injected code will become invalid automatically once the tasks being terminated;
4. in theory, Arthas commands will not change any original behaviors.
1. `monitor` is a persistent command, it never returns until you press `Ctrl+C` to manually stop it;
2. the server runs the jobs in the background;
3. injected monitoring code will become invalid automatically once the monitoring jobs being terminated;
4. in theory, Arthas will not change any original behaviors but if it does, please do not hesitate to start an [issue](https://github.com/alibaba/arthas/issues).
### Properties monitored
@@ -29,8 +29,8 @@ F.Y.I
|---:|:---|
|*class-pattern*|pattern for the class name|
|*method-pattern*|pattern for the method name|
|[E]|turn on regx matching while the default is wildcards matching|
|`[c:]`|cycle of output with default value: `120 s`|
|[E]|turn on regex matching while the default is wildcard matching|
|[c:]|cycle of output with default value: `60 s`|
### Usage
+10 -10
View File
@@ -1,22 +1,22 @@
options
===
> Global options
### Global options
| Name | Default Value | Description |
| ------------------ | ----- | ---------------------------------------- |
| unsafe | false | Enable support for system-level class enhancement; JVM might crash, if you turn on this switch (please use with great caution!) |
| dump | false | Enable support for dumping enhanced class to external file,if turned on,class file will be dumped to`/${application dir}/arthas-class-dump/`,please see console for specific location |
|Name| Default Value | Description |
| ------------------------- | ----- | ---------------------------------------- |
| unsafe | false | Enable system-level class enhancement; JVM might crash, if you turn it on (use with great caution :exclamation:) |
| dump | false | Enable support for dumping enhanced class to external files; if turned on, class file will be dumped to`/${application dir}/arthas-class-dump/`,please check console output for specific location |
| batch-re-transform | true | re-transform matched classes in batch |
| json-format | false | Enable output in JSON format |
| disable-sub-class | false | Disabling child class matching,by default child class will be matched during matching target class,if you wish exact matching,you can turn this off |
| debug-for-asm | false | Print ASM related debug message |
| save-result | false | Enable saving logs for task results,when turn to true, all command results will be saved to `/home/admin/logs/arthas/arthas.log` |
| job-timeout | 1d | Default time-out time for back-stage tasks,if exceed this time,task will be stopped;i.e. 1d, 2h, 3m, 25s,representing day、hour、minute、second |
| disable-sub-class | false | Disabling child class matching: by default child class will be matched while matching target class; if you wish exact matching, you should turn it off |
| debug-for-asm | false | Print ASM-related debug message |
| save-result | false | Enable saving logs for task results: when true, all command results will be saved to `/home/admin/logs/arthas/arthas.log` |
| job-timeout | 1d | Default timeout for background jobs: jobs will be stopped once timed out (i.e. 1d, 2h, 3m, 25s)|
### Usage
For example,if you wish to save logs for command results, you can use following command:
Saving logs for command outputs, you can:
```
$ options save-result true
+4 -5
View File
@@ -56,8 +56,7 @@ public class Demo {
sudo -u admin -EH ./as.sh
```
2. For more details of the booting script, please refer to [starting arthas](start-arthas.md).
2. For more details of the booting script, please refer to [Start Arthas](start-arthas.md).
3. If you cannot *attach* the target process, please check the logs under `~/logs/arthas` for troubleshooting.
4. Selecting the target process as:
@@ -90,8 +89,8 @@ public class Demo {
version: 3.0.1-RC-SNAPSHOT
pid: 13560
timestamp: 1536656867894
'`'`'`'`'`'`'`'`'`
'
$
```
### Windows
@@ -152,7 +151,7 @@ ts=2018-09-10 17:53:14;result=@Integer[624]
ts=2018-09-10 17:53:15;result=@Integer[625]
```
[more advanced functions](advanced-use.md)
[more advanced usages](advanced-use.md)
## 5. Exit Arthas
+4 -4
View File
@@ -1,14 +1,14 @@
redefine
========
Load the external `*.class` files and *re-define* the JVM-loaded classes.
Load the external `*.class` files to **re-define** the JVM-loaded classes.
Reference: [Instrumentation#redefineClasses](https://docs.oracle.com/javase/8/docs/api/java/lang/instrument/Instrumentation.html#redefineClasses-java.lang.instrument.ClassDefinition...-)
F.Y.I
1. Re-defined classes cannot be restores any more;
2. Re-definition can fail (like adding a new field); for more information, please refer to JDK documentation
2. Re-definition can fail (like adding a new field/method); for more information, please refer to JDK documentation
### Options
@@ -21,6 +21,6 @@ F.Y.I
### Usage
```
redefine -p /tmp/Test.class
redefine -c 327a647b -p /tmp/Test.class /tmp/Test\$Inner.class
redefine -p /tmp/Test.class
redefine -c 327a647b -p /tmp/Test.class /tmp/Test$Inner.class
```
+127
View File
@@ -0,0 +1,127 @@
Release Notes
=============
v3.0.4
---
* https://github.com/alibaba/arthas/milestone/1?closed=1
v2017-11-03
----
* [improvement] add [`getstatic`](getstatic.md)
* [bug] fix Arthas class loader logs loading issues
* [improvement] introduce [OGNL](https://en.wikipedia.org/wiki/OGNL) to customize `classloader` to invoke static methods
* [improvement] optimise `termd` uppercase output performance
* [improvement] `classloader` compile in class loader category by default
* [bug] fix `wc` counting issue
* [improvement] disable certain JDK classes e.g. `Classloader`, `Method`, `Integer` and the lik
* [improvement] quit directly when encountering incorrect [OGNL](https://en.wikipedia.org/wiki/OGNL) expression
* [bug] fix `pipe` issues
* [improvement] optimize command re-direct features using asynchronous log
* [improvement] [`trace`](trace.md) can filter JDK method calls
v2017-09-22
----
* [improvement] improve the error message when starting agent and server fails
* [bug] fix some asynchronous issues
v2017-09-11
----
* [improvement] [`async`](async.md) supported
* [improvement] optimize [`jad`](jad.md) support JDK 8 and inner class
* [bug] fix Chinese encoding issues
v2017-05-11
----
* [improvement] [`tt`](tt.md) investigating/recording level one to avoid too much performance overhea
* [bug] fix Chinese characters can not be presented issue
v2017-05-12
----
* Arthas 3.0 release :confetti_ball:
v2016-12-09
----
* [feature] [`as.sh`](https://github.com/alibaba/arthas/blob/master/bin/as.sh) support `-h` to print help info
* [bug] [#121] fix leftover temp files causing Arthas cannot start issue
* [bug] [#123] fix `attach/shutdown` repeatedly causing Arthas classloader leakage issue
* [improvement] make the help info more readable
* [bug] [#126] fix the documents links issues
* [bug] [#122] fix the [`classloader`](classloader.md) filtering out `sun.reflect.DelegatingClassLoader` issue
* [bug] [#129] fix [`classloader`](classloader.md) presenting structure issues
* [improvement] [#125] make the Arthas log output more readable
* [improvement] [#96] [`sc`](sc.md) and more commands are supporting format as `com/taobao/xxx/TestClass`
* [bug] [#124] fix the negative values of [`trace`](trace.md)
* [improvement] [#128] the output of [`tt`](tt.md) will auto-expand now
* [bug] [#130] providing more meaningful error messages when port conflicts
* [bug] [#98] fix Arthas starting issue: when updating/downloading failed, Arthas will fail to start
* [bug] [#139] fix agent attaching fails under some scenarios issues
* [improvement] [#156] delay `jd-core-java` initialization to avoid Arthas starting failure
* [bug] avoid thread names duplicate issue
* [improvement] [#150] filtering by total time cost in [`trace`](trace.md)
* [bug] fix [`sc`](sc.md) `NPE` issue when searching `SystemClassloader`
* [bug] [#180] fix attach fails issues: attaching succeed at the first time, delete the Arthas installer, re-compile and package => attaching fails
v2016-06-07
----
* [bug] fix NPE when loading `spy` as resource
* [improvement] locating the blocking thread
* [improvement] print out thread in name order
* [improvement] specify the refreshing interval when checking topN busiest threads
v2016-04-08
----
* [feature] specify refreshing interval and execution times in [`dashboard`](dashboard.md)
* [feature] log the command execution result
* [feature] speed up the booting and attaching while the first attaching is even quicker by 100% than before
* [feature] batch supported; script supported
* [feature] interactive mode used in Arthas
* [feature] inheritance relation included in class searching; global option `disable-sub-class` can be used to turn it off
* [feature] colorful and plain text modes both supported
* [improvement] merge `exit` and `quit` commands
* [improvement] help info enclosed with wiki links
* [improvement] optimize [`watch`](watch.md) using flow for better UX
* [improvement] add examples to [`thread`](thread.md)
* [improvement] auto-completion ignores character case
* [improvement] make the UI more beautiful/friendly
* [bug] fix [`trace`](trace.md) printing too much encountering loop issues
* [bug] fix [`trace`](trace.md) node twisting issues when method throwing exceptions
* [bug] fix injected/enhanced `BootstrapClassLoader` cannot locate `spy` issues
v2016-03-07
----
* [feature] checking the topN thread and related stack traces
* [bug] fix Arthas starting failure in OpenJdk issues (requiring to reinstall [as.sh](https://github.com/alibaba/arthas/blob/master/bin/as.sh))
* [improvement] optimize UX
v2016-01-18
----
* [improvement] optimise [`jad`](jad.md); dump memory byte array in real time; using `jd-core-java` to de-compile; line number presented;
* [bug] fix checking/re-producing issues when [`tt`](tt.md) is watching thread-context related methods invoking
v2016-01-08
----
* [bug] jad NPE
* [bug] watch/monitor NPE
* [bug] wrong escaping issues
* [bug] wrong statistics
* [bug] [`sc`](sc.md) checking internal structure issues
v2015-12-29
---
* Arthas 2.0 Beta :boom:!
+54
View File
@@ -0,0 +1,54 @@
reset
===
> Reset all classes that have been enhanced by Arthas, and all enhanced classes will be reset when Arthas server `shutdown`.
### Usage
```
$ reset -h
USAGE:
reset [-h] [-E] [class-pattern]
SUMMARY:
Reset all the enhanced classes
EXAMPLES:
reset
reset *List
reset -E .*List
OPTIONS:
-h, --help this help
-E, --regex Enable regular expression to match (wildcard matching by default)
<class-pattern> Path and classname of Pattern Matching
```
### Reset specified class
```
$ trace Test test
Press Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 57 ms.
`---ts=2017-10-26 17:10:33;thread_name=main;id=1;is_daemon=false;priority=5;TCCL=sun.misc.Launcher$AppClassLoader@14dad5dc
`---[0.590102ms] Test:test()
`---ts=2017-10-26 17:10:34;thread_name=main;id=1;is_daemon=false;priority=5;TCCL=sun.misc.Launcher$AppClassLoader@14dad5dc
`---[0.068692ms] Test:test()
$ reset Test
Affect(class-cnt:1 , method-cnt:0) cost in 11 ms.
```
### Reset all classes
```
$ trace Test test
Press Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 15 ms.
`---ts=2017-10-26 17:12:06;thread_name=main;id=1;is_daemon=false;priority=5;TCCL=sun.misc.Launcher$AppClassLoader@14dad5dc
`---[0.128518ms] Test:test()
$ reset
Affect(class-cnt:1 , method-cnt:0) cost in 9 ms.
```
+37
View File
@@ -0,0 +1,37 @@
Log command outputs
===================
Log command outputs for later analysis, turned off by default.
To turn it on, using [options](options.md) as:
```bash
$ options save-result true
NAME BEFORE-VALUE AFTER-VALUE
----------------------------------------
save-result false true
Affect(row-cnt:1) cost in 3 ms.
```
F.Y.I
1. logging file lies in: `{user.home}/logs/arthas-cache/result.log`;
2. remember to clean up the file to save disk space.
### Asynchronous log
:notes: :notes:
With the latest Arthas, you can log the outputs asynchronously in the background:
```bash
$ trace Test t >> &
job id : 2
cache location : /Users/zhuyong/logs/arthas-cache/28198/2
```
F.Y.I
1. `quit/exit` or `Ctrl+C` will not affect the asynchronous jobs :sparkles:;
2. default timeout for the background job is 1 day (you can set it via [options](options.md));
3. outputs will be save to the `cache location` now (no matter what `save-result` is - not `~/logs/arthas-cache/result.log` any more).
+3 -3
View File
@@ -3,7 +3,7 @@ sc
Check the profiles of the loaded classes.
Abbreviated from “Search-Class”; with the help of this command, you can search out all the loaded classes in JVM. Supported options are: `[d]`、`[E]`、`[f]` and `[x:]`.
Abbreviated from *Search-Class*; with the help of this command, you can search out all the loaded classes in JVM. Supported options are: `[d]`、`[E]`、`[f]` and `[x:]`.
Options
-------
@@ -16,12 +16,12 @@ Options
|*method-pattern*|pattern for the method name|
|[d]|print the details of the current class including the source file, class declaration, the class loaders and the like.<br/>F.Y.I if a class is loaded by several class loaders, then the class will be printed several times|
|[E]|turn on regx matching while the default is wildcards matching|
|[f]|print the fields info of the current class, which should be used along with `-d`|
|[f]|print the fields info of the current class, which ***must*** be used with `-d`|
|[x:]|the depth to print the static fields, whose default is `0` - directly invoke the `toString()`|
Tip:
1. *class-patten* supports full qualified class name (e.g. com.taobao.test.AAA and com/taobao/test/AAA)
2. `sc` turned on the `sub-class` matching in default mode, if you do want to hide the `sub-class` please just turn it off via `options disable-sub-class true`.
2. `sc` turned on the `sub-class` matching in default mode; if you do want to hide `sub-class`, you can just turn it off with [options](options.md) as `options disable-sub-class true`.
### Usage
+3 -3
View File
@@ -3,7 +3,7 @@ sm
Check the method profile of the loaded classes;
Abbreviated from “Search-Method”, with which you can search out all methods profiles of the loaded classes.
Abbreviated from *Search-Method*, with which you can check all methods profiles of the loaded classes.
F.Y.I
`sm` only shows the methods declared in the current class; methods declared in ancestors will not be presented.
@@ -15,7 +15,7 @@ F.Y.I
|*class-pattern*|pattern for class name|
|*method-pattern*|pattern for method name|
|[d]|print the details of the method|
|[E]|turn the regex matching on while the default mode is wildcards matching|
|[E]|turn on regex matching while the default mode is wildcard matching|
### Usage
@@ -61,7 +61,7 @@ org.apache.catalina.connector.Connector->getMaxCookieCount
```
```sh
```bash
$ sm org.apache.catalina.connector.Connector -d
declaring-class org.apache.catalina.connector.Connector
constructor-name <init>
+9 -9
View File
@@ -1,7 +1,7 @@
stack
=====
Print out the full call stack trace containing the current method.
Print out the full call stack trace *till* the current method.
Most of the time, we know the method being invoked but not always we know **HOW being invoked**; `stack` can be a great help to locate the *source* for you.
@@ -11,16 +11,16 @@ Most of the time, we know the method being invoked but not always we know **HOW
|---:|:---|
|*class-pattern*|pattern for the class name|
|*method-pattern*|pattern for the method name|
|*condition-express*|condition expression|
|[E]|turn on regx matching while the default is wildcards matching|
|`[n:]`|calling times|
|*condition-expression*|condition expression|
|[E]|turn on regex matching while the default is wildcard matching|
|[n:]|calling times|
F.Y.I
1. any valid OGNL expression as `"{params,returnObj}"` supported;
2. filter by time cost as `trace *StringUtils isBlank '$cost>100'`; calling stack with only time cost higher than `100ms` will be printed.
2. filter by time cost as `trace *StringUtils isBlank '#cost>100'`; calling stack with only time cost higher than `100ms` will be printed.
Attention:
1. `$cost` can be used in `watch/stack/trace`;
1. `#cost` can be used in `watch/stack/trace`;
2. using `#cost` in Arthas 3.0 instead of `$cost`.
@@ -32,7 +32,7 @@ Advanced:
### Usage
The quoting rules: if there are quotes within the expression, use another type of quotes to quote the whole expression.
The quoting rules: if there are quotes within the expression, use another type of quotes to quote the whole expression (single `''` or double `""` quotes).
```
$ stack com.alibaba.sample.petstore.dal.dao.ProductDao getProductById 'params[0]=="K9-BD-01"'
@@ -68,7 +68,7 @@ thread_name="http-bio-8080-exec-2" thread_id=0x48;is_daemon=true;priority=5;
at com.alibaba.citrus.service.pipeline.impl.PipelineImpl$PipelineContextImpl.invoke(PipelineImpl.java:210)
at com.alibaba.citrus.service.pipeline.impl.valve.ChooseValve.invoke(ChooseValve.java:98)
at com.alibaba.citrus.service.pipeline.impl.PipelineImpl$PipelineContextImpl.invokeNext(PipelineImpl.java:157)
......
...
```
Filtering by time cost:
@@ -110,5 +110,5 @@ thread_name=http-nio-8080-exec-10;id=31;is_daemon=true;priority=5;TCCL=com.taoba
at com.alibaba.citrus.webx.impl.WebxControllerImpl.service(WebxControllerImpl.java:43)
at com.alibaba.citrus.webx.impl.WebxRootControllerImpl.handleRequest(WebxRootControllerImpl.java:53)
at com.alibaba.citrus.webx.support.AbstractWebxRootController.service(AbstractWebxRootController.java:165)
.........
...
```
+1 -1
View File
@@ -7,7 +7,7 @@ Start Arthas
./as.sh
```
```sh
```bash
➜ bin git:(develop) ✗ ./as.sh
Found existing java process, please choose one and hit RETURN.
[1]: 3088 org.jetbrains.idea.maven.server.RemoteMavenServer
+2 -2
View File
@@ -100,7 +100,7 @@ $ thread 1
Using `-b`, we can effectively locate the threads holding locks blocking other threads resulting in a frozen system.
```sh
```bash
$ thread -b
"http-bio-8080-exec-4" Id=27 TIMED_WAITING
at java.lang.Thread.sleep(Native Method)
@@ -144,7 +144,7 @@ $ thread -b
#### thread -i specify the collecting interval
```sh
```bash
$ thread -n 3 -i 1000
"as-command-execute-daemon" Id=4759 cpuUsage=23% RUNNABLE
at sun.management.ThreadImpl.dumpThreads0(Native Method)
+7 -8
View File
@@ -1,7 +1,7 @@
trace
=====
Track the `class-pattern` & `method-pattern` matched method calling trace and print the time cost in each call.
Track methods calling stack trace and print the time cost in each call.
### Parameters
@@ -11,19 +11,18 @@ Track the `class-pattern` & `method-pattern` matched method calling trace and pr
|*method-pattern*|pattern for the method name|
|*condition-express*|condition expression|
|[E]|turn on regx matching while the default is wildcards matching|
|`[n:]`|calling times|
|`#cost`|time cost|
|[n:]|calling times|
|#cost|time cost|
F.Y.I
1. any valid OGNL expression as `"{params,returnObj}"` supported;
2. filter by time cost as `trace *StringUtils isBlank '$cost>100'`; calling stack with only time cost higher than `100ms` will be printed.
2. filter by time cost as `trace *StringUtils isBlank '#cost>100'`; calling stack with only time cost higher than `100ms` will be printed.
Attention:
1. `$cost` can be used in `watch/stack/trace`;
1. `#cost` can be used in `watch/stack/trace`;
2. using `#cost` in Arthas 3.0 instead of `$cost`.
3. `trace` can help to locate the performance lurking issue but only `level-one` method invoking considered.
Advanced:
* [Critical fields in expression](advice-class.md)
* [Special usage](https://github.com/alibaba/arthas/issues/71)
@@ -101,8 +100,8 @@ trace com.alibaba.sample.petstore.web.store.module.screen.ItemList execute #cost
Only the calling trace of the time cost higher than `4ms`presented now.
F.Y.I
1. just like JProfile and the like commercial software, you can `trace` down the specified method calling in Arthas;
1. like JProfile and other similar commercial software, you can `trace` down the specified method calling stack with time cost in Arthas;
2. there will be some overhead using `trace` but not much;
3. the time cost is an instructive clue for troubleshooting, which means it's not that accurate ignoring the cost it itself causes; the deeper or more the call is, the accuracy is becoming worse;
3. the time cost is an instructive clue for troubleshooting, which means it's not that accurate ignoring the cost it itself causes; the deeper or more the call is, the worse accuracy the time cost will be;
4. `[0,0,0ms,11]xxx:yyy() [throws Exception]`,the same method calling aggregated into one line here while `throws Exception` indicates there is an exception.
+12 -12
View File
@@ -1,13 +1,13 @@
tt
==
Check the parameters, return values and exceptions of the methods at different times.
Check the `parameters`, `return values` and `exceptions` of the methods at different times.
`watch` is a powerful command but due to its feasibility and complexity, it's quite hard to locate the issue effectively.
In such difficulties, `tt` comes into play.
With the help of `tt` (abbreviated from *TimeTunnel*), you can check the contexts of the methods at different times.
With the help of `tt` (*TimeTunnel*), you can check the contexts of the methods at different times in execution history.
### Usage
@@ -37,7 +37,7 @@ Let's record the whole calling contexts:
- `-n 3`
limit the number of the records (avoid overflow for too many records; with `-n` option, Arthas can automatically stop recording once the records reach the limit)
limit the number of the records (avoid overflow for too many records; with `-n` option, Arthas can automatically stop recording once the records reach the specified limit)
#### Property
@@ -46,8 +46,8 @@ Let's record the whole calling contexts:
|INDEX|the index for each call based on time|
|TIMESTAMP|time to invoke the method|
|COST(ms)|time cost of the method call|
|IS-RET|end with normal return|
|IS-EXP|end with exceptions|
|IS-RET|whether method exits with normal return|
|IS-EXP|whether method failed with exceptions|
|OBJECT|`hashCode()` of the object invoking the method|
|CLASS|class name of the object invoking the method|
|METHOD|method being invoked|
@@ -55,7 +55,7 @@ Let's record the whole calling contexts:
#### Condition expression
Tips:
1. `tt -t *Test print params[0].length==1` with different amount of parameters;
1. `tt -t *Test print params[0].length==1` with different amounts of parameters;
2. `tt -t *Test print 'params[1] instanceof Integer'` with different types of parameters;
3. `tt -t *Test print params[0].mobile=="13989838402"` with specified parameter.
@@ -67,7 +67,7 @@ Advanced:
### Searching for records
#### A specified time range
#### All the recorded
```
$ tt -l
@@ -112,7 +112,7 @@ Advanced:
### Check context of the call
Using `tt -i <index>` to check a specific record.
Using `tt -i <index>` to check a specific calling details.
```
$
@@ -147,7 +147,7 @@ $
### Re-produce
Since Arthas stores the context of the call, you can even re-produce the method calling after some modifications with extra option `-p`.
Since Arthas stores the context of the call, you can even *replay* the method calling afterwards with extra option `-p` to re-produce the issue for advanced troubleshooting.
```
$ tt -i 1003 -p
@@ -189,6 +189,6 @@ $
```
F.Y.I
1. the calling stack is little different using Arthas now instead of the original method;
2. **Loss** of the thread local variables will be a fact since there is no way for Arthas to record the thread local info.
3. **Potential** modifications of objects can happen since only a reference will be recorded by Arthas while later process might modify objects without Arthas's watch.
1. the calling stack is little different using Arthas now unlike the original;
2. **Loss** of the thread local variables will be a undeniable fact since there is no way for Arthas to record the thread local info (*If you find one, please share with us in [issues tracker](https://github.com/alibaba/arthas/issues)*).
3. **Potential** modifications of objects can happen since only a reference will be recorded while later operations might modify objects without Arthas's watch.
+20 -20
View File
@@ -1,38 +1,38 @@
watch
=====
Monitor the methods in data aspect including `return value`, `exceptions` and `parameters`.
Monitor methods in data aspect including `return values`, `exceptions` and `parameters`.
With the help of [OGNL](https://en.wikipedia.org/wiki/OGNL), you can easily check the details of the variables.
With the help of [OGNL](https://en.wikipedia.org/wiki/OGNL), you can easily check the details of variables when methods being invoked.
### Parameters & Options
There are four different usage scenarios for `watch` command, which makes it the most complicated command in Arthas.
There are four different scenarios for `watch` command, which makes it rather complicated.
|Name|Specification|
|---:|:---|
|*class-pattern*|pattern for the class name|
|*method-pattern*|pattern for the method name|
|*express*|expression to monitor|
|*condition-express*|condition expression|
|[b]|before invoking|
|[e]|encountering exceptions|
|[s]|returned normally|
|[f]|returned normally and abnormally|
|[E]|turn on regx matching while the default is wildcards matching|
|*expression*|expression to monitor|
|*condition-expression*|condition expression to filter|
|[b]|before method being invoked|
|[e]|when method encountering exceptions|
|[s]|when method exits normally|
|[f]|when method exits (either succeed or fail with exceptions)|
|[E]|turn on regex matching while the default is wildcard matching|
|[x:]|the depth to print the specified property with default value: 1|
F.Y.I
1. any valid OGNL expression as `"{params,returnObj}"` supported
2. there are four *watching* points: `-b`, `-e`, `-s` and `-f` (the first three are off in default while `-f` on);
3. at the *watching* point, Arthas will use the `expression` to calculate the values and print them out;
4. `in-parameters` and `out-parameters` are different since they can be modified; `params` stands for `in-parameters` in `-b`while `out-parameters` in other *watching* points;
5. there is no `return value` and `exceptions` when using `-b`.
3. at the *watching* point, Arthas will use the *expression* to evaluate the variables and print them out;
4. `in parameters` and `out parameters` are different since they can be modified within the invoked methods; `params` stands for `in parameters` in `-b`while `out parameters` in other *watching* points;
5. there are no `return values` and `exceptions` when using `-b`.
Advanced:
* [Critical fields in expression](advice-class.md)
* [Special usage](https://github.com/alibaba/arthas/issues/71)
* [Critical fields in *expression*](advice-class.md)
* [Special usages](https://github.com/alibaba/arthas/issues/71)
* [OGNL official guide](https://commons.apache.org/proper/commons-ognl/language-guide.html)
### Usage
@@ -57,7 +57,7 @@ A demo:
return list.size();
}
```
#### Check the `out-parameters`and `return value`
#### Check the `out parameters` and `return value`
```shell
$ watch com.alibaba.sample.petstore.web.store.module.screen.ItemList add "{params,returnObj}" -x 2
@@ -73,7 +73,7 @@ Affect(class-cnt:1 , method-cnt:1) cost in 44 ms.
]
```
#### Check `in-parameters`
#### Check `in parameters`
```shell
$ watch com.alibaba.sample.petstore.web.store.module.screen.ItemList add "{params,returnObj}" -x 2 -b
@@ -89,7 +89,7 @@ Affect(class-cnt:1 , method-cnt:1) cost in 48 ms.
]
```
Compared to the previous *check*:
Compared to the previous *check*, there are two differences:
1. size of `params[0]` is `2` instead of `4`;
2. `return value` is `null` since it's `-b`.
@@ -122,7 +122,7 @@ F.Y.I
1. the first block of output is the *before watching* point;
2. the order of the output determined by the *watching* order itself (nothing to do with the order of the options `-b -s`).
#### Using `-x` to check more details
#### Use `-x` to check more details
```shell
$ watch com.alibaba.sample.petstore.web.store.module.screen.ItemList add "{params,returnObj}" -x 3
@@ -150,7 +150,7 @@ Affect(class-cnt:1 , method-cnt:1) cost in 59 ms.
]
```
#### Using condition expressions to locate specific call
#### Use condition expressions to locate specific call
```shell
$ watch com.alibaba.sample.petstore.biz.impl.UserManagerImpl testAdd "{params, returnObj}" "params[0].equals('aaa')" -x 2
+11
View File
@@ -0,0 +1,11 @@
Web Console
===
Arthas supports the Web Console. After attach success, the user can access: [http://localhost:8563/](http://localhost:8563/).
The user can fill in the IP and connect the remote arthas on other machines.
![web console](_static/web-console-local.png)
If you have suggestions for the Web Console, please leave a message here: [https://github.com/alibaba/arthas/issues/15](https://github.com/alibaba/arthas/issues/15)
+1 -1
View File
@@ -119,7 +119,7 @@ Affect(row-cnt:1) cost in 190 ms.
反编译指定的方法:
```sh
```bash
$ jad com.taobao.container.web.arthas.rest.MetricsController directMetrics
ClassLoader:
+13 -2
View File
@@ -87,6 +87,11 @@ $ jvm
PEAK-COUNT 18
STARTED-COUNT 19
DEADLOCK-COUNT 0
FILE-DESCRIPTOR
MAX-FILE-DESCRIPTOR-COUNT 10240
OPEN-FILE-DESCRIPTOR-COUNT 648
Affect cost in 2 ms.
```
@@ -95,5 +100,11 @@ Affect cost in 2 ms.
* COUNT: JVM当前活跃的线程数
* DAEMON-COUNT: JVM当前活跃的守护线程数
* LIVE-COUNT: 从JVM启动开始曾经活着的最大线程数
* STARTED-COUNT: 从jvm启动开始总共启动过的线程次数
* PEAK-COUNT: 从JVM启动开始曾经活着的最大线程数
* STARTED-COUNT: 从JVM启动开始总共启动过的线程次数
* DEADLOCK-COUNT: JVM当前死锁的线程数
### 文件描述符相关
* MAX-FILE-DESCRIPTOR-COUNT:JVM进程最大可以打开的文件描述符数
* OPEN-FILE-DESCRIPTOR-COUNT:JVM当前打开的文件描述符数
+4 -4
View File
@@ -1,7 +1,7 @@
Arthas 3.0命令行快捷键
Arthas 命令行快捷键
===
keymap命令输出当前的快捷键映射表:
`keymap`命令输出当前的快捷键映射表:
默认的快捷键如下:
@@ -17,8 +17,8 @@ keymap命令输出当前的快捷键映射表:
| `"\C-b"` | ctrl + b | backward-word | 向后移动一个单词 |
| `"\e[D"` | 键盘左方向键 | backward-char | 光标向前移动一个字符 |
| `"\e[C"` | 键盘右方向键 | forward-char | 光标向后移动一个字符 |
| `"\e[B"` | 键盘下方向键 | next-history | 上翻显示上一个命令 |
| `"\e[A"` | 键盘上方向键 | previous-history | 下翻显示下一个命令 |
| `"\e[B"` | 键盘下方向键 | next-history | 下翻显示下一个命令 |
| `"\e[A"` | 键盘上方向键 | previous-history | 上翻显示上一个命令 |
| `"\C-h"` | ctrl + h | backward-delete-char | 向后删除一个字符 |
| `"\C-?"` | ctrl + shift + / | backward-delete-char | 向后删除一个字符 |
| `"\C-u"` | ctrl + u | undo | 撤销上一个命令,相当于清空当前行 |
+1 -1
View File
@@ -1,7 +1,7 @@
reset命令
===
> 重置增强类,将被 Arthas 增强过的类全部还原,Arthas 服务端关闭时会重置所有增强过的类
> 重置增强类,将被 Arthas 增强过的类全部还原,Arthas 服务端`shutdown`时会重置所有增强过的类
### 使用参考
+2 -2
View File
@@ -5,7 +5,7 @@
* 默认情况下,该功能是关闭的,如果需要开启,请执行以下命令:
```sh
```bash
$ options save-result true
NAME BEFORE-VALUE AFTER-VALUE
----------------------------------------
@@ -21,7 +21,7 @@ Affect(row-cnt:1) cost in 3 ms.
### 使用新版本Arthas的异步后台任务将结果存日志文件
```sh
```bash
$ trace Test t >> &
job id : 2
cache location : /Users/zhuyong/logs/arthas-cache/28198/2
+1 -1
View File
@@ -60,7 +60,7 @@ org.apache.catalina.connector.Connector->getMaxCookieCount
```
```sh
```bash
$ sm org.apache.catalina.connector.Connector -d
declaring-class org.apache.catalina.connector.Connector
constructor-name <init>
+1 -1
View File
@@ -7,7 +7,7 @@
./as.sh
```
```sh
```bash
➜ bin git:(develop) ✗ ./as.sh
Found existing java process, please choose one and hit RETURN.
[1]: 3088 org.jetbrains.idea.maven.server.RemoteMavenServer
+2 -2
View File
@@ -99,7 +99,7 @@ $ thread 1
有时候我们发现应用卡住了, 通常是由于某个线程拿住了某个锁, 并且其他线程都在等待这把锁造成的。 为了排查这类问题, arthas提供了`thread -b`, 一键找出那个罪魁祸首。
```sh
```bash
$ thread -b
"http-bio-8080-exec-4" Id=27 TIMED_WAITING
at java.lang.Thread.sleep(Native Method)
@@ -143,7 +143,7 @@ $ thread -b
#### thread -i, 指定采样时间间隔
```sh
```bash
$ thread -n 3 -i 1000
"as-command-execute-daemon" Id=4759 cpuUsage=23% RUNNABLE
at sun.management.ThreadImpl.dumpThreads0(Native Method)