Java java.lang.ref.Finalizer 上设置的断点未停止
Java Breakpoint set on java.lang.ref.Finalizer not stopped
我想深入了解 Java java.lang.ref.Finalizer
初始化过程,所以我在其 class 静态块上设置了一个断点:
static {
-> ThreadGroup tg = Thread.currentThread().getThreadGroup(); // breakpoint set on this line
for (ThreadGroup tgn = tg;
tgn != null;
tg = tgn, tgn = tg.getParent());
Thread finalizer = new FinalizerThread(tg);
finalizer.setPriority(Thread.MAX_PRIORITY - 2);
finalizer.setDaemon(true);
finalizer.start();
}
然后通过 IntelliJ IDEA 调试按钮启动一个空的 main()
方法,但断点不会停止程序(JVM 只是执行到它的末尾并退出。)
Java版本:
openjdk version "1.8.0_302"
OpenJDK Runtime Environment Corretto-8.302.08.1 (build 1.8.0_302-b08)
OpenJDK 64-Bit Server VM Corretto-8.302.08.1 (build 25.302-b08, mixed mode)
为什么这个断点没有生效?
从JDK5.0开始,JVM调试能力基于JVM TI构建,取代了JVMPI和JVMDI。我不熟悉 JVMDI,因此以下陈述是基于您使用 agentlib:jdwp
调试代码的事实,例如:
-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005
jdwp 代理(从 libjdwp.so
文件加载)在接收到 post_vm_initialized
事件时绑定指定的端口(上例中的 5005)。正如事件名称所示,VM 已经初始化并且 Finalizer
class 已经在调试端口绑定发生时加载 (当然你只能调试 Java JDWP端口监听后的代码)。所以你不能调试Finalizer
的静态块代码。事实上,在JDWP端口绑定之前加载的classes在初始化方面都是不可调试的。但是如果线程运行在loaded-before class之后的代码中,你仍然可以调试它,例如Finalizer.FinalizerThread#run
方法。
我从 The JVM Tool Interface (JVM TI): How VM Agents Work 中找到了一句话:
The library is loaded before the VM has initialized, allowing the agent library to capture early VM events that it could not access before.
JDWP agentlib 另一方面可以在 Agent_Onload
函数中绑定端口(在 debugInit.c
中),这可能允许在 JVM 中加载所有 classes 的调试(我猜).
PS:如果您对上述代码感兴趣(在 OpenJDK 8 中,Mercurial ID dcb218f54ca1):
post_vm_initialized
函数中的事件处理 debugInit.c:initialize
.
- JDWP 的
Agent_Onload
函数也位于代码文件 debugInit.c
.
我想深入了解 Java java.lang.ref.Finalizer
初始化过程,所以我在其 class 静态块上设置了一个断点:
static {
-> ThreadGroup tg = Thread.currentThread().getThreadGroup(); // breakpoint set on this line
for (ThreadGroup tgn = tg;
tgn != null;
tg = tgn, tgn = tg.getParent());
Thread finalizer = new FinalizerThread(tg);
finalizer.setPriority(Thread.MAX_PRIORITY - 2);
finalizer.setDaemon(true);
finalizer.start();
}
然后通过 IntelliJ IDEA 调试按钮启动一个空的 main()
方法,但断点不会停止程序(JVM 只是执行到它的末尾并退出。)
Java版本:
openjdk version "1.8.0_302"
OpenJDK Runtime Environment Corretto-8.302.08.1 (build 1.8.0_302-b08)
OpenJDK 64-Bit Server VM Corretto-8.302.08.1 (build 25.302-b08, mixed mode)
为什么这个断点没有生效?
从JDK5.0开始,JVM调试能力基于JVM TI构建,取代了JVMPI和JVMDI。我不熟悉 JVMDI,因此以下陈述是基于您使用 agentlib:jdwp
调试代码的事实,例如:
-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005
jdwp 代理(从 libjdwp.so
文件加载)在接收到 post_vm_initialized
事件时绑定指定的端口(上例中的 5005)。正如事件名称所示,VM 已经初始化并且 Finalizer
class 已经在调试端口绑定发生时加载 (当然你只能调试 Java JDWP端口监听后的代码)。所以你不能调试Finalizer
的静态块代码。事实上,在JDWP端口绑定之前加载的classes在初始化方面都是不可调试的。但是如果线程运行在loaded-before class之后的代码中,你仍然可以调试它,例如Finalizer.FinalizerThread#run
方法。
我从 The JVM Tool Interface (JVM TI): How VM Agents Work 中找到了一句话:
The library is loaded before the VM has initialized, allowing the agent library to capture early VM events that it could not access before.
JDWP agentlib 另一方面可以在 Agent_Onload
函数中绑定端口(在 debugInit.c
中),这可能允许在 JVM 中加载所有 classes 的调试(我猜).
PS:如果您对上述代码感兴趣(在 OpenJDK 8 中,Mercurial ID dcb218f54ca1):
post_vm_initialized
函数中的事件处理debugInit.c:initialize
.- JDWP 的
Agent_Onload
函数也位于代码文件debugInit.c
.