Java-Launcher类上打断点无效的案例解读

Java-Launcher类上打断点无效的案例解读

这是一个有意思的案例~
?首先,以下是一个广为流传的说法:
?内建于 JVM 中的启动类加载器(Bootstrap Class Loader)会加载 java.lang.ClassLoder 以及其他 Java 平台类,Launcher 类由此被启动类加载器加载和初始化,因为 Launcer 的静态代码会产生一个 Luancher 实例,继而又会产生了一对 Extension Class Loader 和 Application Class Loader 实例。
?其中,“从加载乃至初始化 Launcher 类,会有创建一个 Launcher 实例,那么又便会创建 Extension Class Loader 和 Application Class Loader 实例”这个观点从 sun.misc.Launcher 类的源码很容易得到验证。问题是如何证明启动类加载器会主动加载以及导致 Launcher 类的初始化呢?很容易想到,在 Launcher 的构造器内部打一个断点不就完事了。
?一般地,debug 的确是解决这类问题的好方法,但是偏偏这个案例中你在 Launcher 的构造器内部打上的断点会被跳过。
?于是,为了验证断点的有效性,在程序中主动调用了 Launcher 类的构造器,如下:
Launcher launcher = new Launcher();

?在断点不变的情况下,debug 模式下成功暂停了。
?这难道证明了广为流传的说法是错误的?
?于是我去翻看了 OpenJDK 对于 Launcher 类的描述:This class is used by the system to launch the main application.
?system 讲道理就是 JVM 的意思,所以广为流传的说法是对的,那么问题会不会是 debug 机制的问题?
?于是我又翻了翻 IBM 关于 Java 中 Debug 实现原理的介绍,文章地址如下:
【Java-Launcher类上打断点无效的案例解读】?https://www.ibm.com/developerworks/cn/java/j-lo-jpda1/
?文章中说到:JDI(Java Debug Interface)是三个模块中最高层的接口,在多数的 JDK 中,它是由 Java 语言实现的。
?参考 Oracle 的官方文档:https://docs.oracle.com/javase/9/docs/api/jdk.jdi-summary.html
?可以知道 jdi 是一个位于 tools.jar 包下的子包,而 tools.jar 也是由 BootStrap 类加载器负责加载的。
?所以现在我们可以知道了,为 Java 提供 Debug 支持的类加载和 Launcher 的类加载都是由 Bootstrap 类加载器负责的,只是后者先发生,所以 debug 功能实现的时候,Launcher 的构造器早已运行结束了。

    推荐阅读