Java虚拟机arthas阿尔萨斯
启动阿尔萨斯
java -jar arthas-boot.jar
初始界面
(base) PS D:\Program Files\arthas> java -jar arthas-boot.jar
[INFO] JAVA_HOME: D:\graalvm-jdk-24.0.1+9.1
[INFO] arthas-boot version: 4.1.4
[INFO] Found existing java process, please choose one and input the serial number of the process, eg : 1. Then hit ENTER.
* [1]: 22656 D:\Program
[2]: 19268 com.intellij.idea.Main
[3]: 33144 com.xxx.Main
3
[INFO] arthas home: D:\Program Files\arthas
WARNING: A restricted method in java.lang.System has been called
WARNING: java.lang.System::loadLibrary has been called by org.fusesource.hawtjni.runtime.Library in an unnamed module (file:/D:/Program%20Files/arthas/arthas-client.jar)
WARNING: Use --enable-native-access=ALL-UNNAMED to avoid a warning for callers in this module
WARNING: Restricted methods will be blocked in a future release unless native access is enabled
[INFO] Try to attach process 33144
Picked up JAVA_TOOL_OPTIONS:
[INFO] Attach process 33144 success.
[INFO] arthas-client connect 127.0.0.1 3658
,---. ,------. ,--------.,--. ,--. ,---. ,---.
/ O \ | .--. ''--. .--'| '--' | / O \ ' .-'
| .-. || '--'.' | | | .--. || .-. |`. `-.
| | | || |\ \ | | | | | || | | |.-' |
`--' `--'`--' '--' `--' `--' `--'`--' `--'`-----'
wiki https://arthas.aliyun.com/doc
tutorials https://arthas.aliyun.com/doc/arthas-tutorials.html
version 4.1.4
main_class com.xxx.Main
pid 33144
start_time 2026-01-09 18:44:10.141
current_time 2026-01-09 18:46:02.407
[arthas@33144]$
classloader
[arthas@34464]$ classloader -t
+-BootstrapClassLoader
+-jdk.internal.loader.ClassLoaders$PlatformClassLoader@15dc4deb
+-com.taobao.arthas.agent.ArthasClassloader@66043fe0
+-jdk.internal.loader.ClassLoaders$AppClassLoader@7852e922
Affect(row-cnt:4) cost in 5 ms.
[arthas@34464]$
dashboard
[arthas@34464]$ dashboard
ID NAME GROUP PRIORITY STATE %CPU DELTA_TIM TIME INTERRUPT DAEMON
3 main main 5 RUNNABLE 0.0 0.000 0:0.000 false false
15 Reference Handler system 10 RUNNABLE 0.0 0.000 0:0.000 false true
16 Finalizer system 8 WAITING 0.0 0.000 0:0.000 false true
17 Signal Dispatcher system 9 RUNNABLE 0.0 0.000 0:0.000 false true
18 Attach Listener system 5 RUNNABLE 0.0 0.000 0:0.000 false true
33 Notification Thread system 9 RUNNABLE 0.0 0.000 0:0.000 false true
34 Common-Cleaner InnocuousThrea 8 TIMED_WA 0.0 0.000 0:0.000 false true
36 arthas-timer system 5 WAITING 0.0 0.000 0:0.000 false true
54 arthas-NettyHttpTelnetBootstr system 5 RUNNABLE 0.0 0.000 0:0.000 false true
55 arthas-NettyWebsocketTtyBoots system 5 RUNNABLE 0.0 0.000 0:0.000 false true
56 arthas-NettyWebsocketTtyBoots system 5 RUNNABLE 0.0 0.000 0:0.000 false true
Memory used total max usage GC
heap 24M 68M 8156M 0.31% gc.g1_young_generation.count 7
g1_eden_space 12M 36M -1 33.33% gc.g1_young_generation.time(m 37
g1_old_gen 10M 28M 8156M 0.13% s)
g1_survivor_space 2M 4M -1 65.76% gc.g1_concurrent_gc.count 2
nonheap 47M 51M -1 93.08% gc.g1_concurrent_gc.time(ms) 1
codeheap_'non-nmethods' 1M 4M 7M 19.70% gc.g1_old_generation.count 0
metaspace 30M 30M -1 98.86% gc.g1_old_generation.time(ms) 0
Runtime
os.name Windows 11
os.version 10.0
java.version 24.0.1
java.home D:\graalvm-jdk-24.0.1+9.1
systemload.average -1.00
processors 16
timestamp/uptime Mon Jan 12 17:02:51 HKT 2026/10114s
谁加载了谁
gemini说
BootstrapClassLoader:最顶层。它是用 C++ 编写的,在 Java 里没有对象,所以它没有 @hash 地址。它负责加载 Java 的核心类(如 java.lang.String)。
PlatformClassLoader:中间层。负责加载一些扩展的系统功能。
AppClassLoader (@7852e922):底层(通常意义上的)。你的 com.xxx.Main 就是由它加载的。
端口占用taskkill
(base) PS D:\Program Files\arthas> netstat -ano | findstr "3658"
TCP 127.0.0.1:3658 0.0.0.0:0 LISTENING 13548
TCP 127.0.0.1:3658 127.0.0.1:52722 TIME_WAIT 0
TCP 127.0.0.1:53765 127.0.0.1:3658 TIME_WAIT 0
(base) PS D:\Program Files\arthas> taskkill -pid 13548
成功: 给进程发送了终止信号,进程的 PID 为 13548。
版本
G1垃圾回收器
docker exec -it my-container sh
# which java
/opt/java/openjdk/bin/java
# java -version
openjdk version "17.0.17" 2025-10-21
OpenJDK Runtime Environment Temurin-17.0.17+10 (build 17.0.17+10)
OpenJDK 64-Bit Server VM Temurin-17.0.17+10 (build 17.0.17+10, mixed mode, sharing)
#
方法区
在jdk8后由元空间metaspace实现 nonheap非堆
宏观查看
memory
[arthas@7]$ memory
Memory used
heap 127M
g1_eden_space 58M
g1_old_gen 30M
g1_survivor_space 39M
nonheap 131M
codeheap_'non-nmethods' 1M
metaspace 92M
codeheap_'profiled_nmethods' 17M
compressed_class_space 11M
codeheap_'non-profiled_nmethods' 7M
mapped 0K
direct 136M
mapped - 'non-volatile memory' 0K
dashboard
Memory used total max usage
heap 130M 512M 1024M 12.76%
g1_eden_space 61M 284M -1 21.48%
g1_old_gen 30M 189M 1024M 2.99%
g1_survivor_space 39M 39M -1 100.00%
nonheap 131M 135M -1 97.26%
codeheap_'non-nmethods' 1M 4M 7M 22.08%
metaspace 92M 93M -1 99.30%
codeheap_'profiled_nmethods' 17M 17M 116M 14.88%
compressed_class_space 11M 12M 1024M 1.16%
codeheap_'non-profiled_nmethods' 7M 8M 116M 6.88%
mapped 0K 0K - 0.00%
direct 136M 136M - 100.00%
mapped - 'non-volatile memory' 0K 0K - 0.00%
类加载器统计classloader -t
ai说
BootstrapClassLoader (根加载器):
地位:它是最高统治者,由 C++ 编写,没有父类。
职责:加载 Java 的核心命脉,比如 java.lang.*(String, Object 等)。
LaunchedClassLoader (Spring Boot 专属):
特点:这是 Spring Boot 为了实现“一个 Jar 包跑天下”而自定义的加载器。它能读取内嵌在 Jar 包里的 Jar 包。
委派逻辑
当 LaunchedClassLoader 想要加载一个类时,它先问 AppClassLoader:“爹,你那有吗?”;AppClassLoader 再问 PlatformClassLoader,直到问到 Bootstrap。
+-BootstrapClassLoader
+-jdk.internal.loader.ClassLoaders$PlatformClassLoader@466fa33f
+-com.taobao.arthas.agent.ArthasClassloader@790b0ad1
+-jdk.internal.loader.ClassLoaders$AppClassLoader@46faa73d
+-org.springframework.boot.loader.launch.LaunchedClassLoader@4517d9a3
+-com.alibaba.fastjson.util.ASMClassLoader@9ad7e92
Affect(row-cnt:6) cost in 31 ms.
类加载器统计classloader -stats
谁往方法区塞了东西?
方法区的内容是由类加载器扔进去的。
[arthas@7]$ classloader -stats
name numberOfInstances loadedCountTotal
org.springframework.boot.loader.launch.LaunchedClassLoader 1 12443
BootstrapClassLoader 1 4923
com.taobao.arthas.agent.ArthasClassloader 1 2397
jdk.internal.loader.ClassLoaders$AppClassLoader 1 112
jdk.internal.loader.ClassLoaders$PlatformClassLoader 1 110
jdk.internal.reflect.DelegatingClassLoader 76 76
Affect(row-cnt:6) cost in 16 ms.
类信息检索 sc -d 具体类名比如( sc -d java.lang.String)
方法区存的是类长什么样子 而不是具体对象
[arthas@7]$ sc -d org.springframework.web.servlet.DispatcherServlet
class-info org.springframework.web.servlet.DispatcherServlet
code-source nested:/app/app.jar/!BOOT-INF/lib/spring-webmvc-6.2.7.jar!/
name org.springframework.web.servlet.DispatcherServlet
isInterface false
isAnnotation false
isEnum false
isAnonymousClass false
isArray false
isLocalClass false
isMemberClass false
isPrimitive false
isSynthetic false
simple-name DispatcherServlet
modifier public
annotation
interfaces
super-class +-org.springframework.web.servlet.FrameworkServlet
+-org.springframework.web.servlet.HttpServletBean
+-jakarta.servlet.http.HttpServlet
+-jakarta.servlet.GenericServlet
+-java.lang.Object
class-loader +-org.springframework.boot.loader.launch.LaunchedClassLoader@1f32e575
+-jdk.internal.loader.ClassLoaders$AppClassLoader@67424e82
+-jdk.internal.loader.ClassLoaders$PlatformClassLoader@1cd0b198
classLoaderHash 1f32e575
Affect(row-cnt:1) cost in 73 ms.
堆
memory
g1_eden_space 77M 284M -1 27.11%
g1_old_gen 30M 189M 1024M 2.99%
g1_survivor_space 39M 39M -1 100.00%
对象真实的内存地址和内容
方法区里存的是 java.lang.String 这个名字,而堆里存的是具体的 "abc" 内容。
[arthas@1]$ vmtool --action getInstances --className java.lang.String --limit 10
@String[][
@String[Copy],
@String[Allocation Failure],
@String[end of minor GC],
@String[com/taobao/arthas/core/shell/term/impl/http/TtyServerInitializer.class],
@String[java.lang:type=GarbageCollector,name=Copy],
@String[java.lang:name=Copy,type=GarbageCollector],
@String[com.taobao.arthas.core.shell.term.impl.http.TtyServerInitializer],
@String[type],
@String[name],
@String[com/taobao/arthas/core/shell/term/impl/http/TtyServerInitializer],
]
服务实现类
[arthas@1]$ vmtool --action getInstances --className com.xxx.service.impl.XXXServiceImpl --limit 10
@XXXServiceImpl[][
@XXXServiceImpl[com.xxx.service.impl.XXXServiceImpl@1e299e3f],
]
[arthas@1]$ vmtool --action getInstances --className com.xxx.service.impl.xxxServiceImpl --expand 2
@xxxServiceImpl[][
@xxxServiceImpl[
xxxRepository=@$Proxy222[org.springframework.data.r2dbc.repository.support.SimpleR2dbcRepository@37edf12f],
xxxRepository=@$Proxy224[org.springframework.data.r2dbc.repository.support.SimpleR2dbcRepository@1bdd747c],
],
]
我调用方法马上看数据库实体
[arthas@1]$ vmtool --action getInstances --className com.xxx.r2dbc.entity.xxx --limit 10
@xxx[][
@xxx[xxx(id=215, userId=1, userName=xxx,createTime=2025-07-14T22:16:20, 后面省略 业务数据
watch
[arthas@1]$ watch com.xxx.controller.admin.xxx list "{params[0]}" -x 2
<!--Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 296 ms, listenerId: 1
-->
method=com.xxx.controller.xxxController.list location=AtExit
ts=2026-01-15 18:58:44.586; [cost=0.92213ms] result=@ArrayList[
@xxxQuery[
serialVersionUID=@Long[21230553180750],
status=null,
],
]

浙公网安备 33010602011771号