我想了解一下Java java.lang.ref.Finalizer初始化过程,因此我在它的类静态块上设置了一个断点:
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();
}然后通过main() IDEA调试按钮启动一个空的IntelliJ方法,但是断点永远不会停止程序(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)为什么这个断点不起作用?
发布于 2021-09-28 15:50:59
从JDK5.0开始,JVM调试功能就建立在JVM TI的基础上,取代了JVMPI和JVMDI。我不太熟悉JVMDI,因此下面的语句是基于使用agentlib:jdwp调试代码的事实,例如:
-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005jdwp代理(从libjdwp.so文件加载)在接收post_vm_initialized事件时绑定指定的端口(在上面的示例中为5005)。如事件名称所示,当调试端口绑定发生Finalizer时,VM已经初始化,类已经加载(当然,只有在JDWP端口侦听之后才能调试代码)。因此,您不能调试Finalizer的静态块代码。实际上,在JDWP端口绑定之前加载的类在初始化方面都是不可调试的。但是,如果线程在加载之前类的代码中运行,那么您仍然能够调试它,例如Finalizer.FinalizerThread#run方法。
我找到了JVM工具接口(JVM TI):VM代理是如何工作的的引文
该库是在VM初始化之前加载的,允许代理库捕获它以前无法访问的早期VM事件。
JDWP代理库可以将端口绑定到Agent_Onload函数中(在debugInit.c中),这可能允许对JVM中加载的所有类进行调试(我猜)。
PS:如果您对上面提到的代码感兴趣(在带有Mercurial ID的OpenJDK 8中,dcb218f54ca1):
post_vm_initialized事件处理函数debugInit.c:initialize。Agent_Onload函数也位于代码文件debugInit.c中。https://stackoverflow.com/questions/69240657
复制相似问题