add tutorials/katacoda. #847
@ -0,0 +1,10 @@
|
||||
# Interactive Katacoda Scenarios
|
||||
|
||||
[![](http://shields.katacoda.com/katacoda/hengyunabc/count.svg)](https://www.katacoda.com/hengyunabc "Get your profile on Katacoda.com")
|
||||
|
||||
Visit https://www.katacoda.com/hengyunabc to view the profile and interactive scenarios
|
||||
|
||||
### Writing Scenarios
|
||||
Visit https://www.katacoda.com/docs to learn more about creating Katacoda scenarios
|
||||
|
||||
For examples, visit https://github.com/katacoda/scenario-example
|
After Width: | Height: | Size: 38 KiB |
After Width: | Height: | Size: 24 KiB |
After Width: | Height: | Size: 38 KiB |
After Width: | Height: | Size: 49 KiB |
@ -0,0 +1,9 @@
|
||||
|
||||
可以通过 `jad` 命令来反编译代码:
|
||||
|
||||
`jad com.example.demo.arthas.user.UserController`{{execute T2}}
|
||||
|
||||
|
||||
通过`--source-only`参数可以只打印出在反编译的源代码:
|
||||
|
||||
`jad --source-only com.example.demo.arthas.user.UserController`{{execute T2}}
|
@ -0,0 +1,30 @@
|
||||
|
||||
|
||||
`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}}
|
||||
|
||||
|
||||
|
After Width: | Height: | Size: 38 KiB |
After Width: | Height: | Size: 24 KiB |
After Width: | Height: | Size: 49 KiB |
@ -0,0 +1,136 @@
|
||||
|
||||
|
||||
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 -c 65361d9a`{{execute T2}}
|
||||
|
||||
```bash
|
||||
$ classloader -a -c 65361d9a
|
||||
hash:1698045338, org.apache.jasper.servlet.JasperLoader@65361d9a
|
||||
org.apache.jsp.jsp.hello_jsp
|
||||
```
|
||||
|
||||
### 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
|
||||
```
|
||||
|
||||
### 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 -c 1be6f5c3`{{execute T2}}
|
||||
|
||||
```
|
||||
$ classloader -c 1be6f5c3
|
||||
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 -c 1be6f5c3 -r logback-spring.xml`{{execute T2}}
|
||||
|
||||
```
|
||||
$ classloader -c 1be6f5c3 -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 -c 1be6f5c3 --load java.lang.String`{{execute T2}}
|
||||
|
||||
```
|
||||
$ classloader -c 1be6f5c3 --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
|
||||
```
|
||||
|
@ -0,0 +1,54 @@
|
||||
|
||||
|
||||
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://alibaba.github.io/arthas/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.
|
||||
```
|
@ -0,0 +1,56 @@
|
||||
|
||||
|
||||
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)
|
||||
```
|
@ -0,0 +1,39 @@
|
||||
|
||||
|
||||
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()
|
||||
```
|
@ -0,0 +1,84 @@
|
||||
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`.
|
||||
|
||||
### mc
|
||||
|
||||
After saving `/tmp/UserController.java`, compile with the `mc` (Memory Compiler) command and specify the ClassLoader with the `-c` option:
|
||||
|
||||
`mc -c 1be6f5c3 /tmp/UserController.java -d /tmp`{{execute T2}}
|
||||
|
||||
```bash
|
||||
$ mc -c 1be6f5c3 /tmp/UserController.java -d /tmp
|
||||
Memory compiler output:
|
||||
/tmp/com/example/demo/arthas/user/UserController.class
|
||||
Affect(row-cnt:1) cost in 346 ms
|
||||
```
|
||||
|
||||
### 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"
|
||||
}
|
||||
```
|
@ -0,0 +1,53 @@
|
||||
|
||||
|
||||
|
||||
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 -c 1be6f5c3 '@com.example.demo.arthas.user.UserController@logger'`{{execute T2}}
|
||||
|
||||
|
||||
```bash
|
||||
$ ognl -c 1be6f5c3 '@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 -c 1be6f5c3 '#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 -c 1be6f5c3 -r logback-spring.xml`{{execute T2}}
|
||||
|
||||
```
|
||||
$ classloader -c 1be6f5c3 -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 -c 1be6f5c3 -r logback.xml`{{execute T2}}
|
||||
|
||||
`classloader -c 1be6f5c3 -r log4j.properties`{{execute T2}}
|
||||
|
||||
|
@ -0,0 +1,24 @@
|
||||
|
||||
|
||||
### 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}}
|
@ -0,0 +1,98 @@
|
||||
|
||||
|
||||
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://alibaba.github.io/arthas/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}}
|
@ -0,0 +1,18 @@
|
||||
|
||||
|
||||
## 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.
|
||||
|
@ -0,0 +1,8 @@
|
||||
|
||||
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 ask in Issue.
|
||||
|
||||
* Issues: https://github.com/alibaba/arthas/issues
|
||||
* Documentation: https://alibaba.github.io/arthas
|
||||
|
||||
|
||||
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)
|
@ -0,0 +1,112 @@
|
||||
{
|
||||
"title": "Arthas Advanced",
|
||||
"description": "Arthas Advanced",
|
||||
"details": {
|
||||
"steps": [
|
||||
{
|
||||
"title": "Start demo",
|
||||
"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"
|
||||
},
|
||||
"assets": {
|
||||
"host01": [
|
||||
{
|
||||
"file": "arthas-boot.png",
|
||||
"target": "/tmp/arthas-boot.png"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"environment": {
|
||||
"uilayout": "terminal",
|
||||
"showdashboard": true,
|
||||
"dashboards": [
|
||||
{
|
||||
"name": "Web Port 80",
|
||||
"port": 80
|
||||
}
|
||||
]
|
||||
},
|
||||
"backend": {
|
||||
"imageid": "java",
|
||||
"environmentsprotocol": "http"
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
|
||||
|
||||
|
||||
![Arthas](https://alibaba.github.io/arthas/_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://alibaba.github.io/arthas/
|
@ -0,0 +1,8 @@
|
||||
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}}
|
@ -0,0 +1,29 @@
|
||||
|
||||
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.
|
@ -0,0 +1,54 @@
|
||||
|
||||
The `ognl` command can execute code dynamically.
|
||||
|
||||
### Invoke the static method
|
||||
|
||||
`ognl '@java.lang.System@out.println("hello ognl")'`{{execute T2}}
|
||||
|
||||
可以检查`Terminal 1`里的进程输出,可以发现打印出了`hello ognl`。
|
||||
|
||||
|
||||
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
|
||||
```
|
||||
|
||||
### Get static fields of static classes
|
||||
|
||||
Get the `logger` field of the `UserController` class:
|
||||
|
||||
`ognl -c 1be6f5c3 @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 -c 1be6f5c3 -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/proper/commons-ognl/language-guide.html
|
@ -0,0 +1,36 @@
|
||||
|
||||
|
||||
|
||||
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"]
|
||||
```
|
@ -0,0 +1,33 @@
|
||||
|
||||
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}}
|
||||
|
@ -0,0 +1,14 @@
|
||||
|
||||
|
||||
|
||||
|
||||
Download `demo-arthas-spring-boot.jar`, and start with `java -jar` command:
|
||||
|
||||
`wget https://github.com/hengyunabc/katacoda-scenarios/raw/master/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](/hengyunabc/scenarios/arthas-advanced-cn/assets/demo-web.png)
|
@ -0,0 +1,47 @@
|
||||
|
||||
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}}
|
@ -0,0 +1,20 @@
|
||||
|
||||
|
||||
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](/hengyunabc/scenarios/arthas-advanced-en/assets/web-console.png)
|
||||
|
||||
|
||||
It is recommended to experience it through "Quick Start": https://alibaba.github.io/arthas/en/quick-start.html
|
@ -0,0 +1,10 @@
|
||||
|
||||
|
||||
|
||||
|
||||
下载`arthas-demo.jar`,再用`java -jar`命令启动:
|
||||
|
||||
`wget https://alibaba.github.io/arthas/arthas-demo.jar
|
||||
java -jar arthas-demo.jar`{{execute T1}}
|
||||
|
||||
`arthas-demo`是一个很简单的程序,它随机生成整数,再执行因式分解,把结果打印出来。如果生成的随机数是负数,则会打印提示信息。
|
After Width: | Height: | Size: 38 KiB |
After Width: | Height: | Size: 38 KiB |
@ -0,0 +1,3 @@
|
||||
`dashboard`{{execute T2}} 命令可以查看当前系统的实时数据面板。
|
||||
|
||||
输入 `Q`{{execute T2}} 或者 `Ctrl+C` 可以退出dashboard命令。
|
@ -0,0 +1,61 @@
|
||||
{
|
||||
"title": "Arthas 基础教程",
|
||||
"description": "Arthas 基础教程",
|
||||
"details": {
|
||||
"steps": [
|
||||
{
|
||||
"title": "启动arthas-demo",
|
||||
"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": "Exit/Stop",
|
||||
"text": "exit.md"
|
||||
}
|
||||
],
|
||||
"intro": {
|
||||
"text": "intro.md"
|
||||
},
|
||||
"finish": {
|
||||
"text": "finish.md"
|
||||
},
|
||||
"assets": {
|
||||
"host01": [
|
||||
{
|
||||
"file": "arthas-boot.png",
|
||||
"target": "/tmp/arthas-boot.png"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"environment": {
|
||||
"uilayout": "terminal"
|
||||
},
|
||||
"backend": {
|
||||
"imageid": "java",
|
||||
"environmentsprotocol": "http"
|
||||
}
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
|
||||
可以通过 `jad` 命令来反编译代码:
|
||||
|
||||
`jad demo.MathGame`{{execute T2}}
|
@ -0,0 +1,6 @@
|
||||
|
||||
通过`watch`命令可以查看函数的参数/返回值/异常信息。
|
||||
|
||||
`watch demo.MathGame primeFactors returnObj`{{execute T2}}
|
||||
|
||||
输入 `Q`{{execute T2}} 或者 `Ctrl+C` 退出watch命令。
|
@ -0,0 +1,11 @@
|
||||
|
||||
|
||||
|
||||
|
||||
Download `arthas-demo.jar` and start with the `java -jar` command:
|
||||
|
||||
`wget https://alibaba.github.io/arthas/arthas-demo.jar
|
||||
java -jar arthas-demo.jar`{{execute T1}}
|
||||
|
||||
`arthas-demo` 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.
|
After Width: | Height: | Size: 38 KiB |
@ -0,0 +1,3 @@
|
||||
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.
|
@ -0,0 +1,13 @@
|
||||
|
||||
|
||||
## 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.
|
@ -0,0 +1,6 @@
|
||||
|
||||
Through this tutorial, you can know how to use Arthas. More advanced features can be found in the Advanced Guide below.
|
||||
|
||||
* [Arthas Advanced](https://alibaba.github.io/arthas/arthas-tutorials?language=en&id=arthas-advanced)
|
||||
* [Arthas Github](https://github.com/alibaba/arthas)
|
||||
* [Arthas Documentation](https://alibaba.github.io/arthas/en)
|
@ -0,0 +1,61 @@
|
||||
{
|
||||
"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": "Exit/Stop",
|
||||
"text": "exit.md"
|
||||
}
|
||||
],
|
||||
"intro": {
|
||||
"text": "intro.md"
|
||||
},
|
||||
"finish": {
|
||||
"text": "finish.md"
|
||||
},
|
||||
"assets": {
|
||||
"host01": [
|
||||
{
|
||||
"file": "arthas-boot.png",
|
||||
"target": "/tmp/arthas-boot.png"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"environment": {
|
||||
"uilayout": "terminal"
|
||||
},
|
||||
"backend": {
|
||||
"imageid": "java",
|
||||
"environmentsprotocol": "http"
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
|
||||
|
||||
|
||||
![Arthas](https://alibaba.github.io/arthas/_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://alibaba.github.io/arthas/en
|
@ -0,0 +1,4 @@
|
||||
|
||||
The `jad` command can be used to decompile the byte code:
|
||||
|
||||
`jad demo.MathGame`{{execute T2}}
|
@ -0,0 +1,4 @@
|
||||
|
||||
The `sc` command can be used to find the loaded classes in the JVM:
|
||||
|
||||
`sc -d *MathGame`{{execute T2}}
|
@ -0,0 +1,10 @@
|
||||
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)
|
||||
```
|
@ -0,0 +1,5 @@
|
||||
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.
|
@ -0,0 +1,17 @@
|
||||
{
|
||||
"title": "Arthas 教程",
|
||||
"description": "使用Arthas的教程",
|
||||
"icon": "fa-katacoda",
|
||||
"courses": [
|
||||
{
|
||||
"course_id": "arthas-basics-cn",
|
||||
"title": "Arthas基础教程",
|
||||
"description": "Arthas基础教程"
|
||||
},
|
||||
{
|
||||
"course_id": "arthas-advanced-cn",
|
||||
"title": "Arthas进阶教程",
|
||||
"description": "Arthas进阶教程"
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
{
|
||||
"title": "Arthas Tutorials",
|
||||
"description": "Example of Arthas",
|
||||
"icon": "fa-katacoda",
|
||||
"courses": [
|
||||
{
|
||||
"course_id": "arthas-basics-en",
|
||||
"title": "Arthas Basics",
|
||||
"description": "Arthas Basics"
|
||||
},
|
||||
{
|
||||
"course_id": "arthas-advanced-en",
|
||||
"title": "Arthas Advanced",
|
||||
"description": "Arthas Advanced"
|
||||
}
|
||||
]
|
||||
}
|