java debug体系为何不能debug到jdk里全部的代码

做为java码农确定碰到过当咱们debug到一些class的时候,发现当进入到某个方法里是看不到声明的入参名,取而代之的是arg0,arg1等,继续深刻更是看不到局部变量,这主要是java类编译的时候没有加-g参数致使的,而为何咱们本身在eclipse中写的代码倒是能够正常跟踪呢,缘由很简单,由于eclipse自行编译的时候是带-g参数编译的。java

 

       这种问题在咱们安装的jdk中更为常见,为了节省生成的jar空间,因而javac编译都是不带-g参数的,好比rt.jar,里面的类都是不能被正常debug的,由于生成的class信息中没有辅助debug的信息,好比行号,局部变量信息等,那是否是咱们经过手动编译jdk便可彻底debug jdk中的任意java类呢,答案是否认的。linux

 

       说到debug,那就要先了解下jdpa体系,jdpa包含三部分,从低到高是jvmti->jdwp->jdi,jvmti是一套本地代码接口,jvm暴露出来的扩展接口,全部的调试功能都是经过其提供出来的,不少jvm性能工具都是基于这些接口来实现的;jdwp是java调试线协议,其主要规范了jvmti和jdi之间的通讯协议,好比命令的格式是什么,回复的格式是什么等,固然还包括不少类型的定义,理论上其不包括通讯层的实现,通讯层的实现能够是socket,也能够是共享内存等;jdi位于最上层,定义了调试器所须要的调试接口,基于这些接口调试器能够方便地了解目标虚拟机的状态信息,你们最熟悉的有eclipse IDE。eclipse

    

       那java debug的原理是什么呢,说简单点主要是经过实现jdwp的动态连接库,利用agentlib的机制(其实就是jvmti的扩展机制)在启动或者运行器动态执行动态连接库,-agentlib:jdwp=transport=dt_socket,suspend=y,address=localhost:58140 ,相似如上的启动配置,jdwp是动态连接库的名称,会根据所在的平台自动查找对应的动态库,好比linux下会找到jdwp.so,mac下会找到jdwp.dylib等,至于这个agent怎么实现的就很少说了。jvm

 

       那回过来讲说为何说不能debug到rt.jar中的每行代码呢,该agent往jvmti环境中注册了一个回调方法,回调方法里干了啥呢,好比建立serversocket来等待链接,这主要在咱们设置了调试端口,而且suspend=y的状况,该回调方法是在vm初始化完毕以后才去执行的,而在vm初始化的过程当中经过启动类加载器已经加载了不少类了,执行了很多java逻辑,因此这些逻辑是根本跟踪不到的,好比sun.misc.Launcher的建立等。socket

相关文章
相关标签/搜索