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

2020-02-25 15:15:56 浏览数 (1)

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 类的构造器,如下:

代码语言:javascript复制
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 实现原理的介绍,文章地址如下:

 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 的构造器早已运行结束了。

0 人点赞