remove katacoda

pull/2798/head
hengyunabc 1 year ago
parent 2f5ab94032
commit 18ea7d2736

@ -1 +0,0 @@
scenario_root : tutorials/katacoda

@ -1,37 +0,0 @@
# Interactive Katacoda Online Tutorials for Arthas
[![](http://shields.katacoda.com/katacoda/arthas/count.svg)](https://www.katacoda.com/arthas "Get your profile on Katacoda.com")
[中文说明/Chinese Documentation](README_CN.md)
## Online Tutorial Usages
1. First visit the online tutorial: https://arthas.aliyun.com/doc/arthas-tutorials.html?language=en , select the course you want to study from the menu:
![](https://user-images.githubusercontent.com/43995067/90310125-2a9bf480-df21-11ea-819d-2713f22f4145.png)
2. The course introduction page will indicate the difficulty of the course and the time required to help you understand the basic information of the course. click `START SCENARIO` to start learning.
![](https://user-images.githubusercontent.com/43995067/90310168-9ed69800-df21-11ea-93cf-a01b4a41c66b.png)
3. Enter the course, the left side is the description of this step, and the right side is a ready terminal, which can be used directly. Click the black blocks on the left to execute commands in the right:
![](https://user-images.githubusercontent.com/43995067/90310223-3d62f900-df22-11ea-936c-deb950e61f9e.png)
4. Click the tab on the right to switch between terminals. Then follow the step-by-step instructions to complete the learning step by step:
![](https://user-images.githubusercontent.com/43995067/90310282-b8c4aa80-df22-11ea-8052-3799277b748e.png)
## Contribution Guide
If you want to contribute to the Arthas online tutorials, you are welcome to submit pull requests for the Arthas online tutorials.
Visit https://www.katacoda.com/docs to learn more about creating Katacoda scenarios. You can also refer to the article of Alibaba cloud developer community here(In Chinese): https://developer.aliyun.com/article/752183
For examples of the scenarios folder, visit https://github.com/katacoda/scenario-example
After that, if you have finished doing writing jobs, You just need to put your scenarios folder here in this folder, and add links in the related pages, that's all.
Menu page source code is at https://github.com/alibaba/arthas/blob/master/site/src/site/sphinx/_include_html/arthas-tutorials.html
## About
This project is a part of [Alibaba Summer of Code 2020](https://www.alibabacloud.com/campaign/summerofcode2020) done by [@HollowMan6](https://github.com/HollowMan6), for more information please visit: https://github.com/HollowMan6/My-Alibaba-Summer-of-Code
Issue: [#847](https://github.com/alibaba/arthas/issues/847)

@ -1,37 +0,0 @@
# Arthas交互式Katacoda在线教程
[![](http://shields.katacoda.com/katacoda/arthas/count.svg)](https://www.katacoda.com/arthas "Get your profile on Katacoda.com")
English version goes [here](README.md).
## 在线教程使用方法
1. 首先访问在线教程https://arthas.aliyun.com/doc/arthas-tutorials.html?language=cn ,从菜单中选择你想要学习的课程:
![](https://images.gitee.com/uploads/images/2020/0814/211330_e71ef0ca_7637131.png)
2. 课程介绍页面会标明课程的难度和需要的时间,帮助你了解该课程的基本信息。点击`START SCENARIO`开始学习。
![](https://images.gitee.com/uploads/images/2020/0814/212507_4a02d8aa_7637131.png)
3. 进入课程,左侧是该步骤说明,右侧是一个已经准备好的终端,直接可以使用。点击左侧黑块部分就可以在右侧执行:
![](https://images.gitee.com/uploads/images/2020/0814/213005_62d85818_7637131.png)
4. 点击右侧标签可以切换终端。之后就是跟着步骤说明,一步步的完成学习即可:
![](https://images.gitee.com/uploads/images/2020/0814/213458_43bb4e3f_7637131.png)
## 贡献指南
如果你想为Arthas在线教程做出贡献欢迎为Arthas在线教程提交Pull Request。
访问https://www.katacoda.com/docs 来了解更多创建Katacoda教程的信息也可以参考这里的一篇阿里云开发者社区的推送https://developer.aliyun.com/article/752183
Katacoda教程文件夹的示例https://github.com/katacoda/scenario-example
之后,如果你已经完成了编写,你只需要把你的教程文件夹放在此文件夹,并在相关页面中添加链接。
菜单页面源代码位于https://github.com/alibaba/arthas/blob/master/site/src/site/sphinx/_include_html/arthas-tutorials.html
## 关于
此项目为[阿里巴巴编程之夏2020](https://developer.aliyun.com/topic/summerofcode2020)的一部分,由[@HollowMan6](https://github.com/HollowMan6)完成更多信息请参见https://github.com/HollowMan6/My-Alibaba-Summer-of-Code
Issue: [#847](https://github.com/alibaba/arthas/issues/847)

@ -1,30 +0,0 @@
`arthas-boot.jar` 支持很多参数,可以执行 `java -jar arthas-boot.jar -h`{{execute T2}} 来查看。
## 允许外部访问
默认情况下, arthas server侦听的是 `127.0.0.1` 这个IP如果希望远程可以访问可以使用`--target-ip`的参数。
`java -jar arthas-boot.jar --target-ip`{{execute T2}}
## 列出所有的版本
`java -jar arthas-boot.jar --versions`{{execute T2}}
使用指定版本:
`java -jar arthas-boot.jar --use-version 3.1.0`{{execute T2}}
## 只侦听Telnet端口不侦听HTTP端口
`java -jar arthas-boot.jar --telnet-port 9999 --http-port -1`{{execute T2}}
## 打印运行的详情
`java -jar arthas-boot.jar -v`{{execute T2}}

@ -1,16 +0,0 @@
在新的`Terminal 2`里,下载`arthas-boot.jar`,再用`java -jar`命令启动:
`wget https://arthas.aliyun.com/arthas-boot.jar
java -jar arthas-boot.jar --target-ip 0.0.0.0`{{execute T2}}
`arthas-boot`是`Arthas`的启动程序它启动后会列出所有的Java进程用户可以选择需要诊断的目标进程。
选择第一个进程,输入 `1`{{execute T2}} ,再`Enter/回车`
Attach成功之后会打印Arthas LOGO。输入 `help`{{execute T2}} 可以获取到更多的帮助信息。
![Arthas Boot](/arthas/scenarios/common-resources/assets/arthas-boot.png)

@ -1,139 +0,0 @@
下面介绍`classloader`命令的功能。
先访问一个jsp网页触发jsp的加载 https://[[HOST_SUBDOMAIN]]-80-[[KATACODA_HOST]].environments.katacoda.com/hello
### 列出所有ClassLoader
`classloader -l`{{execute T2}}
```bash
$ classloader -l
name loadedCount hash parent
BootstrapClassLoader 2724 null null
com.taobao.arthas.agent.ArthasClassloader@411ce1ab 2009 411ce1ab sun.misc.Launcher$ExtClassLoader@7494e528
com.taobao.arthas.agent.ArthasClassloader@22ae1234 1253 22ae1234 sun.misc.Launcher$ExtClassLoader@7494e528
org.apache.jasper.servlet.JasperLoader@65361d9a 1 65361d9a TomcatEmbeddedWebappClassLoader
context: ROOT
delegate: true
----------> Parent Classloader:
org.springframework.boot.loader.LaunchedURLClassLoader@1be6f5c3
TomcatEmbeddedWebappClassLoader 0 8546cd5 org.springframework.boot.loader.LaunchedURLClassLoader@1be6f5c3
context: ROOT
delegate: true
----------> Parent Classloader:
org.springframework.boot.loader.LaunchedURLClassLoader@1be6f5c3
org.springframework.boot.loader.LaunchedURLClassLoader@1be6f5c3 5416 1be6f5c3 sun.misc.Launcher$AppClassLoader@3d4eac69
sun.misc.Launcher$AppClassLoader@3d4eac69 45 3d4eac69 sun.misc.Launcher$ExtClassLoader@7494e528
sun.misc.Launcher$ExtClassLoader@7494e528 4 7494e528 null
```
* TomcatEmbeddedWebappClassLoader 加载的class数量是0所以在spring boot embedded tomcat里它只是一个空壳所有的类加载都是`LaunchedURLClassLoader`完成的
### 列出ClassLoader里加载的所有类
列出上面的`org.apache.jasper.servlet.JasperLoader`加载的类:
`classloader -a --classLoaderClass org.apache.jasper.servlet.JasperLoader`{{execute T2}}
```bash
$ classloader -a --classLoaderClass apache.jasper.servlet.JasperLoader
hash:1698045338, org.apache.jasper.servlet.JasperLoader@65361d9a
org.apache.jsp.jsp.hello_jsp
```
* 注同ognl, 也可用`-c <hashcode>`而不用`--classLoaderClass`指定
### 反编译jsp的代码
`jad org.apache.jsp.jsp.hello_jsp`{{execute T2}}
```bash
$ jad org.apache.jsp.jsp.hello_jsp
ClassLoader:
+-org.apache.jasper.servlet.JasperLoader@65361d9a
+-TomcatEmbeddedWebappClassLoader
context: ROOT
...
```
### 查看ClassLoader树
`classloader -t`{{execute T2}}
```
$ classloader -t
+-BootstrapClassLoader
+-sun.misc.Launcher$ExtClassLoader@28cbbddd
+-com.taobao.arthas.agent.ArthasClassloader@8c25e55
+-sun.misc.Launcher$AppClassLoader@55f96302
+-org.springframework.boot.loader.LaunchedURLClassLoader@1be6f5c3
+-TomcatEmbeddedWebappClassLoader
context: ROOT
delegate: true
----------> Parent Classloader:
org.springframework.boot.loader.LaunchedURLClassLoader@1be6f5c3
+-org.apache.jasper.servlet.JasperLoader@21ae0fe2
```
注意请使用你的classLoaderHash值覆盖 `<classLoaderHash>` ,然后手动执行下面相关命令:
### 列出ClassLoader的urls
比如上面查看到的spring LaunchedURLClassLoader的 hashcode是`1be6f5c3`,可以通过`-c`或者`--classLoaderClass`参数来列出它的所有urls
`classloader --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader`{{execute T2}}
```
$ classloader --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader
jar:file:/home/scrapbook/tutorial/demo-arthas-spring-boot.jar!/BOOT-INF/classes!/
jar:file:/home/scrapbook/tutorial/demo-arthas-spring-boot.jar!/BOOT-INF/lib/spring-boot-starter-aop-1.5
.13.RELEASE.jar!/
...
```
### 加载指定ClassLoader里的资源文件
查找指定的资源文件: `classloader --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader -r logback-spring.xml`{{execute T2}}
```
$ classloader --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader -r logback-spring.xml
jar:file:/home/scrapbook/tutorial/demo-arthas-spring-boot.jar!/BOOT-INF/classes!/logback-spring.xml
```
### 尝试加载指定的类
比如用上面的spring LaunchedURLClassLoader 尝试加载 `java.lang.String`
`classloader --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader --load java.lang.String`{{execute T2}}
```
$ classloader --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader --load java.lang.String
load class success.
class-info java.lang.String
code-source
name java.lang.String
isInterface false
isAnnotation false
isEnum false
isAnonymousClass false
isArray false
isLocalClass false
isMemberClass false
isPrimitive false
isSynthetic false
simple-name String
modifier final,public
annotation
interfaces java.io.Serializable,java.lang.Comparable,java.lang.CharSequence
super-class +-java.lang.Object
class-loader
classLoaderHash null
```

@ -1,54 +0,0 @@
在这个案例里展示获取spring context再获取bean然后调用函数。
### 使用tt命令获取到spring context
`tt`即 TimeTunnel它可以记录下指定方法每次调用的入参和返回信息并能对这些不同的时间下调用进行观测。
* https://arthas.aliyun.com/doc/tt.html
`tt -t org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter invokeHandlerMethod`{{execute T2}}
访问https://[[HOST_SUBDOMAIN]]-80-[[KATACODA_HOST]].environments.katacoda.com/user/1
可以看到`tt`命令捕获到了一个请求:
```bash
$ tt -t org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdaptePress Q or Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 252 ms.
INDE TIMESTAMP COST( IS-R IS- OBJECT CLASS METHOD
X ms) ET EXP
-----------------------------------------------------------------------------------------
1000 2019-02-15 4.583 true fal 0xc93cf1a RequestMappingHand invokeHandlerMethod
15:38:32 923 se lerAdapter
```
### 使用tt命令从调用记录里获取到spring context
输入 `Q`{{execute T2}} 或者 `Ctrl + C` 退出上面的 `tt -t`命令。
`tt -i 1000 -w 'target.getApplicationContext()'`{{execute T2}}
```bash
$ tt -i 1000 -w 'target.getApplicationContext()'
@AnnotationConfigEmbeddedWebApplicationContext[
reader=@AnnotatedBeanDefinitionReader[org.springframework.context.annotation.AnnotatedBeanDefinitionReader@2e457641],
scanner=@ClassPathBeanDefinitionScanner[org.springframework.context.annotation.ClassPathBeanDefinitionScanner@6eb38026],
annotatedClasses=null,
basePackages=null,
]
Affect(row-cnt:1) cost in 439 ms.
```
## 获取spring bean并调用函数
`tt -i 1000 -w 'target.getApplicationContext().getBean("helloWorldService").getHelloMessage()'`{{execute T2}}
结果是:
```bash
$ tt -i 1000 -w 'target.getApplicationContext().getBean("helloWorldService").getHelloMessage()'
@String[Hello World]
Affect(row-cnt:1) cost in 52 ms.
```

@ -1,53 +0,0 @@
在这个案例里展示排查HTTP 401问题的技巧。
访问: https://[[HOST_SUBDOMAIN]]-80-[[KATACODA_HOST]].environments.katacoda.com/admin
结果是:
```
Something went wrong: 401 Unauthorized
```
我们知道`401`通常是被权限管理的`Filter`拦截了,那么到底是哪个`Filter`处理了这个请求返回了401
### 跟踪所有的Filter函数
开始trace
`trace javax.servlet.Filter *`{{execute T2}}
访问: https://[[HOST_SUBDOMAIN]]-80-[[KATACODA_HOST]].environments.katacoda.com/admin
可以在调用树的最深层,找到`AdminFilterConfig$AdminFilter`返回了`401`
```
+---[3.806273ms] javax.servlet.FilterChain:doFilter()
| `---[3.447472ms] com.example.demo.arthas.AdminFilterConfig$AdminFilter:doFilter()
| `---[0.17259ms] javax.servlet.http.HttpServletResponse:sendError()
```
### 通过stack获取调用栈
上面是通过`trace`命令来获取信息,从结果里,我们可以知道通过`stack`跟踪`HttpServletResponse:sendError()`,同样可以知道是哪个`Filter`返回了`401`
执行:
`stack javax.servlet.http.HttpServletResponse sendError 'params[0]==401'`{{execute T2}}
访问: https://[[HOST_SUBDOMAIN]]-80-[[KATACODA_HOST]].environments.katacoda.com/admin
```bash
$ stack javax.servlet.http.HttpServletResponse sendError 'params[0]==401'
Press Q or Ctrl+C to abort.
Affect(class-cnt:2 , method-cnt:4) cost in 87 ms.
ts=2019-02-15 16:44:06;thread_name=http-nio-8080-exec-6;id=16;is_daemon=true;priority=5;TCCL=org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedWebappClassLoader@8546cd5
@org.apache.catalina.connector.ResponseFacade.sendError()
at com.example.demo.arthas.AdminFilterConfig$AdminFilter.doFilter(AdminFilterConfig.java:38)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
```

@ -1,39 +0,0 @@
在这个案例里展示排查HTTP 404问题的技巧。
访问: https://[[HOST_SUBDOMAIN]]-80-[[KATACODA_HOST]].environments.katacoda.com/a.txt
结果是:
```
Something went wrong: 404 Not Found
```
那么到底是哪个Servlet处理了这个请求返回了404
### 跟踪所有的Servlet函数
开始trace
`trace javax.servlet.Servlet * > /tmp/servlet.txt`{{execute T2}}
访问: https://[[HOST_SUBDOMAIN]]-80-[[KATACODA_HOST]].environments.katacoda.com/a.txt
在`Terminal 3`里,查看`/tmp/servlet.txt`的内容:
`less /tmp/servlet.txt`{{execute T3}}
`/tmp/servlet.txt`里的内容会比较多,需要耐心找到调用树里最长的地方。
可以发现请求最终是被`freemarker`处理的:
```
`---[13.974188ms] org.springframework.web.servlet.ViewResolver:resolveViewName()
+---[0.045561ms] javax.servlet.GenericServlet:<init>()
+---[min=0.045545ms,max=0.074342ms,total=0.119887ms,count=2] org.springframework.web.servlet.view.freemarker.FreeMarkerView$GenericServletAdapter:<init>()
+---[0.170895ms] javax.servlet.GenericServlet:init()
| `---[0.068578ms] javax.servlet.GenericServlet:init()
| `---[0.021793ms] javax.servlet.GenericServlet:init()
`---[0.164035ms] javax.servlet.GenericServlet:getServletContext()
```

@ -1,89 +0,0 @@
下面介绍通过`jad`/`mc`/`redefine` 命令实现动态更新代码的功能。
目前,访问 http://localhost/user/0 会返回500异常
`curl http://localhost/user/0`{{execute T3}}
```
{"timestamp":1550223186170,"status":500,"error":"Internal Server Error","exception":"java.lang.IllegalArgumentException","message":"id < 1","path":"/user/0"}
```
下面通过热更新代码,修改这个逻辑。
### jad反编译UserController
`jad --source-only com.example.demo.arthas.user.UserController > /tmp/UserController.java`{{execute T2}}
jad反编译的结果保存在 `/tmp/UserController.java`文件里了。
再打开一个`Terminal 3`然后用vim来编辑`/tmp/UserController.java`
`vim /tmp/UserController.java`{{execute T3}}
比如当 user id 小于1时也正常返回不抛出异常
```java
@GetMapping(value={"/user/{id}"})
public User findUserById(@PathVariable Integer id) {
logger.info("id: {}", (Object)id);
if (id != null && id < 1) {
return new User(id, "name" + id);
// throw new IllegalArgumentException("id < 1");
}
return new User(id.intValue(), "name" + id);
}
```
### sc查找加载UserController的ClassLoader
`sc -d *UserController | grep classLoaderHash`{{execute T2}}
```bash
$ sc -d *UserController | grep classLoaderHash
classLoaderHash 1be6f5c3
```
可以发现是 spring boot `LaunchedURLClassLoader@1be6f5c3` 加载的。
请记下你的classLoaderHash后面需要使用它。在这里它是 `1be6f5c3`
### mc
保存好`/tmp/UserController.java`之后,使用`mc`(Memory Compiler)命令来编译,并且通过`-c`或者`--classLoaderClass`参数指定ClassLoader
`mc --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader /tmp/UserController.java -d /tmp`{{execute T2}}
```bash
$ mc --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader /tmp/UserController.java -d /tmp
Memory compiler output:
/tmp/com/example/demo/arthas/user/UserController.class
Affect(row-cnt:1) cost in 346 ms
```
也可以通过`mc -c <classLoaderHash> /tmp/UserController.java -d /tmp`,使用`-c`参数指定ClassLoaderHash:
```bash
$ mc -c 1be6f5c3 /tmp/UserController.java -d /tmp
```
### redefine
再使用`redefine`命令重新加载新编译好的`UserController.class`
`redefine /tmp/com/example/demo/arthas/user/UserController.class`{{execute T2}}
```
$ redefine /tmp/com/example/demo/arthas/user/UserController.class
redefine success, size: 1
```
### 热修改代码结果
`redefine`成功之后,再次访问 https://[[HOST_SUBDOMAIN]]-80-[[KATACODA_HOST]].environments.katacoda.com/user/0 ,结果是:
```
{
"id": 0,
"name": "name0"
}
```

@ -1,52 +0,0 @@
在这个案例里展示排查logger冲突的方法。
### 确认应用使用的logger系统
以`UserController`为例它使用的是slf4j api但实际使用到的logger系统是logback。
`ognl --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader '@com.example.demo.arthas.user.UserController@logger'`{{execute T2}}
```bash
$ ognl --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader '@com.example.demo.arthas.user.UserController@logger'
@Logger[
serialVersionUID=@Long[5454405123156820674],
FQCN=@String[ch.qos.logback.classic.Logger],
name=@String[com.example.demo.arthas.user.UserController],
level=null,
effectiveLevelInt=@Integer[20000],
parent=@Logger[Logger[com.example.demo.arthas.user]],
childrenList=null,
aai=null,
additive=@Boolean[true],
loggerContext=@LoggerContext[ch.qos.logback.classic.LoggerContext[default]],
]
```
### 获取logback实际加载的配置文件
`ognl --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader '#map1=@org.slf4j.LoggerFactory@getLogger("root").loggerContext.objectMap, #map1.get("CONFIGURATION_WATCH_LIST")'`{{execute T2}}
### 使用classloader命令查找可能存在的logger配置文件
`classloader --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader -r logback-spring.xml`{{execute T2}}
```
$ classloader --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader -r logback-spring.xml
jar:file:/Users/hengyunabc/code/java/spring-boot-inside/demo-arthas-spring-boot/target/demo-arthas-spring-boot-0.0.1-SNAPSHOT.jar!/BOOT-INF/classes!/logback-spring.xml
Affect(row-cnt:1) cost in 13 ms.
```
可以知道加载的配置的具体来源。
可以尝试加载容易冲突的文件:
`classloader --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader -r logback.xml`{{execute T2}}
`classloader --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader -r log4j.properties`{{execute T2}}

@ -1,66 +0,0 @@
在这个案例里动态修改应用的Logger Level。
### 查找UserController的ClassLoader
`sc -d com.example.demo.arthas.user.UserController | grep classLoaderHash`{{execute T2}}
```bash
$ sc -d com.example.demo.arthas.user.UserController | grep classLoaderHash
classLoaderHash 1be6f5c3
```
### 用ognl获取logger
`ognl --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader '@com.example.demo.arthas.user.UserController@logger'`{{execute T2}}
```bash
$ ognl --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader '@com.example.demo.arthas.user.UserController@logger'
@Logger[
serialVersionUID=@Long[5454405123156820674],
FQCN=@String[ch.qos.logback.classic.Logger],
name=@String[com.example.demo.arthas.user.UserController],
level=null,
effectiveLevelInt=@Integer[20000],
parent=@Logger[Logger[com.example.demo.arthas.user]],
childrenList=null,
aai=null,
additive=@Boolean[true],
loggerContext=@LoggerContext[ch.qos.logback.classic.LoggerContext[default]],
]
```
可以知道`UserController@logger`实际使用的是logback。可以看到`level=null`则说明实际最终的level是从`root` logger里来的。
### 单独设置UserController的logger level
`ognl --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader '@com.example.demo.arthas.user.UserController@logger.setLevel(@ch.qos.logback.classic.Level@DEBUG)'`{{execute T2}}
再次获取`UserController@logger`,可以发现已经是`DEBUG`了:
`ognl --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader '@com.example.demo.arthas.user.UserController@logger'`{{execute T2}}
```bash
$ ognl --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader '@com.example.demo.arthas.user.UserController@logger'
@Logger[
serialVersionUID=@Long[5454405123156820674],
FQCN=@String[ch.qos.logback.classic.Logger],
name=@String[com.example.demo.arthas.user.UserController],
level=@Level[DEBUG],
effectiveLevelInt=@Integer[10000],
parent=@Logger[Logger[com.example.demo.arthas.user]],
childrenList=null,
aai=null,
additive=@Boolean[true],
loggerContext=@LoggerContext[ch.qos.logback.classic.LoggerContext[default]],
]
```
### 修改logback的全局logger level
通过获取`root` logger可以修改全局的logger level
`ognl --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader '@org.slf4j.LoggerFactory@getLogger("root").setLevel(@ch.qos.logback.classic.Level@DEBUG)'`{{execute T2}}

@ -1,25 +0,0 @@
### 查看所有线程信息
`thread`{{execute T2}}
### 查看具体线程的栈
查看线程ID 16的栈
`thread 16`{{execute T2}}
### 查看CPU使用率top n线程的栈
`thread -n 3`{{execute T2}}
查看5秒内的CPU使用率top n线程栈
`thread -n 3 -i 5000`{{execute T2}}
### 查找线程是否有阻塞
`thread -b`{{execute T2}}

@ -1,100 +0,0 @@
### 现象
目前,访问 http://localhost/user/0 会返回500异常
`curl http://localhost/user/0`{{execute T3}}
```
{"timestamp":1550223186170,"status":500,"error":"Internal Server Error","exception":"java.lang.IllegalArgumentException","message":"id < 1","path":"/user/0"}
```
但请求的具体参数,异常栈是什么呢?
### 查看UserController的 参数/异常
在Arthas里执行
`watch com.example.demo.arthas.user.UserController * '{params, throwExp}'`{{execute T2}}
1. 第一个参数是类名,支持通配
2. 第二个参数是函数名,支持通配
访问 `curl http://localhost/user/0`{{execute T3}} ,`watch`命令会打印调用的参数和异常
```bash
$ watch com.example.demo.arthas.user.UserController * '{params, throwExp}'
Press Q or Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:2) cost in 53 ms.
ts=2019-02-15 01:35:25; [cost=0.996655ms] result=@ArrayList[
@Object[][isEmpty=false;size=1],
@IllegalArgumentException[java.lang.IllegalArgumentException: id < 1],
]
```
可以看到实际抛出的异常是`IllegalArgumentException`。
可以输入 `Q`{{execute T2}} 或者 `Ctrl+C` 退出watch命令。
如果想把获取到的结果展开,可以用`-x`参数:
`watch com.example.demo.arthas.user.UserController * '{params, throwExp}' -x 2`{{execute T2}}
### 返回值表达式
在上面的例子里,第三个参数是`返回值表达式`,它实际上是一个`ognl`表达式,它支持一些内置对象:
* loader
* clazz
* method
* target
* params
* returnObj
* throwExp
* isBefore
* isThrow
* isReturn
你可以利用这些内置对象来组成不同的表达式。比如返回一个数组:
`watch com.example.demo.arthas.user.UserController * '{params[0], target, returnObj}'`{{execute T2}}
更多参考: https://arthas.aliyun.com/doc/advice-class.html
### 条件表达式
`watch`命令支持在第4个参数里写条件表达式比如
`watch com.example.demo.arthas.user.UserController * returnObj 'params[0] > 100'`{{execute T2}}
当访问 https://[[HOST_SUBDOMAIN]]-80-[[KATACODA_HOST]].environments.katacoda.com/user/1 时,`watch`命令没有输出
当访问 https://[[HOST_SUBDOMAIN]]-80-[[KATACODA_HOST]].environments.katacoda.com/user/101 时,`watch`会打印出结果。
```bash
$ watch com.example.demo.arthas.user.UserController * returnObj 'params[0] > 100'
Press Q or Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:2) cost in 47 ms.
ts=2019-02-13 19:42:12; [cost=0.821443ms] result=@User[
id=@Integer[101],
name=@String[name101],
]
```
### 当异常时捕获
`watch`命令支持`-e`选项,表示只捕获抛出异常时的请求:
`watch com.example.demo.arthas.user.UserController * "{params[0],throwExp}" -e`{{execute T2}}
### 按照耗时进行过滤
watch命令支持按请求耗时进行过滤比如
`watch com.example.demo.arthas.user.UserController * '{params, returnObj}' '#cost>200'`{{execute T2}}

@ -1,19 +0,0 @@
## reset
Arthas在 watch/trace 等命令时,实际上是修改了应用的字节码,插入增强的代码。显式执行 `reset`{{execute T2}} 命令,可以清除掉这些增强代码。
## 退出Arthas
`exit`{{execute interrupt}} 或者 `quit`{{execute interrupt}} 命令可以退出Arthas。
退出Arthas之后还可以再次用 `java -jar arthas-boot.jar`{{execute interrupt}} 来连接。
## 彻底退出Arthas
`exit/quit`命令只是退出当前sessionarthas server还在目标进程中运行。
想完全退出Arthas可以执行 `stop`{{execute interrupt}} 命令。

@ -1,11 +0,0 @@
在“进阶教程”演示了Arthas的大部分高级用法希望对大家排查问题有帮助。如果有更多的技巧或者使用疑问欢迎在Issue里提出。
* Issues: https://github.com/alibaba/arthas/issues
* 文档: https://arthas.aliyun.com/doc
如果您在使用Arthas请让我们知道。您的使用对我们非常重要[查看](https://github.com/alibaba/arthas/issues/111)
欢迎关注公众号获取Arthas项目的信息、源码分析、案例实践。
![Arthas公众号](/arthas/scenarios/common-resources/assets/qrcode_gongzhonghao.jpg)

@ -1,104 +0,0 @@
{
"title": "Arthas 进阶",
"description": "Arthas 进阶",
"details": {
"steps": [
{
"title": "启动math-game",
"text": "start-demo.md"
},
{
"title": "启动arthas-boot",
"text": "arthas-boot.md"
},
{
"title": "查看JVM信息",
"text": "jvm-info.md"
},
{
"title": "Tips",
"text": "tips.md"
},
{
"title": "sc/sm 查看已加载的类",
"text": "sc-sm.md"
},
{
"title": "Jad",
"text": "jad.md"
},
{
"title": "Ognl",
"text": "ognl.md"
},
{
"title": "案例: 排查函数调用异常",
"text": "case-watch-method-exception.md"
},
{
"title": "案例: 热更新代码",
"text": "case-jad-mc-redefine.md"
},
{
"title": "案例: 动态更新应用Logger Level",
"text": "case-ognl-update-logger-level.md"
},
{
"title": "案例: 排查logger冲突问题",
"text": "case-logger-config-problem.md"
},
{
"title": "案例: 获取Spring Context",
"text": "case-get-spring-context.md"
},
{
"title": "案例: 排查HTTP请求返回401",
"text": "case-http-401.md"
},
{
"title": "案例: 排查HTTP请求返回404",
"text": "case-http-404.md"
},
{
"title": "案例: 理解Spring Boot应用的ClassLoader结构",
"text": "case-classloader.md"
},
{
"title": "案例查找Top N线程",
"text": "case-thread.md"
},
{
"title": "Web Console",
"text": "web-console.md"
},
{
"title": "Exit/Stop",
"text": "exit.md"
},
{
"title": "arthas-boot支持的参数",
"text": "arthas-boot-details.md"
}
],
"intro": {
"text": "intro.md"
},
"finish": {
"text": "finish.md"
}
},
"environment": {
"uilayout": "terminal",
"showdashboard": true,
"dashboards": [
{
"name": "Web Port 80",
"port": 80
}
]
},
"backend": {
"imageid": "openjdk:15",
"environmentsprotocol": "http"
}
}

@ -1,11 +0,0 @@
![Arthas](https://arthas.aliyun.com/doc/_images/arthas.png)
`Arthas` 是Alibaba开源的Java诊断工具深受开发者喜爱。
本教程会以一个普通的Spring Boot应用为例演示Arthas命令的详细用法。
* Github: https://github.com/alibaba/arthas
* 文档: https://arthas.aliyun.com/doc/

@ -1,9 +0,0 @@
可以通过 `jad` 命令来反编译代码:
`jad com.example.demo.arthas.user.UserController`{{execute T2}}
通过`--source-only`参数可以只打印出在反编译的源代码:
`jad --source-only com.example.demo.arthas.user.UserController`{{execute T2}}

@ -1,30 +0,0 @@
下面介绍Arthas里查看`JVM`信息的命令。
### sysprop
`sysprop`{{execute T2}} 可以打印所有的System Properties信息。
也可以指定单个key `sysprop java.version`{{execute T2}}
也可以通过`grep`来过滤: `sysprop | grep user`{{execute T2}}
可以设置新的value `sysprop testKey testValue`{{execute T2}}
### sysenv
`sysenv`{{execute T2}} 命令可以获取到环境变量。和`sysprop`命令类似。
### jvm
`jvm`{{execute T2}} 命令会打印出`JVM`的各种详细信息。
### dashboard
`dashboard`{{execute T2}} 命令可以查看当前系统的实时数据面板。
输入 `Q`{{execute T2}} 或者 `Ctrl+C` 可以退出dashboard命令。

@ -1,71 +0,0 @@
在Arthas里有一个单独的`ognl`命令,可以动态执行代码。
### 调用static函数
`ognl '@java.lang.System@out.println("hello ognl")'`{{execute T2}}
可以检查`Terminal 1`不是arthas的Terminal 2里的进程输出可以发现打印出了`hello ognl`。
### 查找UserController的ClassLoader
`sc -d com.example.demo.arthas.user.UserController | grep classLoaderHash`{{execute T2}}
```bash
$ sc -d com.example.demo.arthas.user.UserController | grep classLoaderHash
classLoaderHash 1be6f5c3
```
注意hashcode是变化的需要先查看当前的ClassLoader信息提取对应ClassLoader的hashcode。
如果你使用`-c`你需要手动输入hashcode`-c <hashcode>`
```bash
$ ognl -c 1be6f5c3 @com.example.demo.arthas.user.UserController@logger
```
对于只有唯一实例的ClassLoader可以通过`--classLoaderClass`指定class name使用起来更加方便
```bash
$ ognl --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader @org.springframework.boot.SpringApplication@logger
@Slf4jLocationAwareLog[
FQCN=@String[org.apache.commons.logging.LogAdapter$Slf4jLocationAwareLog],
name=@String[org.springframework.boot.SpringApplication],
logger=@Logger[Logger[org.springframework.boot.SpringApplication]],
]
```
`--classLoaderClass` 的值是ClassLoader的类名只有匹配到唯一的ClassLoader实例时才能工作目的是方便输入通用命令而`-c <hashcode>`是动态变化的。
### 获取静态类的静态字段
获取`UserController`类里的`logger`字段:
`ognl --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader @com.example.demo.arthas.user.UserController@logger`{{execute T2}}
还可以通过`-x`参数控制返回值的展开层数。比如:
`ognl --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader -x 2 @com.example.demo.arthas.user.UserController@logger`{{execute T2}}
### 执行多行表达式赋值给临时变量返回一个List
`ognl '#value1=@System@getProperty("java.home"), #value2=@System@getProperty("java.runtime.name"), {#value1, #value2}'`{{execute T2}}
```bash
$ ognl '#value1=@System@getProperty("java.home"), #value2=@System@getProperty("java.runtime.name"), {#value1, #value2}'
@ArrayList[
@String[/Library/Java/JavaVirtualMachines/jdk1.8.0_162.jdk/Contents/Home/jre],
@String[Java(TM) SE Runtime Environment],
]
```
### 更多
在Arthas里`ognl`表达式是很重要的功能,在很多命令里都可以使用`ognl`表达式。
一些更复杂的用法,可以参考:
* OGNL特殊用法请参考https://github.com/alibaba/arthas/issues/71
* OGNL表达式官方指南https://commons.apache.org/dormant/commons-ognl/language-guide.html

@ -1,37 +0,0 @@
在Arthas里有一些开关可以通过 `options`{{execute T2}} 命令来查看。
查看单个option的值比如
`options unsafe`{{execute T2}}
## 允许增强JDK的类
默认情况下`unsafe`为false即watch/trace等命令不会增强JVM的类即`java.*`下面的类。
如果想增强JVM里的类可以执行 `options unsafe true`{{execute T2}} ,设置`unsafe`为true。
## 以JSON格式打印对象
`json-format` 为false时输出结果是
```bash
$ ognl '#value1=@System@getProperty("java.home"), #value2=@System@getProperty("java.runtime.name"), {#value1, #value2}'
@ArrayList[
@String[/usr/lib/jvm/java-8-oracle/jre],
@String[Java(TM) SE Runtime Environment],
]
```
`options json-format true`{{execute T2}}
`json-format` 为true时输出结果是
```bash
$ ognl '#value1=@System@getProperty("java.home"), #value2=@System@getProperty("java.runtime.name"), {#v["/usr/lib/jvm/java-8-oracle/jre","Java(TM) SE Runtime Environment"]
```

@ -1,34 +0,0 @@
下面介绍Arthas里查找已加载类的命令。
### sc
`sc` 命令可以查找到所有JVM已经加载到的类。
如果搜索的是接口,还会搜索所有的实现类。比如查看所有的`Filter`实现类:
`sc javax.servlet.Filter`{{execute T2}}
通过`-d`参数,可以打印出类加载的具体信息,很方便查找类加载问题。
`sc -d javax.servlet.Filter`{{execute T2}}
`sc`支持通配,比如搜索所有的`StringUtils`
`sc *StringUtils`{{execute T2}}
### sm
`sm`命令则是查找类的具体函数。比如:
`sm java.math.RoundingMode`{{execute T2}}
通过`-d`参数可以打印函数的具体属性:
`sm -d java.math.RoundingMode`{{execute T2}}
也可以查找特定的函数,比如查找构造函数:
`sm java.math.RoundingMode <init>`{{execute T2}}

@ -1,14 +0,0 @@
下载`demo-arthas-spring-boot.jar`,再用`java -jar`命令启动:
`wget https://github.com/hengyunabc/spring-boot-inside/raw/master/demo-arthas-spring-boot/demo-arthas-spring-boot.jar
java -jar demo-arthas-spring-boot.jar`{{execute T1}}
`demo-arthas-spring-boot`是一个很简单的spring boot应用源代码[查看](https://github.com/hengyunabc/spring-boot-inside/tree/master/demo-arthas-spring-boot)
启动之后可以访问80端口 https://[[HOST_SUBDOMAIN]]-80-[[KATACODA_HOST]].environments.katacoda.com
![Demo Web](/arthas/scenarios/common-resources/assets/demo-web.png)

@ -1,47 +0,0 @@
为了更好使用Arthas下面先介绍Arthas里的一些使用技巧。
### help
Arthas里每一个命令都有详细的帮助信息。可以用`-h`来查看。帮助信息里有`EXAMPLES`和`WIKI`链接。
比如:
`sysprop -h`{{execute T2}}
### 自动补全
Arthas支持丰富的自动补全功能在使用有疑惑时可以输入`Tab`来获取更多信息。
比如输入 `sysprop java.` 之后,再输入`Tab`会补全出对应的key
```
$ sysprop java.
java.runtime.name java.protocol.handler.pkgs java.vm.version
java.vm.vendor java.vendor.url java.vm.name
...
```
### readline的快捷键支持
Arthas支持常见的命令行快捷键比如`Ctrl + A`跳转行首,`Ctrl + E`跳转行尾。
更多的快捷键可以用 `keymap`{{execute T2}} 命令查看。
### 历史命令的补全
如果想再执行之前的命令,可以在输入一半时,按`Up/↑` 或者 `Ddown/↓`,来匹配到之前的命令。
比如之前执行过`sysprop java.version`,那么在输入`sysprop ja`之后,可以输入`Up/↑`,就会自动补全为`sysprop java.version`。
如果想查看所有的历史命令,也可以通过 `history`{{execute T2}} 命令查看到。
### pipeline
Arthas支持在pipeline之后执行一些简单的命令比如
`sysprop | grep java`{{execute T2}}
`sysprop | wc -l`{{execute T2}}

@ -1,19 +0,0 @@
Arthas支持通过Web Socket来连接。
## 教程里的Web Console
http://[[HOST_SUBDOMAIN]]-8563-[[KATACODA_HOST]].environments.katacoda.com/?ip=[[HOST_SUBDOMAIN]]-8563-[[KATACODA_HOST]].environments.katacoda.com&port=80
> 注意教程里访问的是80端口因为做了端口转发。在本地体验时需要访问8563端口。
## 本地体验
当在本地启动时,可以访问 http://127.0.0.1:8563/ 通过浏览器来使用Arthas。
![Arthas WebConsole](/arthas/scenarios/common-resources/assets/web-console.png)
推荐通过“快速入门”来体验: https://arthas.aliyun.com/doc/quick-start.html

@ -1,30 +0,0 @@
`arthas-boot.jar` supports many parameters and can be viewed by `java -jar arthas-boot.jar -h`{{execute T2}}.
## Allow external network access
By default, the arthas server listens for the IP of `127.0.0.1`. If you want remote access, you can use the `--target-ip` option.
`java -jar arthas-boot.jar --target-ip`{{execute T2}}
## List all versions
`java -jar arthas-boot.jar --versions`{{execute T2}}
Use the specified version:
`java -jar arthas-boot.jar --use-version 3.1.0`{{execute T2}}
## Only listens at the Telnet port and does not listen at the HTTP port.
`java -jar arthas-boot.jar --telnet-port 9999 --http-port -1`{{execute T2}}
## Print verbose information
`java -jar arthas-boot.jar -v`{{execute T2}}

@ -1,16 +0,0 @@
In the new `Terminal 2`, download `arthas-boot.jar` and start with the `java -jar` command:
`wget https://arthas.aliyun.com/arthas-boot.jar
java -jar arthas-boot.jar --target-ip 0.0.0.0`{{execute T2}}
`arthas-boot` is the launcher for `Arthas`. It lists all the Java processes, and the user can select the target process to be diagnosed.
Select the first process, type `1`{{execute T2}} then type `Enter`
After the Attach is successful, Arthas LOGO is printed. Enter `help`{{execute T2}} for more help.
![Arthas Boot](/arthas/scenarios/common-resources/assets/arthas-boot.png)

@ -1,140 +0,0 @@
The following describes the usage of the `classloader` command.
First visit the jsp page: https://[[HOST_SUBDOMAIN]]-80-[[KATACODA_HOST]].environments.katacoda.com/hello
### List all ClassLoaders
`classloader -l`{{execute T2}}
```bash
$ classloader -l
name loadedCount hash parent
BootstrapClassLoader 2724 null null
com.taobao.arthas.agent.ArthasClassloader@411ce1ab 2009 411ce1ab sun.misc.Launcher$ExtClassLoader@7494e528
com.taobao.arthas.agent.ArthasClassloader@22ae1234 1253 22ae1234 sun.misc.Launcher$ExtClassLoader@7494e528
org.apache.jasper.servlet.JasperLoader@65361d9a 1 65361d9a TomcatEmbeddedWebappClassLoader
context: ROOT
delegate: true
----------> Parent Classloader:
org.springframework.boot.loader.LaunchedURLClassLoader@1be6f5c3
TomcatEmbeddedWebappClassLoader 0 8546cd5 org.springframework.boot.loader.LaunchedURLClassLoader@1be6f5c3
context: ROOT
delegate: true
----------> Parent Classloader:
org.springframework.boot.loader.LaunchedURLClassLoader@1be6f5c3
org.springframework.boot.loader.LaunchedURLClassLoader@1be6f5c3 5416 1be6f5c3 sun.misc.Launcher$AppClassLoader@3d4eac69
sun.misc.Launcher$AppClassLoader@3d4eac69 45 3d4eac69 sun.misc.Launcher$ExtClassLoader@7494e528
sun.misc.Launcher$ExtClassLoader@7494e528 4 7494e528 null
```
* The number of classes loaded by TomcatEmbeddedWebappClassLoader is 0, so in spring boot embedded tomcat, it is just an empty ClassLoader, all the classes are loaded by `LaunchedURLClassLoader`
### List all classes loaded in ClassLoader
List all classes loaded by `org.apache.jasper.servlet.JasperLoader`:
`classloader -a --classLoaderClass org.apache.jasper.servlet.JasperLoader`{{execute T2}}
```bash
$ classloader -a --classLoaderClass apache.jasper.servlet.JasperLoader
hash:1698045338, org.apache.jasper.servlet.JasperLoader@65361d9a
org.apache.jsp.jsp.hello_jsp
```
* PS: Same as `ognl`, you can also use `-c <hashcode>` instead of `--classLoaderClass` to specify
### Decompile dynamically generated jsp classes
`jad org.apache.jsp.jsp.hello_jsp`{{execute T2}}
```bash
$ jad org.apache.jsp.jsp.hello_jsp
ClassLoader:
+-org.apache.jasper.servlet.JasperLoader@65361d9a
+-TomcatEmbeddedWebappClassLoader
context: ROOT
...
```
### View the ClassLoader tree
`classloader -t`{{execute T2}}
```
$ classloader -t
+-BootstrapClassLoader
+-sun.misc.Launcher$ExtClassLoader@28cbbddd
+-com.taobao.arthas.agent.ArthasClassloader@8c25e55
+-sun.misc.Launcher$AppClassLoader@55f96302
+-org.springframework.boot.loader.LaunchedURLClassLoader@1be6f5c3
+-TomcatEmbeddedWebappClassLoader
context: ROOT
delegate: true
----------> Parent Classloader:
org.springframework.boot.loader.LaunchedURLClassLoader@1be6f5c3
+-org.apache.jasper.servlet.JasperLoader@21ae0fe2
```
Note: Please replace `<classLoaderHash>` with your classLoaderHash above, then execute the related commands manually in the following steps:
### List the urls of the ClassLoader
For example, the hashcode of spring `LaunchedURLClassLoader` viewed above is `1be6f5c3`, and all its urls can be listed by the `-c` parameter:
`classloader --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader`{{execute T2}}
```
$ classloader --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader
jar:file:/home/scrapbook/tutorial/demo-arthas-spring-boot.jar!/BOOT-INF/classes!/
jar:file:/home/scrapbook/tutorial/demo-arthas-spring-boot.jar!/BOOT-INF/lib/spring-boot-starter-aop-1.5
.13.RELEASE.jar!/
...
```
### Load the resource file in the specified ClassLoader
Load the specified resource file: `classloader --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader -r logback-spring.xml`{{execute T2}}
```
$ classloader --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader -r logback-spring.xml
jar:file:/home/scrapbook/tutorial/demo-arthas-spring-boot.jar!/BOOT-INF/classes!/logback-spring.xml
```
### Try to load the specified class
For example, try loading `java.lang.String` with spring LaunchedURLClassLoader :
`classloader --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader --load java.lang.String`{{execute T2}}
```
$ classloader --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader --load java.lang.String
load class success.
class-info java.lang.String
code-source
name java.lang.String
isInterface false
isAnnotation false
isEnum false
isAnonymousClass false
isArray false
isLocalClass false
isMemberClass false
isPrimitive false
isSynthetic false
simple-name String
modifier final,public
annotation
interfaces java.io.Serializable,java.lang.Comparable,java.lang.CharSequence
super-class +-java.lang.Object
class-loader
classLoaderHash null
```

@ -1,54 +0,0 @@
In this case, the user can get the spring context, get the bean, and invoke the method.
### Use the tt command to record the invocation of the specified method
`tt` is TimeTunnel, which records the parameters and return value of each invocation of the specified method.
* https://arthas.aliyun.com/doc/tt.html
`tt -t org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter invokeHandlerMethod`{{execute T2}}
Visit: https://[[HOST_SUBDOMAIN]]-80-[[KATACODA_HOST]].environments.katacoda.com/user/1
You can see that the `tt` command record an invocation:
```bash
$ tt -t org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdaptePress Q or Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 252 ms.
INDE TIMESTAMP COST( IS-R IS- OBJECT CLASS METHOD
X ms) ET EXP
-----------------------------------------------------------------------------------------
1000 2019-02-15 4.583 true fal 0xc93cf1a RequestMappingHand invokeHandlerMethod
15:38:32 923 se lerAdapter
```
### Use the tt command to get the spring context from the invocation record.
Type `Q`{{execute T2}} or `Ctrl + C` to exit the `tt -t` command above.
`tt -i 1000 -w 'target.getApplicationContext()'`{{execute T2}}
```bash
$ tt -i 1000 -w 'target.getApplicationContext()'
@AnnotationConfigEmbeddedWebApplicationContext[
reader=@AnnotatedBeanDefinitionReader[org.springframework.context.annotation.AnnotatedBeanDefinitionReader@2e457641],
scanner=@ClassPathBeanDefinitionScanner[org.springframework.context.annotation.ClassPathBeanDefinitionScanner@6eb38026],
annotatedClasses=null,
basePackages=null,
]
Affect(row-cnt:1) cost in 439 ms.
```
## Get the spring bean and invoke method
`tt -i 1000 -w 'target.getApplicationContext().getBean("helloWorldService").getHelloMessage()'`{{execute T2}}
The result is:
```bash
$ tt -i 1000 -w 'target.getApplicationContext().getBean("helloWorldService").getHelloMessage()'
@String[Hello World]
Affect(row-cnt:1) cost in 52 ms.
```

@ -1,56 +0,0 @@
In this case, the user will resolve the HTTP 401 issue.
Visit: https://[[HOST_SUBDOMAIN]]-80-[[KATACODA_HOST]].environments.katacoda.com/admin
The result is:
```
Something went wrong: 401 Unauthorized
```
We know that `401` is usually intercepted by the permission-managed `Filter`, so which `Filter` returns 401?
### Track all Filter methods
Start trace:
`trace javax.servlet.Filter *`{{execute T2}}
Visit: https://[[HOST_SUBDOMAIN]]-80-[[KATACODA_HOST]].environments.katacoda.com/admin
At the deepest level of the call tree, you can find `AdminFilterConfig$AdminFilter` which returns `401`:
```
+---[3.806273ms] javax.servlet.FilterChain:doFilter()
| `---[3.447472ms] com.example.demo.arthas.AdminFilterConfig$AdminFilter:doFilter()
| `---[0.17259ms] javax.servlet.http.HttpServletResponse:sendError()
```
### Get the call stack through stack command
From the above result, we can find the method: `HttpServletResponse:sendError()`. So we can use `stack` command to resolved the HTTP `401` issue.
Run:
`stack javax.servlet.http.HttpServletResponse sendError 'params[0]==401'`{{execute T2}}
Visit: https://[[HOST_SUBDOMAIN]]-80-[[KATACODA_HOST]].environments.katacoda.com/admin
The Result:
```bash
$ stack javax.servlet.http.HttpServletResponse sendError 'params[0]==401'
Press Q or Ctrl+C to abort.
Affect(class-cnt:2 , method-cnt:4) cost in 87 ms.
ts=2019-02-15 16:44:06;thread_name=http-nio-8080-exec-6;id=16;is_daemon=true;priority=5;TCCL=org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedWebappClassLoader@8546cd5
@org.apache.catalina.connector.ResponseFacade.sendError()
at com.example.demo.arthas.AdminFilterConfig$AdminFilter.doFilter(AdminFilterConfig.java:38)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
```

@ -1,39 +0,0 @@
In this case, the user will resolve the HTTP 404 issue.
Visit: https://[[HOST_SUBDOMAIN]]-80-[[KATACODA_HOST]].environments.katacoda.com/a.txt
The result is:
```
Something went wrong: 404 Not Found
```
So which servlet is handle this request and returning 404?
### Trace all the Servlet methods
Start trace:
`trace javax.servlet.Servlet * > /tmp/servlet.txt`{{execute T2}}
Visit: https://[[HOST_SUBDOMAIN]]-80-[[KATACODA_HOST]].environments.katacoda.com/a.txt
In `Terminal 3`, view the contents of `/tmp/servlet.txt`:
`less /tmp/servlet.txt`{{execute T3}}
The contents of `/tmp/servlet.txt` will be more, and you need to be patient to find the longest level in the call tree.
It can be found that the request is handled by `freemarker`:
```
`---[13.974188ms] org.springframework.web.servlet.ViewResolver:resolveViewName()
+---[0.045561ms] javax.servlet.GenericServlet:<init>()
+---[min=0.045545ms,max=0.074342ms,total=0.119887ms,count=2] org.springframework.web.servlet.view.freemarker.FreeMarkerView$GenericServletAdapter:<init>()
+---[0.170895ms] javax.servlet.GenericServlet:init()
| `---[0.068578ms] javax.servlet.GenericServlet:init()
| `---[0.021793ms] javax.servlet.GenericServlet:init()
`---[0.164035ms] javax.servlet.GenericServlet:getServletContext()
```

@ -1,92 +0,0 @@
This case introduces the ability to dynamically update code via the `jad`/`mc`/`redefine` command.
Currently, visiting http://localhost/user/0 will return a 500 error:
`curl http://localhost/user/0`{{execute T3}}
```
{"timestamp":1550223186170,"status":500,"error":"Internal Server Error","exception":"java.lang.IllegalArgumentException","message":"id < 1","path":"/user/0"}
```
This logic will be modified by `redefine` command below.
### Use jad command to decompile UserController
`jad --source-only com.example.demo.arthas.user.UserController > /tmp/UserController.java`{{execute T2}}
The result of jad command will be saved in the `/tmp/UserController.java` file.
Then open `Terminal 3`, use `vim` to edit `/tmp/UserController.java`:
`vim /tmp/UserController.java`{{execute T3}}
For example, when the user id is less than 1, it also returns normally without throwing an exception:
```java
@GetMapping(value={"/user/{id}"})
public User findUserById(@PathVariable Integer id) {
logger.info("id: {}", (Object)id);
if (id != null && id < 1) {
return new User(id, "name" + id);
// throw new IllegalArgumentException("id < 1");
}
return new User(id.intValue(), "name" + id);
}
```
### Use sc command to find the ClassLoader that loads the UserController
`sc -d *UserController | grep classLoaderHash`{{execute T2}}
```bash
$ sc -d *UserController | grep classLoaderHash
classLoaderHash 1be6f5c3
```
It can be found that it is loaded by spring boot `LaunchedURLClassLoader@1be6f5c3`.
Please write down your classLoaderHash here, in the case here, it's `1be6f5c3`. It will be used in the future steps.
### mc
After saving `/tmp/UserController.java`, compile with the `mc` (Memory Compiler) command and specify the ClassLoader with the `-c` or `--classLoaderClass` option:
`mc --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader /tmp/UserController.java -d /tmp`{{execute T2}}
```bash
$ mc --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader /tmp/UserController.java -d /tmp
Memory compiler output:
/tmp/com/example/demo/arthas/user/UserController.class
Affect(row-cnt:1) cost in 346 ms
```
You can also execute `mc -c <classLoaderHash> /tmp/UserController.java -d /tmp`using `-c` to specify ClassLoaderHash:
```bash
$ mc -c 1be6f5c3 /tmp/UserController.java -d /tmp
```
### redefine
Then reload the newly compiled `UserController.class` with the `redefine` command:
`redefine /tmp/com/example/demo/arthas/user/UserController.class`{{execute T2}}
```
$ redefine /tmp/com/example/demo/arthas/user/UserController.class
redefine success, size: 1
```
### Check the results of the hotswap code
After the `redefine` command is executed successfully, visit https://[[HOST_SUBDOMAIN]]-80-[[KATACODA_HOST]].environments.katacoda.com/user/0 again.
The result is:
```
{
"id": 0,
"name": "name0"
}
```

@ -1,53 +0,0 @@
In this case, show how to troubleshoot logger conflicts.
### View the logger system used by the app
Take `UserController` as an example, it uses slf4j api, but the actual logger system used is logback.
`ognl --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader '@com.example.demo.arthas.user.UserController@logger'`{{execute T2}}
```bash
$ ognl --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader '@com.example.demo.arthas.user.UserController@logger'
@Logger[
serialVersionUID=@Long[5454405123156820674],
FQCN=@String[ch.qos.logback.classic.Logger],
name=@String[com.example.demo.arthas.user.UserController],
level=null,
effectiveLevelInt=@Integer[20000],
parent=@Logger[Logger[com.example.demo.arthas.user]],
childrenList=null,
aai=null,
additive=@Boolean[true],
loggerContext=@LoggerContext[ch.qos.logback.classic.LoggerContext[default]],
]
```
### Find the configuration file actually loaded by the logback
`ognl --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader '#map1=@org.slf4j.LoggerFactory@getLogger("root").loggerContext.objectMap, #map1.get("CONFIGURATION_WATCH_LIST")'`{{execute T2}}
### Use the classloader command to find possible logger configuration files
`classloader --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader -r logback-spring.xml`{{execute T2}}
```
$ classloader --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader -r logback-spring.xml
jar:file:/Users/hengyunabc/code/java/spring-boot-inside/demo-arthas-spring-boot/target/demo-arthas-spring-boot-0.0.1-SNAPSHOT.jar!/BOOT-INF/classes!/logback-spring.xml
Affect(row-cnt:1) cost in 13 ms.
```
You can know the specific source of the loaded configuration.
You can try to load files that are prone to conflict:
`classloader --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader -r logback.xml`{{execute T2}}
`classloader --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader -r log4j.properties`{{execute T2}}

@ -1,66 +0,0 @@
In this case, show how to dynamically modify the Logger Level.
### Find the ClassLoader of the UserController
`sc -d com.example.demo.arthas.user.UserController | grep classLoaderHash`{{execute T2}}
```bash
$ sc -d com.example.demo.arthas.user.UserController | grep classLoaderHash
classLoaderHash 1be6f5c3
```
### Use ognl command to get the logger
`ognl --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader '@com.example.demo.arthas.user.UserController@logger'`{{execute T2}}
```bash
$ ognl --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader '@com.example.demo.arthas.user.UserController@logger'
@Logger[
serialVersionUID=@Long[5454405123156820674],
FQCN=@String[ch.qos.logback.classic.Logger],
name=@String[com.example.demo.arthas.user.UserController],
level=null,
effectiveLevelInt=@Integer[20000],
parent=@Logger[Logger[com.example.demo.arthas.user]],
childrenList=null,
aai=null,
additive=@Boolean[true],
loggerContext=@LoggerContext[ch.qos.logback.classic.LoggerContext[default]],
]
```
可以知道`UserController@logger`实际使用的是logback。可以看到`level=null`则说明实际最终的level是从`root` logger里来的。
The user can know that `UserController@logger` actually uses logback. Because `level=null`, the actual final level is from the `root` logger.
### Change the logger level of UserController
`ognl --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader '@com.example.demo.arthas.user.UserController@logger.setLevel(@ch.qos.logback.classic.Level@DEBUG)'`{{execute T2}}
Get `UserController@logger` again, the user can see that it is already `DEBUG`:
`ognl --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader '@com.example.demo.arthas.user.UserController@logger'`{{execute T2}}
```bash
$ ognl --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader '@com.example.demo.arthas.user.UserController@logger'
@Logger[
serialVersionUID=@Long[5454405123156820674],
FQCN=@String[ch.qos.logback.classic.Logger],
name=@String[com.example.demo.arthas.user.UserController],
level=@Level[DEBUG],
effectiveLevelInt=@Integer[10000],
parent=@Logger[Logger[com.example.demo.arthas.user]],
childrenList=null,
aai=null,
additive=@Boolean[true],
loggerContext=@LoggerContext[ch.qos.logback.classic.LoggerContext[default]],
]
```
### Change the global logger level of the logback
By getting the `root` logger, the user can modify the global logger level:
`ognl --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader '@org.slf4j.LoggerFactory@getLogger("root").setLevel(@ch.qos.logback.classic.Level@DEBUG)'`{{execute T2}}

@ -1,24 +0,0 @@
### View all thread information
`thread`{{execute T2}}
### View the stack of specific threads
View the stack of thread ID 16:
`thread 16`{{execute T2}}
### View the stack of CPU usage TOP N threads
`thread -n 3`{{execute T2}}
View the CPU usage TOP N thread stack in 5 seconds
`thread -n 3 -i 5000`{{execute T2}}
### Find if the thread is blocked
`thread -b`{{execute T2}}

@ -1,98 +0,0 @@
Currently, visiting http://localhost/user/0 will return a 500 error:
`curl http://localhost/user/0`{{execute T3}}
```
{"timestamp":1550223186170,"status":500,"error":"Internal Server Error","exception":"java.lang.IllegalArgumentException","message":"id < 1","path":"/user/0"}
```
But what are the specific parameters of the request, what is the exception stack?
### View the parameters/exception of UserController
Execute in Arthas:
`watch com.example.demo.arthas.user.UserController * '{params, throwExp}'`{{execute T2}}
1. The first argument is the class name, which supports wildcards.
2. The second argument is the function name, which supports wildcards.
Visit `curl http://localhost/user/0`{{execute T3}} , the `watch` command will print the parameters and exception
```bash
$ watch com.example.demo.arthas.user.UserController * '{params, throwExp}'
Press Q or Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:2) cost in 53 ms.
ts=2019-02-15 01:35:25; [cost=0.996655ms] result=@ArrayList[
@Object[][isEmpty=false;size=1],
@IllegalArgumentException[java.lang.IllegalArgumentException: id < 1],
]
```
The user can see that the actual thrown exception is `IllegalArgumentException`.
The user can exit the watch command by typing `Q`{{execute T2}} or `Ctrl+C`.
If the user want to expand the result, can use the `-x` option:
`watch com.example.demo.arthas.user.UserController * '{params, throwExp}' -x 2`{{execute T2}}
### The return value expression
In the above example, the third argument is the `return value expression`, which is actually an `ognl` expression that supports some built-in objects:
* loader
* clazz
* method
* target
* params
* returnObj
* throwExp
* isBefore
* isThrow
* isReturn
You can use these built-in objects in the expressions. For example, return an array:
`watch com.example.demo.arthas.user.UserController * '{params[0], target, returnObj}'`{{execute T2}}
More references: https://arthas.aliyun.com/doc/en/advice-class.html
### The conditional expression
The `watch` command supports conditional expressions in the fourth argument, such as:
`watch com.example.demo.arthas.user.UserController * returnObj 'params[0] > 100'`{{execute T2}}
When visit https://[[HOST_SUBDOMAIN]]-80-[[KATACODA_HOST]].environments.katacoda.com/user/1 , the `watch` command print nothing.
When visit https://[[HOST_SUBDOMAIN]]-80-[[KATACODA_HOST]].environments.katacoda.com/user/101 , the `watch` command will print:
```bash
$ watch com.example.demo.arthas.user.UserController * returnObj 'params[0] > 100'
Press Q or Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:2) cost in 47 ms.
ts=2019-02-13 19:42:12; [cost=0.821443ms] result=@User[
id=@Integer[101],
name=@String[name101],
]
```
### Capture when an exception occurs
The `watch` command supports the `-e` option, which means that only requests that throw an exception are caught:
`watch com.example.demo.arthas.user.UserController * "{params[0],throwExp}" -e`{{execute T2}}
### Filter by cost
The watch command supports filtering by cost, such as:
`watch com.example.demo.arthas.user.UserController * '{params, returnObj}' '#cost>200'`{{execute T2}}

@ -1,18 +0,0 @@
## reset
When Arthas executes commands such as watch/trace, it actually modifies the application's bytecode and inserts the enhanced code. These enhancement codes can be removed by explicitly executing the `reset`{{execute T2}} command.
## Exit/Stop Arthas
Arthas can be exited with the `exit`{{execute interrupt}} or `quit`{{execute interrupt}} command.
After exiting Arthas, you can also connect with `java -jar arthas-boot.jar`{{execute interrupt}} again.
## Stop Arthas
The `exit/quit` command simply exits the current session and the arthas server still runs in the target process.
To completely exit Arthas, you can execute the `stop`{{execute interrupt}} command.

@ -1,8 +0,0 @@
In the `Advanced Tutorial`, there are most of the advanced usages of Arthas and hope to help you troubleshoot the issue. If you have more tips or questions, please feel free to tell or ask in Issue.
* Issues: https://github.com/alibaba/arthas/issues
* Documentation: https://arthas.aliyun.com/doc/en
If you are using Arthas, please let us know that. Your use is very important to us: [View](https://github.com/alibaba/arthas/issues/111)

@ -1,104 +0,0 @@
{
"title": "Arthas Advanced",
"description": "Arthas Advanced",
"details": {
"steps": [
{
"title": "Start math-game",
"text": "start-demo.md"
},
{
"title": "Start arthas-boot",
"text": "arthas-boot.md"
},
{
"title": "JVM Infomation",
"text": "jvm-info.md"
},
{
"title": "Tips",
"text": "tips.md"
},
{
"title": "sc/sm view loaded classes",
"text": "sc-sm.md"
},
{
"title": "Jad",
"text": "jad.md"
},
{
"title": "Ognl",
"text": "ognl.md"
},
{
"title": "Case: Troubleshooting method invoke exception",
"text": "case-watch-method-exception.md"
},
{
"title": "Case: Hotswap code",
"text": "case-jad-mc-redefine.md"
},
{
"title": "Case: Change Logger Level",
"text": "case-ognl-update-logger-level.md"
},
{
"title": "Case: Troubleshoot logger conflicts",
"text": "case-logger-config-problem.md"
},
{
"title": "Case: Get the Spring Context",
"text": "case-get-spring-context.md"
},
{
"title": "Case: Troubleshooting HTTP request returns 401",
"text": "case-http-401.md"
},
{
"title": "Case: Troubleshooting HTTP request returns 404",
"text": "case-http-404.md"
},
{
"title": "Case: The ClassLoaders in Spring Boot application",
"text": "case-classloader.md"
},
{
"title": "Case: Find CPU usage Top N threads",
"text": "case-thread.md"
},
{
"title": "Web Console",
"text": "web-console.md"
},
{
"title": "Exit/Stop",
"text": "exit.md"
},
{
"title": "arthas-boot supported options",
"text": "arthas-boot-details.md"
}
],
"intro": {
"text": "intro.md"
},
"finish": {
"text": "finish.md"
}
},
"environment": {
"uilayout": "terminal",
"showdashboard": true,
"dashboards": [
{
"name": "Web Port 80",
"port": 80
}
]
},
"backend": {
"imageid": "openjdk:15",
"environmentsprotocol": "http"
}
}

@ -1,11 +0,0 @@
![Arthas](https://arthas.aliyun.com/doc/_images/arthas.png)
`Arthas` is a Java diagnostic tool open-sourced by Alibaba middleware team. Arthas helps developers in trouble-shooting issues in production environment for Java based applications without modifying code or restarting servers.
This tutorial takes a normal Spring Boot application as an example to demonstrate the advanced usage of the Arthas.
* Github: https://github.com/alibaba/arthas
* Docs: https://arthas.aliyun.com/doc/en

@ -1,8 +0,0 @@
The user can decompile the code with the `jad` command:
`jad com.example.demo.arthas.user.UserController`{{execute T2}}
The `--source-only` option can only print out the source code:
`jad --source-only com.example.demo.arthas.user.UserController`{{execute T2}}

@ -1,29 +0,0 @@
The following describes the commands for viewing `JVM` information in Arthas.
### sysprop
`sysprop`{{execute T2}} can print all System Properties information.
Specify a single key: `sysprop java.version`{{execute T2}}
It can also be filtered by `grep`: `sysprop | grep user`{{execute T2}}
Set a new value: `sysprop testKey testValue`{{execute T2}}
### sysenv
The `sysenv`{{execute T2}} command gets the environment variable. Similar to the `sysprop` command.
### jvm
The `jvm`{{execute T2}} command prints out various details of the `JVM`.
### dashboard
The `dashboard`{{execute T2}} command can view the real-time data panel of the current system.
Enter `Q`{{execute T2}} or `Ctrl+C` to exit the dashboard command.

@ -1,71 +0,0 @@
The `ognl` command can execute code dynamically.
### Invoke the static method
`ognl '@java.lang.System@out.println("hello ognl")'`{{execute T2}}
The `Terminal 1` will print `hello ognl`.
### Find the ClassLoader of the UserController
`sc -d com.example.demo.arthas.user.UserController | grep classLoaderHash`{{execute T2}}
```bash
$ sc -d com.example.demo.arthas.user.UserController | grep classLoaderHash
classLoaderHash 1be6f5c3
```
Please write down your classLoaderHash here since it's dynamic. In the case here, it's `1be6f5c3`.
if you use`-c`, you have to manually type hashcode by `-c <hashcode>`.
```bash
$ ognl -c 1be6f5c3 @com.example.demo.arthas.user.UserController@logger
```
For classloader with only one instance, it can be specified by `--classLoaderClass` using class name, which is more convenient to use.
```bash
$ ognl --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader @org.springframework.boot.SpringApplication@logger
@Slf4jLocationAwareLog[
FQCN=@String[org.apache.commons.logging.LogAdapter$Slf4jLocationAwareLog],
name=@String[org.springframework.boot.SpringApplication],
logger=@Logger[Logger[org.springframework.boot.SpringApplication]],
]
```
The value of `--classloaderclass` is the class name of classloader. It can only work when it matches a unique classloader instance. The purpose is to facilitate the input of general commands. However, `-c <hashcode>` is dynamic.
### Get static fields of static classes
Get the `logger` field of the `UserController` class:
`ognl --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader @com.example.demo.arthas.user.UserController@logger`{{execute T2}}
Control the number of expansion layers of the return value with the `-x` parameter. such as:
`ognl --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader -x 2 @com.example.demo.arthas.user.UserController@logger`{{execute T2}}
### Execute multi-line expressions
Return a list:
`ognl '#value1=@System@getProperty("java.home"), #value2=@System@getProperty("java.runtime.name"), {#value1, #value2}'`{{execute T2}}
```bash
$ ognl '#value1=@System@getProperty("java.home"), #value2=@System@getProperty("java.runtime.name"), {#value1, #value2}'
@ArrayList[
@String[/Library/Java/JavaVirtualMachines/jdk1.8.0_162.jdk/Contents/Home/jre],
@String[Java(TM) SE Runtime Environment],
]
```
### More
The `ognl` expression in Arthas is an important feature, and the `ognl` expression can be used in many commands.
For some more complicated usages, refer to:
* For special usage of OGNL, please refer to: https://github.com/alibaba/arthas/issues/71
* Official Guide to OGNL Expressions: https://commons.apache.org/dormant/commons-ognl/language-guide.html

@ -1,36 +0,0 @@
There are some switches in Arthas that can be viewed with the `options`{{execute T2}} command.
View the value of a single option, such as
`options unsafe`{{execute T2}}
## Allow to enhance the classes of JDK
By default, `unsafe` is false, ie commands such as `watch`/`trace` do not enhance the JVM class, which is the class starting with `java.*`.
To enhance the classes in the JVM, execute `options unsafe true`{{execute T2}} to set `unsafe` to true.
## Print objects in JSON format
When `json-format` is false, the output is:
```bash
$ ognl '#value1=@System@getProperty("java.home"), #value2=@System@getProperty("java.runtime.name"), {#value1, #value2}'
@ArrayList[
@String[/usr/lib/jvm/java-8-oracle/jre],
@String[Java(TM) SE Runtime Environment],
]
```
`options json-format true`{{execute T2}}
When `json-format` is true, the output is:
```bash
$ ognl '#value1=@System@getProperty("java.home"), #value2=@System@getProperty("java.runtime.name"), {#v["/usr/lib/jvm/java-8-oracle/jre","Java(TM) SE Runtime Environment"]
```

@ -1,33 +0,0 @@
The commands in Arthas for finding loaded classes.
### sc
The `sc` command finds all the classes that the JVM has loaded.
When search an interface, it also search all implementation classes. For example, look at all the `Filter` implementation classes:
`sc javax.servlet.Filter`{{execute T2}}
With the `-d` option, it will print out the specific information of the loaded classes, which is very convenient for finding the class loading problem.
`sc -d javax.servlet.Filter`{{execute T2}}
`sc` supports wildcards, such as searching for all `StringUtils`:
`sc *StringUtils`{{execute T2}}
### sm
The `sm` command find the specific method of the class. such as:
`sm java.math.RoundingMode`{{execute T2}}
With `-d` option, it will print the deatils of the method.
`sm -d java.math.RoundingMode`{{execute T2}}
Find specific methods, such as the constructors:
`sm java.math.RoundingMode <init>`{{execute T2}}

@ -1,14 +0,0 @@
Download `demo-arthas-spring-boot.jar`, and start with `java -jar` command:
`wget https://github.com/hengyunabc/spring-boot-inside/raw/master/demo-arthas-spring-boot/demo-arthas-spring-boot.jar
java -jar demo-arthas-spring-boot.jar`{{execute T1}}
`demo-arthas-spring-boot` is a simple Spring Boot demo, the source code here: [View](https://github.com/hengyunabc/spring-boot-inside/tree/master/demo-arthas-spring-boot)
After booting, access port 80: https://[[HOST_SUBDOMAIN]]-80-[[KATACODA_HOST]].environments.katacoda.com
![Demo Web](/arthas/scenarios/common-resources/assets/demo-web.png)

@ -1,47 +0,0 @@
Some tips on using Arthas.
### help
Every command in Arthas has help doc. Can be viewed with `-h`. There are `EXAMPLES` and `WIKI` links in the help doc.
such as:
`sysprop -h`{{execute T2}}
### Auto completion
Arthas supports a wide range of auto-completion features, and you can type `Tab` to get more information when you have doubts about your use.
For example, after typing `sysprop java.`, enter `Tab`, which will complete the corresponding key:
```
$ sysprop java.
java.runtime.name java.protocol.handler.pkgs java.vm.version
java.vm.vendor java.vendor.url java.vm.name
...
```
### Readline shortcut key support
Arthas supports common command line shortcuts, such as `Ctrl + A` to jump to the beginning of the line, and `Ctrl + E` to jump to the end of the line.
More shortcuts can be viewed with the `keymap`{{execute T2}} command.
### Completion of history commands
If you want to execute the previous command again, you can match the previous command by pressing `Up/↑` or `Ddown/↓` when you enter halfway.
For example, if `sysprop java.version` was executed before, then after entering `sysprop ja`, you can type `Up/↑`, and it will be automatically completed as `sysprop java.version`.
If you want to see all the history commands, you can also view them with the `history`{{execute T2}} command.
### pipeline
Arthas supports some simple commands after the pipeline, such as:
`sysprop | grep java`{{execute T2}}
`sysprop | wc -l`{{execute T2}}

@ -1,20 +0,0 @@
Arthas supports connections via a Web Socket.
## The Web Console in the tutorial
http://[[HOST_SUBDOMAIN]]-8563-[[KATACODA_HOST]].environments.katacoda.com/?ip=[[HOST_SUBDOMAIN]]-8563-[[KATACODA_HOST]].environments.katacoda.com&port=80
> Note: The 80 port is accessed in the tutorial because port forwarding. In the local, you need to access port 8563.
## Local
When launching locally, you can access Arthas through a browser by visiting http://127.0.0.1:8563/.
![Arthas WebConsole](/arthas/scenarios/common-resources/assets/web-console.png)
It is recommended to experience it through "Quick Start": https://arthas.aliyun.com/doc/en/quick-start.html

@ -1,16 +0,0 @@
在新的`Terminal 2`里,下载`arthas-boot.jar`,再用`java -jar`命令启动:
`wget https://arthas.aliyun.com/arthas-boot.jar
java -jar arthas-boot.jar`{{execute T2}}
`arthas-boot`是`Arthas`的启动程序它启动后会列出所有的Java进程用户可以选择需要诊断的目标进程。
选择第一个进程,输入 `1`{{execute T2}} ,再`Enter/回车`
Attach成功之后会打印Arthas LOGO。输入 `help`{{execute T2}} 可以获取到更多的帮助信息。
![Arthas Boot](/arthas/scenarios/common-resources/assets/arthas-boot.png)

@ -1,10 +0,0 @@
下载`math-game.jar`,再用`java -jar`命令启动:
`wget https://arthas.aliyun.com/math-game.jar
java -jar math-game.jar`{{execute T1}}
`math-game`是一个很简单的程序,它随机生成整数,再执行因式分解,把结果打印出来。如果生成的随机数是负数,则会打印提示信息。

@ -1,3 +0,0 @@
`dashboard`{{execute T2}} 命令可以查看当前系统的实时数据面板。
输入 `Q`{{execute T2}} 或者 `Ctrl+C` 可以退出dashboard命令。

@ -1,15 +0,0 @@
## 退出Arthas
`exit`{{execute interrupt}} 或者 `quit`{{execute interrupt}} 命令可以退出Arthas。
退出Arthas之后还可以再次用 `java -jar arthas-boot.jar`{{execute interrupt}} 来连接。
## 彻底退出Arthas
`exit/quit`命令只是退出当前sessionarthas server还在目标进程中运行。
想完全退出Arthas可以执行 `stop`{{execute interrupt}} 命令。

@ -1,10 +0,0 @@
通过本教程基本掌握了Arthas的用法。更多高级特性可以在下面的进阶指南里继续了解。
* [Arthas进阶](https://arthas.aliyun.com/doc/arthas-tutorials.html?language=cn&id=arthas-advanced)
* [Arthas Github](https://github.com/alibaba/arthas)
* [Arthas 文档](https://arthas.aliyun.com/doc/)
欢迎关注公众号获取Arthas项目的信息源码分析案例实践。
![Arthas公众号](/arthas/scenarios/common-resources/assets/qrcode_gongzhonghao.jpg)

@ -1,57 +0,0 @@
{
"title": "Arthas 基础教程",
"description": "Arthas 基础教程",
"details": {
"steps": [
{
"title": "启动math-game",
"text": "arthas-demo.md"
},
{
"title": "启动arthas-boot",
"text": "arthas-boot.md"
},
{
"title": "Dashboard",
"text": "dashboard.md"
},
{
"title": "Thread",
"text": "thread.md"
},
{
"title": "Sc",
"text": "sc.md"
},
{
"title": "Jad",
"text": "jad.md"
},
{
"title": "Watch",
"text": "watch.md"
},
{
"title": "Vmtool",
"text": "vmtool.md"
},
{
"title": "Exit/Stop",
"text": "exit.md"
}
],
"intro": {
"text": "intro.md"
},
"finish": {
"text": "finish.md"
}
},
"environment": {
"uilayout": "terminal"
},
"backend": {
"imageid": "openjdk:15",
"environmentsprotocol": "http"
}
}

@ -1,11 +0,0 @@
![Arthas](https://arthas.aliyun.com/doc/_images/arthas.png)
`Arthas` 是Alibaba开源的Java诊断工具深受开发者喜爱。在线排查问题无需重启动态跟踪Java代码实时监控JVM状态。
`Arthas` 支持JDK 6+支持Linux/Mac/Windows采用命令行交互模式同时提供丰富的 `Tab` 自动补全功能,进一步方便进行问题的定位和诊断。
* Github: https://github.com/alibaba/arthas
* 文档: https://arthas.aliyun.com/doc/

@ -1,4 +0,0 @@
可以通过 `jad` 命令来反编译代码:
`jad demo.MathGame`{{execute T2}}

@ -1,4 +0,0 @@
可以通过 `sc` 命令来查找JVM里已加载的类
`sc -d *MathGame`{{execute T2}}

@ -1,11 +0,0 @@
`thread 1`{{execute interrupt}} 命令会打印线程ID 1的栈。
Arthas支持管道可以用 `thread 1 | grep 'main('`{{execute T2}} 查找到`main class`。
可以看到`main class`是`demo.MathGame`
```
$ thread 1 | grep 'main('
at demo.MathGame.main(MathGame.java:17)
```

@ -1,20 +0,0 @@
通过`vmtool`命令,可以搜索内存对象。
`vmtool --action getInstances --className java.lang.String --limit 10`{{execute T2}}
```bash
$ vmtool --action getInstances --className java.lang.String --limit 10
@String[][
@String[com/taobao/arthas/core/shell/session/Session],
@String[com.taobao.arthas.core.shell.session.Session],
@String[com/taobao/arthas/core/shell/session/Session],
@String[com/taobao/arthas/core/shell/session/Session],
@String[com/taobao/arthas/core/shell/session/Session.class],
@String[com/taobao/arthas/core/shell/session/Session.class],
@String[com/taobao/arthas/core/shell/session/Session.class],
@String[com/],
@String[java/util/concurrent/ConcurrentHashMap$ValueIterator],
@String[java/util/concurrent/locks/LockSupport],
]
```

@ -1,6 +0,0 @@
通过`watch`命令可以查看函数的参数/返回值/异常信息。
`watch demo.MathGame primeFactors returnObj`{{execute T2}}
输入 `Q`{{execute T2}} 或者 `Ctrl+C` 退出watch命令。

@ -1,15 +0,0 @@
In the new `Terminal 2`, download `arthas-boot.jar` and start with the `java -jar` command:
`wget https://arthas.aliyun.com/arthas-boot.jar
java -jar arthas-boot.jar`{{execute T2}}
`arthas-boot` is the launcher for `Arthas`. It lists all the Java processes, and the user can select the target process to be diagnosed.
Select the first process, type `1`{{execute T2}} then type `Enter`
After the Attach is successful, Arthas LOGO is printed. Enter `help`{{execute T2}} for more help.
![Arthas Boot](/arthas/scenarios/common-resources/assets/arthas-boot.png)

@ -1,11 +0,0 @@
Download `math-game.jar` and start with the `java -jar` command:
`wget https://arthas.aliyun.com/math-game.jar
java -jar math-game.jar`{{execute T1}}
`math-game` is a very simple program that randomly generates integers, performs factorization, and prints the results.
If the generated random number is negative, a error message will be printed.

@ -1,3 +0,0 @@
The `dashboard`{{execute T2}} command allows you to view the real-time data panel of the current system.
Enter `Q`{{execute T2}} or `Ctrl+C` to exit the dashboard command.

@ -1,13 +0,0 @@
## Exit/Stop Arthas
Arthas can be exited with the `exit`{{execute interrupt}} or `quit`{{execute interrupt}} command.
After exiting Arthas, you can also connect with `java -jar arthas-boot.jar`{{execute interrupt}} again.
## Stop Arthas
The `exit/quit` command simply exits the current session and the arthas server still runs in the target process.
To completely exit Arthas, you can execute the `stop`{{execute interrupt}} command.

@ -1,6 +0,0 @@
Through this tutorial, now you know how to use Arthas. More advanced features can be found in the Advanced Guide below.
* [Arthas Advanced](https://arthas.aliyun.com/doc/arthas-tutorials.html?language=en&id=arthas-advanced)
* [Arthas Github](https://github.com/alibaba/arthas)
* [Arthas Documentation](https://arthas.aliyun.com/doc/en)

@ -1,57 +0,0 @@
{
"title": "Arthas Basics",
"description": "Arthas Basics",
"details": {
"steps": [
{
"title": "Start arthas-demo",
"text": "arthas-demo.md"
},
{
"title": "Start arthas-boot",
"text": "arthas-boot.md"
},
{
"title": "Dashboard",
"text": "dashboard.md"
},
{
"title": "Thread",
"text": "thread.md"
},
{
"title": "Sc",
"text": "sc.md"
},
{
"title": "Jad",
"text": "jad.md"
},
{
"title": "Watch",
"text": "watch.md"
},
{
"title": "Vmtool",
"text": "vmtool.md"
},
{
"title": "Exit/Stop",
"text": "exit.md"
}
],
"intro": {
"text": "intro.md"
},
"finish": {
"text": "finish.md"
}
},
"environment": {
"uilayout": "terminal"
},
"backend": {
"imageid": "openjdk:15",
"environmentsprotocol": "http"
}
}

@ -1,11 +0,0 @@
![Arthas](https://arthas.aliyun.com/doc/_images/arthas.png)
`Arthas` is a Java diagnostic tool open-sourced by Alibaba middleware team. Arthas helps developers in trouble-shooting issues in production environment for Java based applications without modifying code or restarting servers.
`Arthas` supports JDK 6+, supports Linux/Mac/Windows.
* Github: https://github.com/alibaba/arthas
* Documentation: https://arthas.aliyun.com/doc/en

@ -1,4 +0,0 @@
The `jad` command can be used to decompile the byte code:
`jad demo.MathGame`{{execute T2}}

@ -1,4 +0,0 @@
The `sc` command can be used to find the loaded classes in the JVM:
`sc -d *MathGame`{{execute T2}}

@ -1,10 +0,0 @@
The `thread 1`{{execute interrupt}} command prints the stack of thread ID 1.
Arthas supports pipes, and you can find `main class` with `thread 1 | grep 'main('`{{execute T2}}.
You can see that `main class` is `demo.MathGame`:
```
$ thread 1 | grep 'main('
at demo.MathGame.main(MathGame.java:17)
```

@ -1,20 +0,0 @@
The `vmtool` command can search object in JVM.
`vmtool --action getInstances --className java.lang.String --limit 10`{{execute T2}}
```bash
$ vmtool --action getInstances --className java.lang.String --limit 10
@String[][
@String[com/taobao/arthas/core/shell/session/Session],
@String[com.taobao.arthas.core.shell.session.Session],
@String[com/taobao/arthas/core/shell/session/Session],
@String[com/taobao/arthas/core/shell/session/Session],
@String[com/taobao/arthas/core/shell/session/Session.class],
@String[com/taobao/arthas/core/shell/session/Session.class],
@String[com/taobao/arthas/core/shell/session/Session.class],
@String[com/],
@String[java/util/concurrent/ConcurrentHashMap$ValueIterator],
@String[java/util/concurrent/locks/LockSupport],
]
```

@ -1,5 +0,0 @@
The `watch` command can view the parameter/return value/exception of the method.
`watch demo.MathGame primeFactors returnObj`{{execute T2}}
Input `Q`{{execute T2}} or `Ctrl+C` to exit the watch command.

@ -1,16 +0,0 @@
在新的`Terminal 2`里,下载`arthas-boot.jar`,再用`java -jar`命令启动:
`wget https://arthas.aliyun.com/arthas-boot.jar
java -jar arthas-boot.jar`{{execute T2}}
`arthas-boot`是`Arthas`的启动程序它启动后会列出所有的Java进程用户可以选择需要诊断的目标进程。
选择第一个进程,输入 `1`{{execute T2}} ,再`Enter/回车`
Attach成功之后会打印Arthas LOGO。输入 `help`{{execute T2}} 可以获取到更多的帮助信息。
![Arthas Boot](/arthas/scenarios/common-resources/assets/arthas-boot.png)

@ -1,10 +0,0 @@
下载`math-game.jar`,再用`java -jar`命令启动:
`wget https://arthas.aliyun.com/math-game.jar
java -jar math-game.jar`{{execute T1}}
`math-game`是一个很简单的程序,它随机生成整数,再执行因式分解,把结果打印出来。如果生成的随机数是负数,则会打印提示信息。

@ -1,2 +0,0 @@
arthas中的后台异步任务使用了仿linux系统任务相关的命令。[linux任务相关介绍](https://ehlxr.me/2017/01/18/Linux-%E4%B8%AD-fg%E3%80%81bg%E3%80%81jobs%E3%80%81-%E6%8C%87%E4%BB%A4/)。

@ -1,11 +0,0 @@
通过本教程基本掌握了Arthas后台异步任务。如果有更多的技巧或者使用疑问欢迎在Issue里提出。
* Issues: https://github.com/alibaba/arthas/issues
* 文档: https://arthas.aliyun.com/doc
如果您在使用Arthas请让我们知道。您的使用对我们非常重要[查看](https://github.com/alibaba/arthas/issues/111)
欢迎关注公众号获取Arthas项目的信息、源码分析、案例实践。
![Arthas公众号](/arthas/scenarios/common-resources/assets/qrcode_gongzhonghao.jpg)

@ -1,63 +0,0 @@
{
"title": "Arthas 后台异步任务 案例",
"description": "Arthas 后台异步任务 案例",
"difficulty": "高级使用者",
"time": "10分钟",
"details": {
"steps": [
{
"title": "Arthas demo",
"text": "arthas-demo.md"
},
{
"title": "Start arthas-boot",
"text": "arthas-boot.md"
},
{
"title": "后台异步任务",
"text": "async-jobs.md"
},
{
"title": "使用&在后台执行任务",
"text": "run-cmd-in-backgd.md"
},
{
"title": "通过jobs查看任务",
"text": "list-backgd-jobs.md"
},
{
"title": "任务暂停和取消",
"text": "suspend-cancel-job.md"
},
{
"title": "fg、bg命令将命令转到前台、后台继续执行",
"text": "switch-foregd-backgd.md"
},
{
"title": "任务输出重定向",
"text": "redirect-output.md"
},
{
"title": "停止命令",
"text": "stop-job.md"
},
{
"title": "其他",
"text": "others.md"
}
],
"intro": {
"text": "intro.md"
},
"finish": {
"text": "finish.md"
}
},
"environment": {
"uilayout": "terminal"
},
"backend": {
"imageid": "openjdk:15",
"environmentsprotocol": "http"
}
}

@ -1,23 +0,0 @@
![Arthas](https://arthas.aliyun.com/doc/_images/arthas.png)
`Arthas` 是Alibaba开源的Java诊断工具深受开发者喜爱。在线排查问题无需重启动态跟踪Java代码实时监控JVM状态。
`Arthas` 支持JDK 6+支持Linux/Mac/Windows采用命令行交互模式同时提供丰富的 `Tab` 自动补全功能,进一步方便进行问题的定位和诊断。
当你遇到以下类似问题而束手无策时Arthas可以帮助你解决
- 这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception
- 我改的代码为什么没有执行到?难道是我没 commit分支搞错了
- 遇到问题无法在线上 debug难道只能通过加日志再重新发布吗
- 线上遇到某个用户的数据处理有问题,但线上同样无法 debug线下无法重现
- 是否有一个全局视角来查看系统的运行状况?
- 有什么办法可以监控到JVM的实时运行状态
- 怎么快速定位应用的热点,生成火焰图?
本教程会以一个简单的应用为例,演示后台异步任务。
* Github: https://github.com/alibaba/arthas
* 文档: https://arthas.aliyun.com/doc/

@ -1,24 +0,0 @@
如果希望查看当前有哪些arthas任务在执行可以执行jobs命令执行结果如下
`jobs`{{execute T2}}
```bash
$ jobs
[1]*
Running trace demo.MathGame primeFactors &
execution count : 49
start time : Wed Jul 22 05:47:52 GMT 2020
timeout date : Thu Jul 23 05:47:52 GMT 2020
session : aa75753d-74f1-4929-a829-7ff965345183 (current)
```
可以看到目前有一个后台任务在执行。
job id是10, `*` 表示此job是当前session创建
状态是Stopped
execution count是执行次数从启动开始已经执行了19次
timeout date是超时的时间到这个时间任务将会自动超时退出

@ -1,6 +0,0 @@
* 最多同时支持8个命令使用重定向将结果写日志
* 请勿同时开启过多的后台异步命令以免对目标JVM性能造成影响
* 如果不想停止arthas继续执行后台任务可以执行 `quit` 退出arthas控制台`stop` 会停止arthas 服务)

@ -1,11 +0,0 @@
可通过>或者>>将任务输出结果输出到指定的文件中,可以和&一起使用实现arthas命令的后台异步任务。比如
`trace demo.MathGame primeFactors >> test.out &`{{execute T2}}
这时 trace 命令会在后台执行,并且把结果输出到应用`工作目录`下面的`test.out`文件。可继续执行其他命令。并可查看文件中的命令执行结果。可以执行`pwd`命令查看当前应用的`工作目录`。
`pwd`{{execute T2}}
`cat test.out`{{execute T2}}

@ -1,6 +0,0 @@
比如希望在后台执行trace命令那么调用下面命令
`trace demo.MathGame primeFactors &`{{execute T2}}
这时命令在后台执行可以在console中继续执行其他命令。

@ -1,2 +0,0 @@
异步执行的命令,如果希望停止,可执行`kill`

@ -1,8 +0,0 @@
当任务正在前台执行,比如直接调用命令`trace Test t`或者调用后台执行命令`trace Test t &`后又通过fg命令将任务转到前台。这时console中无法继续执行命令但是可以接收并处理以下事件
`ctrl + z`将任务暂停。通过jbos查看任务状态将会变为Stopped通过`bg <job-id>`或者`fg <job-id>`可让任务重新开始执行
`ctrl + c`:停止任务
`ctrl + d`按照linux语义应当是退出终端目前arthas中是空实现不处理

@ -1,6 +0,0 @@
* 任务在后台执行或者暂停状态(`ctrl + z`暂停任务)时,执行`fg <job-id>`将可以把对应的任务转到前台继续执行。在前台执行时无法在console中执行其他命令
* 当任务处于暂停状态时(`ctrl + z`暂停任务),执行`bg <job-id>`将可以把对应的任务在后台继续执行
* 非当前session创建的job只能由当前session `fg`到前台执行

@ -1,16 +0,0 @@
In the new `Terminal 2`, download `arthas-boot.jar` and start with the `java -jar` command:
`wget https://arthas.aliyun.com/arthas-boot.jar
java -jar arthas-boot.jar`{{execute T2}}
`arthas-boot` is the launcher for `Arthas`. It lists all the Java processes, and the user can select the target process to be diagnosed.
Select the first process, type `1`{{execute T2}} then type `Enter`
After the Attach is successful, Arthas LOGO is printed. Enter `help`{{execute T2}} for more help.
![Arthas Boot](/arthas/scenarios/common-resources/assets/arthas-boot.png)

@ -1,11 +0,0 @@
Download `math-game.jar` and start with the `java -jar` command:
`wget https://arthas.aliyun.com/math-game.jar
java -jar math-game.jar`{{execute T1}}
`math-game` is a very simple program that randomly generates integers, performs factorization, and prints the results.
If the generated random number is negative, a error message will be printed.

@ -1,2 +0,0 @@
Asynchronous jobs in arthas. The idea is borrowed from [linux jobs](http://man7.org/linux/man-pages/man1/jobs.1p.html).

@ -1,7 +0,0 @@
Through this tutorial, now you know Arthas Async Jobs. If you have more tips or questions, please feel free to tell or ask in Issue.
* Issues: https://github.com/alibaba/arthas/issues
* Documentation: https://arthas.aliyun.com/doc/en
If you are using Arthas, please let us know that. Your use is very important to us: [View](https://github.com/alibaba/arthas/issues/111)

@ -1,63 +0,0 @@
{
"title": "Arthas Async Jobs",
"description": "Arthas Async Jobs",
"difficulty": "expert",
"time": "10 minutes",
"details": {
"steps": [
{
"title": "Arthas demo",
"text": "arthas-demo.md"
},
{
"title": "Start arthas-boot",
"text": "arthas-boot.md"
},
{
"title": "Async Jobs",
"text": "async-jobs.md"
},
{
"title": "Use & to run the command in the background",
"text": "run-cmd-in-backgd.md"
},
{
"title": "List background jobs",
"text": "list-backgd-jobs.md"
},
{
"title": "Suspend and cancel job",
"text": "suspend-cancel-job.md"
},
{
"title": "fg/bg, switch the job from the foreground to the background, and vise verse",
"text": "switch-foregd-backgd.md"
},
{
"title": "Redirect the output",
"text": "redirect-output.md"
},
{
"title": "Stop job",
"text": "stop-job.md"
},
{
"title": "Others",
"text": "others.md"
}
],
"intro": {
"text": "intro.md"
},
"finish": {
"text": "finish.md"
}
},
"environment": {
"uilayout": "terminal"
},
"backend": {
"imageid": "openjdk:15",
"environmentsprotocol": "http"
}
}

@ -1,39 +0,0 @@
![Arthas](https://arthas.aliyun.com/doc/_images/arthas.png)
`Arthas` is a Java diagnostic tool open-sourced by Alibaba middleware team. Arthas helps developers in trouble-shooting issues in production environment for Java based applications without modifying code or restarting servers.
`Arthas` supports JDK 6+, supports Linux/Mac/Windows.
## Background
Oftentimes 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. Whats even worse, debugging in production environment is unacceptable, as it will suspend all the threads, leading to services downtime.
Developers could always try to reproduce the same issue on the test/staging environment. However, this is tricky as some issues cannot be reproduced easily in a different environment, or even disappear once restarted.
And if youre 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! Worse still, the issue may not be fixed since it might be irreproducible once the JVM is restarted, as described above.
Arthas is built to solve these issues. A developer can troubleshoot production issues on the fly. No JVM restart, no additional code changes. Arthas works as an observer, that is, it will never suspend your running threads.
## Key features
- 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.
- Check classloader statistics, e.g. the number of classloaders, the number of classes loaded per classloader, the classloader hierarchy, possible classloader leaks, etc.
- Check the method invocation details, e.g. method parameter, returned values, exceptions and etc.
- Check the stack trace of specified method invocation. This is useful when a developer wants to know the caller of the method.
- Trace the method invocation to find slow sub-invocations.
- Monitor method invocation statistics, e.g. QPS (Query Per Second), RT (Return Time), 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.
- Supports profiler/Flame Graph
- Supports JDK 6+
- Supports Linux/Mac/Windows
This tutorial takes a simple application as an example to demonstrate the the use case of Async Jobs.
* Github: https://github.com/alibaba/arthas
* Docs: https://arthas.aliyun.com/doc/en

@ -1,24 +0,0 @@
If you want to list all background jobs, you can execute the jobs command and the results are as follows:
`jobs`{{execute T2}}
```bash
$ jobs
[1]*
Running trace demo.MathGame primeFactors &
execution count : 49
start time : Wed Jul 22 05:47:52 GMT 2020
timeout date : Thu Jul 23 05:47:52 GMT 2020
session : aa75753d-74f1-4929-a829-7ff965345183 (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: timeout timestamp, when the time exceeds this timestamp, the job will be automatically timeout and exit.

@ -1,6 +0,0 @@
* Support up to 8 commands at the same time to redirect the output to the log files.
* Do not open too many background jobs at the same time to avoid negative performance effect to the target JVM.
* If you do not want to stop the Arthas service and continue to perform background tasks, you can exit the Arthas console by executing `quit` command (`stop` command will stop the Arthas service)

@ -1,11 +0,0 @@
The job output can be redirect to the specified file by > or >>, and can be used together with &. By doing this, you can achieve running commands asynchronously, for example:
`trace demo.MathGame primeFactors >> test.out &`{{execute T2}}
At this time, the trace command will be executed in the background, and the result will be output to the `test.out` file under the `working directory` of the application. You can continue to execute other commands. And you can view the command execution result in the file. You can execute the `pwd` command to view the `working directory` of the current application.
`pwd`{{execute T2}}
`cat test.out`{{execute T2}}

@ -1,6 +0,0 @@
For example, execute the trace command in the background:
`trace demo.MathGame primeFactors &`{{execute T2}}
By doing this, the current command is put to the background to run, you can continue to execute other commands in the console.

@ -1,2 +0,0 @@
If you want to stop background job, just `kill <job-id>`.

@ -1,8 +0,0 @@
When the job is executing in the foreground, for example, directly executing the command` trace Test t`, or executing the background job command `trace Test t &`, then putting the job back to the foreground via fg command, the console cannot continue to execute other command, but can receive and process the following keyboard events:
`ctrl + z`: Suspends 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`: Stops the job
`ctrl + d`: According to linux semantics this should lead to exit the terminal, right now Arthas has not implemented this yet, therefore simply ignore this keystroke.

@ -1,6 +0,0 @@
* When a job is executed in the background or in suspended status (use `ctrl + z` to suspend job), `fg <job-id>` can transfer the job to the foreground to continue to run.
* When a job is in suspended status (use `ctrl + z` to suspend job), `bg <job-id>` can put the job to the background to continue to run.
* A job created by other session can only be put to the foreground to run by using `fg` in the current session.

@ -1,65 +0,0 @@
在新的`Terminal 2`里,下载`arthas-boot.jar`
`wget https://arthas.aliyun.com/arthas-boot.jar`{{execute T2}}
`arthas-boot.jar` 支持很多参数,可以执行 `java -jar arthas-boot.jar -h`{{execute T2}} 来查看。
```bash
$ java -jar arthas-boot.jar -h
[INFO] arthas-boot version: 3.3.6
Usage: arthas-boot [-h] [--target-ip <value>] [--telnet-port <value>]
[--http-port <value>] [--session-timeout <value>] [--arthas-home <value>]
[--use-version <value>] [--repo-mirror <value>] [--versions] [--use-http]
[--attach-only] [-c <value>] [-f <value>] [--height <value>] [--width
<value>] [-v] [--tunnel-server <value>] [--agent-id <value>] [--stat-url
<value>] [--select <value>] [pid]
Bootstrap Arthas
EXAMPLES:
java -jar arthas-boot.jar <pid>
java -jar arthas-boot.jar --target-ip 0.0.0.0
java -jar arthas-boot.jar --telnet-port 9999 --http-port -1
java -jar arthas-boot.jar --tunnel-server 'ws://192.168.10.11:7777/ws'
java -jar arthas-boot.jar --tunnel-server 'ws://192.168.10.11:7777/ws'
--agent-id bvDOe8XbTM2pQWjF4cfw
java -jar arthas-boot.jar --stat-url 'http://192.168.10.11:8080/api/stat'
java -jar arthas-boot.jar -c 'sysprop; thread' <pid>
java -jar arthas-boot.jar -f batch.as <pid>
java -jar arthas-boot.jar --use-version 3.3.6
java -jar arthas-boot.jar --versions
java -jar arthas-boot.jar --select math-game
java -jar arthas-boot.jar --session-timeout 3600
java -jar arthas-boot.jar --attach-only
java -jar arthas-boot.jar --repo-mirror aliyun --use-http
WIKI:
https://arthas.aliyun.com/doc
Options and Arguments:
-h,--help Print usage
--target-ip <value> The target jvm listen ip, default 127.0.0.1
--telnet-port <value> The target jvm listen telnet port, default 3658
--http-port <value> The target jvm listen http port, default 8563
--session-timeout <value> The session timeout seconds, default 1800
(30min)
--arthas-home <value> The arthas home
--use-version <value> Use special version arthas
--repo-mirror <value> Use special maven repository mirror, value is
center/aliyun or http repo url.
--versions List local and remote arthas versions
--use-http Enforce use http to download, default use https
--attach-only Attach target process only, do not connect
-c,--command <value> Command to execute, multiple commands separated
by ;
-f,--batch-file <value> The batch file to execute
--height <value> arthas-client terminal height
--width <value> arthas-client terminal width
-v,--verbose Verbose, print debug info.
--tunnel-server <value> The tunnel server url
--agent-id <value> The agent id register to tunnel server
--stat-url <value> The report stat url
--select <value> select target process by classname or
JARfilename
<pid> Target pid
```

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save