前言
接前一篇 Signal Dispatcher, 25 关于 Signal Dispatcher
呵呵 关于常见的几个线程 AttchListener, Signal Dispatcher, Reference Handler, Finalizer, 虽然 平时使用的不是很多吧, 但是 还是可以了解一下的
这里 我们便来看一下 Attach Listener 这个线程吧
呵呵 这个 Attach Listener, 在一些常用的工具里面 经常会和它有关, 比如 jstack, jinfo, jmap, jconsole 等等, 都可能会和 Attach Listener 进行交互的
一下的相关代码, 截图如果没有特殊说明 基于 jdk9
测试用例
package com.hx.test05;
/**
* Test25AttachListener
*
* @author Jerry.X.He <970655147@qq.com>
* @version 1.0
* @date 2020-05-05 17:24
*/
public class Test25AttachListener {
// Test25AttachListener
public static void main(String[] args) throws Exception {
System.out.println(" I'm wait for ... ");
System.in.read();
}
}
这个相对比较简单, 只要保证 vm 立即结束就行
然后 使用其他的工具 来给 vm 发送 attach 命令, 来获取相关的数据, 比如 我们这里使用 jstack $pid 来进行测试
Attach Listener
我们来看一下 Attach Listener 的初始化, 以及它 主要做的事情
这里创建了 java.lang.Thread 对象, 并添加到了 系统线程组 里面, 然后下面 还设置了 本地线程, 优先级, 守护线程 的相关配置
创建了一个 本地线程(C层面), 并将它们互相建立关系, 并启动线程
Attach Listener 的启动方式有多种, 一种就是 vm 启动的时候创建, 另外一种就是 我上图这种 由 Signal Dispatcher 触发 Attach Listener 在需要的时候初始化
Attach Listener 做的事情
可以看到 就是不断等待 消息过来, 然后进行处理
根据给定的 operation, 查询处理的 这个 operation 的函数, 调用这个函数, 将数据存放到 st 里面
然后 将结果(res, st) 返回给调用方
接下来我们来调试一个 实际的场景, 以 jstack 为例
jstack 发送请求
LinuxVirtualMachine 里面 execut 的代码如下(这里截取 LinuxVirtualMachine的代码, 是因为 我本地没得 BstVirtualMachine的代码, 并且这两者的 execute 方法基本上都是一样的)
上下文信息如下
以 "/var/folders/pw/lb8dvl7d6474r5plrnwtcp180000gn/T/.java_pid3247" 作为媒介进行交互
输入了 PROTOCOL_VERSION["1"], 命令[threaddump], 以及参数[这里没有传递了 三个空格]
vm 接受请求
vm 这边接收到请求, 然后 查询对应的 handler 进行处理
各个操作 以及对应的 处理函数如下
solaris 上面有一些 平台特有的操作
thread_dump 的相关处理逻辑如下, 输出对战信息, JNI信息, 死锁信息, 输出到 out 里面(也就是上面的 st)
处理完业务之后, 将 结果码 + 结果内容 返回给客户端
jstack 接收结果
测试用例中输出 堆栈信息如下
Connected to the target VM, address: '127.0.0.1:55793', transport: 'socket'
2020-05-05 19:26:58
Full thread dump OpenJDK 64-Bit Server VM (9-internal+0-adhoc.jerry.jdk9 mixed mode):
"Attach Listener" #12 daemon prio=9 os_prio=31 tid=0x00007fdb7f04c800 nid=0x3c03 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
JavaThread state: _thread_blocked
Thread: 0x00007fdb7f04c800 [0x3c03] State: _at_safepoint _has_called_back 0 _at_poll_safepoint 0
JavaThread state: _thread_blocked
"Service Thread" #11 daemon prio=9 os_prio=31 tid=0x00007fdb7f04b800 nid=0x3903 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
JavaThread state: _thread_blocked
Thread: 0x00007fdb7f04b800 [0x3903] State: _at_safepoint _has_called_back 0 _at_poll_safepoint 0
JavaThread state: _thread_blocked
"Common-Cleaner" #10 daemon prio=8 os_prio=31 tid=0x00007fdb7d872000 nid=0x4803 in Object.wait() [0x00007000080ae000]
java.lang.Thread.State: TIMED_WAITING (on object monitor)
JavaThread state: _thread_blocked
Thread: 0x00007fdb7d872000 [0x4803] State: _at_safepoint _has_called_back 0 _at_poll_safepoint 0
JavaThread state: _thread_blocked
at java.lang.Object.wait(java.base/Native Method)
- waiting on <0x00000007bf91b508> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(java.base/ReferenceQueue.java:151)
- waiting to re-lock in wait() <0x00000007bf91b508> (a java.lang.ref.ReferenceQueue$Lock)
at jdk.internal.ref.CleanerImpl.run(java.base/CleanerImpl.java:148)
at java.lang.Thread.run(java.base/Thread.java:844)
at jdk.internal.misc.InnocuousThread.run(java.base/InnocuousThread.java:122)
"Sweeper thread" #9 daemon prio=9 os_prio=31 tid=0x00007fdb7d868000 nid=0x3703 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
JavaThread state: _thread_blocked
Thread: 0x00007fdb7d868000 [0x3703] State: _at_safepoint _has_called_back 0 _at_poll_safepoint 0
JavaThread state: _thread_blocked
"C1 CompilerThread3" #8 daemon prio=9 os_prio=31 tid=0x00007fdb80000800 nid=0x4a03 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
JavaThread state: _thread_blocked
Thread: 0x00007fdb80000800 [0x4a03] State: _at_safepoint _has_called_back 0 _at_poll_safepoint 0
JavaThread state: _thread_blocked
No compile task
"C2 CompilerThread2" #7 daemon prio=9 os_prio=31 tid=0x00007fdb7d866800 nid=0x3503 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
JavaThread state: _thread_blocked
Thread: 0x00007fdb7d866800 [0x3503] State: _at_safepoint _has_called_back 0 _at_poll_safepoint 0
JavaThread state: _thread_blocked
No compile task
"C2 CompilerThread1" #6 daemon prio=9 os_prio=31 tid=0x00007fdb7d865000 nid=0x4b03 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
JavaThread state: _thread_blocked
Thread: 0x00007fdb7d865000 [0x4b03] State: _at_safepoint _has_called_back 0 _at_poll_safepoint 0
JavaThread state: _thread_blocked
No compile task
"C2 CompilerThread0" #5 daemon prio=9 os_prio=31 tid=0x00007fdb7f80a000 nid=0xf07 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
JavaThread state: _thread_blocked
Thread: 0x00007fdb7f80a000 [0xf07] State: _at_safepoint _has_called_back 0 _at_poll_safepoint 0
JavaThread state: _thread_blocked
No compile task
"Signal Dispatcher" #4 daemon prio=9 os_prio=31 tid=0x00007fdb7d853000 nid=0x3303 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
JavaThread state: _thread_blocked
Thread: 0x00007fdb7d853000 [0x3303] State: _at_safepoint _has_called_back 0 _at_poll_safepoint 0
JavaThread state: _thread_blocked
"Finalizer" #3 daemon prio=8 os_prio=31 tid=0x00007fdb7d84e000 nid=0x5203 in Object.wait() [0x0000700007999000]
java.lang.Thread.State: WAITING (on object monitor)
JavaThread state: _thread_blocked
Thread: 0x00007fdb7d84e000 [0x5203] State: _at_safepoint _has_called_back 0 _at_poll_safepoint 0
JavaThread state: _thread_blocked
at java.lang.Object.wait(java.base/Native Method)
- waiting on <0x00000007bf91c070> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(java.base/ReferenceQueue.java:151)
- waiting to re-lock in wait() <0x00000007bf91c070> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(java.base/ReferenceQueue.java:172)
at java.lang.ref.Finalizer$FinalizerThread.run(java.base/Finalizer.java:216)
"Reference Handler" #2 daemon prio=10 os_prio=31 tid=0x00007fdb7d844800 nid=0x2c03 waiting on condition [0x0000700007896000]
java.lang.Thread.State: RUNNABLE
JavaThread state: _thread_blocked
Thread: 0x00007fdb7d844800 [0x2c03] State: _at_safepoint _has_called_back 0 _at_poll_safepoint 0
JavaThread state: _thread_blocked
at java.lang.ref.Reference.waitForReferencePendingList(java.base/Native Method)
at java.lang.ref.Reference.processPendingReferences(java.base/Reference.java:174)
at java.lang.ref.Reference.access$000(java.base/Reference.java:44)
at java.lang.ref.Reference$ReferenceHandler.run(java.base/Reference.java:138)
"main" #1 prio=5 os_prio=31 tid=0x00007fdb7f009800 nid=0x2703 runnable [0x0000700007690000]
java.lang.Thread.State: RUNNABLE
JavaThread state: _thread_in_native
Thread: 0x00007fdb7f009800 [0x2703] State: _at_safepoint _has_called_back 0 _at_poll_safepoint 0
JavaThread state: _thread_in_native
at java.io.FileInputStream.readBytes(java.base/Native Method)
at java.io.FileInputStream.read(java.base/FileInputStream.java:256)
at java.io.BufferedInputStream.fill(java.base/BufferedInputStream.java:246)
at java.io.BufferedInputStream.read(java.base/BufferedInputStream.java:265)
- locked <0x00000007bf92b058> (a java.io.BufferedInputStream)
at com.hx.test05.Test25AttachListener.main(Test25AttachListener.java:16)
"VM Thread" os_prio=31 tid=0x00007fdb7f02e800 nid=0x5403 runnable
"VM Periodic Task Thread" os_prio=31 tid=0x00007fdb81001000 nid=0x3b03 waiting on condition
JNI global references: 181
Disconnected from the target VM, address: '127.0.0.1:55793', transport: 'socket'
Process finished with exit code 0
Attach Listener 和 Signal Dispatcher 的一些对比
1. 数据的交互方式
前者通过 Socket 进行通信, 后者通过 信号机制 进行通信
前者可以传递 一个标记, 一定的参数, 后者只有一个 标记
2. 业务的执行
前者在 vm 内部执行, 后者在 java 层面上执行
3. 业务的限定
前者只有固定的 N 中业务可以处理, 后者是可以 自定义业务处理
完