diff --git a/tutorials/katacoda/arthas-advanced-cn/case-classloader.md b/tutorials/katacoda/arthas-advanced-cn/case-classloader.md index 7508fd97c..32e561ba3 100644 --- a/tutorials/katacoda/arthas-advanced-cn/case-classloader.md +++ b/tutorials/katacoda/arthas-advanced-cn/case-classloader.md @@ -80,12 +80,13 @@ $ classloader -t +-org.apache.jasper.servlet.JasperLoader@21ae0fe2 ``` +注意:请使用你的classLoaderHash值覆盖 `` ,然后手动执行下面相关命令: ### 列出ClassLoader的urls 比如上面查看到的spring LaunchedURLClassLoader的 hashcode是`1be6f5c3`,可以通过`-c`参数来列出它的所有urls: -`classloader -c 1be6f5c3`{{execute T2}} +`classloader -c ` ``` $ classloader -c 1be6f5c3 @@ -97,7 +98,7 @@ jar:file:/home/scrapbook/tutorial/demo-arthas-spring-boot.jar!/BOOT-INF/lib/spri ### 加载指定ClassLoader里的资源文件 -查找指定的资源文件: `classloader -c 1be6f5c3 -r logback-spring.xml`{{execute T2}} +查找指定的资源文件: `classloader -c -r logback-spring.xml` ``` $ classloader -c 1be6f5c3 -r logback-spring.xml @@ -108,7 +109,7 @@ $ classloader -c 1be6f5c3 -r logback-spring.xml 比如用上面的spring LaunchedURLClassLoader 尝试加载 `java.lang.String` : -`classloader -c 1be6f5c3 --load java.lang.String`{{execute T2}} +`classloader -c --load java.lang.String` ``` $ classloader -c 1be6f5c3 --load java.lang.String diff --git a/tutorials/katacoda/arthas-advanced-cn/case-jad-mc-redefine.md b/tutorials/katacoda/arthas-advanced-cn/case-jad-mc-redefine.md index 92b7a244c..6cb8d7fc5 100644 --- a/tutorials/katacoda/arthas-advanced-cn/case-jad-mc-redefine.md +++ b/tutorials/katacoda/arthas-advanced-cn/case-jad-mc-redefine.md @@ -45,11 +45,15 @@ $ sc -d *UserController | grep classLoaderHash 可以发现是 spring boot `LaunchedURLClassLoader@1be6f5c3` 加载的。 +请记下你的classLoaderHash,后面需要使用它。在这里,它是 `1be6f5c3`。 + +注意:请使用你的classLoaderHash值覆盖 `` ,然后手动执行这些命令: + ### mc 保存好`/tmp/UserController.java`之后,使用`mc`(Memory Compiler)命令来编译,并且通过`-c`参数指定ClassLoader: -`mc -c 1be6f5c3 /tmp/UserController.java -d /tmp`{{execute T2}} +`mc -c /tmp/UserController.java -d /tmp` ```bash $ mc -c 1be6f5c3 /tmp/UserController.java -d /tmp diff --git a/tutorials/katacoda/arthas-advanced-cn/case-logger-config-problem.md b/tutorials/katacoda/arthas-advanced-cn/case-logger-config-problem.md index e37c7d0c5..da6ad4dc2 100644 --- a/tutorials/katacoda/arthas-advanced-cn/case-logger-config-problem.md +++ b/tutorials/katacoda/arthas-advanced-cn/case-logger-config-problem.md @@ -6,11 +6,11 @@ 以`UserController`为例,它使用的是slf4j api,但实际使用到的logger系统是logback。 -`ognl -c 1be6f5c3 '@com.example.demo.arthas.user.UserController@logger'`{{execute T2}} +`ognl --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader '@com.example.demo.arthas.user.UserController@logger'`{{execute T2}} ```bash -$ ognl -c 1be6f5c3 '@com.example.demo.arthas.user.UserController@logger' +$ 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], @@ -28,15 +28,15 @@ $ ognl -c 1be6f5c3 '@com.example.demo.arthas.user.UserController@logger' ### 获取logback实际加载的配置文件 -`ognl -c 1be6f5c3 '#map1=@org.slf4j.LoggerFactory@getLogger("root").loggerContext.objectMap, #map1.get("CONFIGURATION_WATCH_LIST")'`{{execute T2}} +`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 -c 1be6f5c3 -r logback-spring.xml`{{execute T2}} +`classloader --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader -r logback-spring.xml`{{execute T2}} ``` -$ classloader -c 1be6f5c3 -r logback-spring.xml +$ 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. @@ -45,8 +45,8 @@ Affect(row-cnt:1) cost in 13 ms. 可以尝试加载容易冲突的文件: -`classloader -c 1be6f5c3 -r logback.xml`{{execute T2}} +`classloader --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader -r logback.xml`{{execute T2}} -`classloader -c 1be6f5c3 -r log4j.properties`{{execute T2}} +`classloader --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader -r log4j.properties`{{execute T2}} diff --git a/tutorials/katacoda/arthas-advanced-cn/case-ognl-update-logger-level.md b/tutorials/katacoda/arthas-advanced-cn/case-ognl-update-logger-level.md index 2cffd64b9..a2c3fcca8 100644 --- a/tutorials/katacoda/arthas-advanced-cn/case-ognl-update-logger-level.md +++ b/tutorials/katacoda/arthas-advanced-cn/case-ognl-update-logger-level.md @@ -14,10 +14,10 @@ $ sc -d com.example.demo.arthas.user.UserController | grep classLoaderHash ### 用ognl获取logger -`ognl -c 1be6f5c3 '@com.example.demo.arthas.user.UserController@logger'`{{execute T2}} +`ognl --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader '@com.example.demo.arthas.user.UserController@logger'`{{execute T2}} ```bash -$ ognl -c 1be6f5c3 '@com.example.demo.arthas.user.UserController@logger' +$ 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], @@ -36,14 +36,14 @@ $ ognl -c 1be6f5c3 '@com.example.demo.arthas.user.UserController@logger' ### 单独设置UserController的logger level -`ognl -c 1be6f5c3 '@com.example.demo.arthas.user.UserController@logger.setLevel(@ch.qos.logback.classic.Level@DEBUG)'`{{execute T2}} +`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 -c 1be6f5c3 '@com.example.demo.arthas.user.UserController@logger'`{{execute T2}} +`ognl --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader '@com.example.demo.arthas.user.UserController@logger'`{{execute T2}} ```bash -$ ognl -c 1be6f5c3 '@com.example.demo.arthas.user.UserController@logger' +$ 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], @@ -62,5 +62,5 @@ $ ognl -c 1be6f5c3 '@com.example.demo.arthas.user.UserController@logger' 通过获取`root` logger,可以修改全局的logger level: -`ognl -c 1be6f5c3 '@org.slf4j.LoggerFactory@getLogger("root").setLevel(@ch.qos.logback.classic.Level@DEBUG)'`{{execute T2}} +`ognl --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader '@org.slf4j.LoggerFactory@getLogger("root").setLevel(@ch.qos.logback.classic.Level@DEBUG)'`{{execute T2}} diff --git a/tutorials/katacoda/arthas-advanced-cn/ognl.md b/tutorials/katacoda/arthas-advanced-cn/ognl.md index 3fb2c2322..7a1c25d20 100644 --- a/tutorials/katacoda/arthas-advanced-cn/ognl.md +++ b/tutorials/katacoda/arthas-advanced-cn/ognl.md @@ -18,15 +18,36 @@ $ sc -d com.example.demo.arthas.user.UserController | grep classLoaderHash classLoaderHash 1be6f5c3 ``` +注意hashcode是变化的,需要先查看当前的ClassLoader信息,提取对应ClassLoader的hashcode。 + +如果你使用`-c`,你需要手动输入hashcode:`-c ` + +```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 `是动态变化的。 + ### 获取静态类的静态字段 获取`UserController`类里的`logger`字段: -`ognl -c 1be6f5c3 @com.example.demo.arthas.user.UserController@logger`{{execute T2}} +`ognl --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader @com.example.demo.arthas.user.UserController@logger`{{execute T2}} 还可以通过`-x`参数控制返回值的展开层数。比如: -`ognl -c 1be6f5c3 -x 2 @com.example.demo.arthas.user.UserController@logger`{{execute T2}} +`ognl --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader -x 2 @com.example.demo.arthas.user.UserController@logger`{{execute T2}} ### 执行多行表达式,赋值给临时变量,返回一个List diff --git a/tutorials/katacoda/arthas-advanced-en/case-classloader.md b/tutorials/katacoda/arthas-advanced-en/case-classloader.md index 4a05d65fe..06d50c16b 100644 --- a/tutorials/katacoda/arthas-advanced-en/case-classloader.md +++ b/tutorials/katacoda/arthas-advanced-en/case-classloader.md @@ -81,11 +81,13 @@ $ classloader -t +-org.apache.jasper.servlet.JasperLoader@21ae0fe2 ``` +Note: Please replace `` 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 -c 1be6f5c3`{{execute T2}} +`classloader -c ` ``` $ classloader -c 1be6f5c3 @@ -97,7 +99,7 @@ jar:file:/home/scrapbook/tutorial/demo-arthas-spring-boot.jar!/BOOT-INF/lib/spri ### Load the resource file in the specified ClassLoader -Load the specified resource file: `classloader -c 1be6f5c3 -r logback-spring.xml`{{execute T2}} +Load the specified resource file: `classloader -c -r logback-spring.xml` ``` $ classloader -c 1be6f5c3 -r logback-spring.xml @@ -108,7 +110,7 @@ $ classloader -c 1be6f5c3 -r logback-spring.xml For example, try loading `java.lang.String` with spring LaunchedURLClassLoader : -`classloader -c 1be6f5c3 --load java.lang.String`{{execute T2}} +`classloader -c --load java.lang.String` ``` $ classloader -c 1be6f5c3 --load java.lang.String diff --git a/tutorials/katacoda/arthas-advanced-en/case-jad-mc-redefine.md b/tutorials/katacoda/arthas-advanced-en/case-jad-mc-redefine.md index 7bd589bd7..320395eb4 100644 --- a/tutorials/katacoda/arthas-advanced-en/case-jad-mc-redefine.md +++ b/tutorials/katacoda/arthas-advanced-en/case-jad-mc-redefine.md @@ -46,11 +46,15 @@ $ sc -d *UserController | grep classLoaderHash 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. + +Note: Please replace `` with your classLoaderHash above, then execute the related commands manually in the following steps: + ### 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}} +`mc -c /tmp/UserController.java -d /tmp` ```bash $ mc -c 1be6f5c3 /tmp/UserController.java -d /tmp diff --git a/tutorials/katacoda/arthas-advanced-en/case-logger-config-problem.md b/tutorials/katacoda/arthas-advanced-en/case-logger-config-problem.md index 7c3d56a9d..908298d50 100644 --- a/tutorials/katacoda/arthas-advanced-en/case-logger-config-problem.md +++ b/tutorials/katacoda/arthas-advanced-en/case-logger-config-problem.md @@ -7,11 +7,11 @@ In this case, show how to troubleshoot logger conflicts. 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}} +`ognl --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader '@com.example.demo.arthas.user.UserController@logger'`{{execute T2}} ```bash -$ ognl -c 1be6f5c3 '@com.example.demo.arthas.user.UserController@logger' +$ 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], @@ -29,15 +29,15 @@ $ ognl -c 1be6f5c3 '@com.example.demo.arthas.user.UserController@logger' ### 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}} +`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 -c 1be6f5c3 -r logback-spring.xml`{{execute T2}} +`classloader --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader -r logback-spring.xml`{{execute T2}} ``` -$ classloader -c 1be6f5c3 -r logback-spring.xml +$ 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. @@ -46,8 +46,8 @@ 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 --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader -r logback.xml`{{execute T2}} -`classloader -c 1be6f5c3 -r log4j.properties`{{execute T2}} +`classloader --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader -r log4j.properties`{{execute T2}} diff --git a/tutorials/katacoda/arthas-advanced-en/case-ognl-update-logger-level.md b/tutorials/katacoda/arthas-advanced-en/case-ognl-update-logger-level.md index 671f86432..ac3fe73a5 100644 --- a/tutorials/katacoda/arthas-advanced-en/case-ognl-update-logger-level.md +++ b/tutorials/katacoda/arthas-advanced-en/case-ognl-update-logger-level.md @@ -12,10 +12,10 @@ $ sc -d com.example.demo.arthas.user.UserController | grep classLoaderHash ### Use ognl command to get the logger -`ognl -c 1be6f5c3 '@com.example.demo.arthas.user.UserController@logger'`{{execute T2}} +`ognl --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader '@com.example.demo.arthas.user.UserController@logger'`{{execute T2}} ```bash -$ ognl -c 1be6f5c3 '@com.example.demo.arthas.user.UserController@logger' +$ 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], @@ -36,14 +36,14 @@ The user can know that `UserController@logger` actually uses logback. Because `l ### Change the logger level of UserController -`ognl -c 1be6f5c3 '@com.example.demo.arthas.user.UserController@logger.setLevel(@ch.qos.logback.classic.Level@DEBUG)'`{{execute T2}} +`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 -c 1be6f5c3 '@com.example.demo.arthas.user.UserController@logger'`{{execute T2}} +`ognl --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader '@com.example.demo.arthas.user.UserController@logger'`{{execute T2}} ```bash -$ ognl -c 1be6f5c3 '@com.example.demo.arthas.user.UserController@logger' +$ 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], @@ -62,5 +62,5 @@ $ ognl -c 1be6f5c3 '@com.example.demo.arthas.user.UserController@logger' By getting the `root` logger, the user can modify the global logger level: -`ognl -c 1be6f5c3 '@org.slf4j.LoggerFactory@getLogger("root").setLevel(@ch.qos.logback.classic.Level@DEBUG)'`{{execute T2}} +`ognl --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader '@org.slf4j.LoggerFactory@getLogger("root").setLevel(@ch.qos.logback.classic.Level@DEBUG)'`{{execute T2}} diff --git a/tutorials/katacoda/arthas-advanced-en/ognl.md b/tutorials/katacoda/arthas-advanced-en/ognl.md index cc31fac58..e5e1a6ca4 100644 --- a/tutorials/katacoda/arthas-advanced-en/ognl.md +++ b/tutorials/katacoda/arthas-advanced-en/ognl.md @@ -20,15 +20,35 @@ $ 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 `. + +```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 ` is dynamic. + ### 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}} +`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 -c 1be6f5c3 -x 2 @com.example.demo.arthas.user.UserController@logger`{{execute T2}} +`ognl --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader -x 2 @com.example.demo.arthas.user.UserController@logger`{{execute T2}} ### Execute multi-line expressions diff --git a/tutorials/katacoda/common-resources/assets/demo-web.png b/tutorials/katacoda/common-resources/assets/demo-web.png new file mode 100644 index 000000000..a1466ad0a Binary files /dev/null and b/tutorials/katacoda/common-resources/assets/demo-web.png differ