编绎调试HotSpot JVM及在Eclipse里调试HotSpot一些步骤

编绎整个OpenJDK要很久,而且有很多东西是不需要的。研究HotSpot的话,其实只要下HotSpot部分的代码就可以了。

下面简单记录下编绎调试HotSpot一些步骤。

一、编绎

进入hotsopt的make目录下:


1

cd code/cpp/openjdk/hotspot/make/

用make help可以看到有很多有用的信息。当然查看Makefile文件,里面也有很多有用的注释。

make help会输出当前的一些环境变量的设置,如果不对,自然编绎不过去。

设置环境变量:


1

2

3

4

5

unset JAVA_HOME

export ARCH_DATA_MODEL=64

export JDK_IMPORT_PATH=/usr/lib/jvm/java-7-oracle

export ALT_BOOTDIR=/usr/lib/jvm/java-7-oracle

export ZIP_DEBUGINFO_FILES=0                      //这个貌似不起作用。。这些变量的定义貌似都在def.make文件里。还有一个这样的参数:FULL_DEBUG_SYMBOLS

用make all_beug来编绎。

编绎后好,到目录下openjdk/hotspot/build/Linux/linux_amd64_compiler2/jvmg,执行 unzip libjvm.diz,解压得到调试信息文件

这个算是个坑,默认情况下,会压缩调试信息文件,这样用gdb调试时,就会出现下面的提示:


1

no debugging symbols found

从编绎的输出信息来看,是有一个ZIP_DEBUGINFO_FILES的参数,但是设置了环境变量却不起效。

二、调试

在 openjdk/hotspot/build/linux/linux_amd64_compiler2/jvmg 目录下,有一个hotspot的脚本,只要执行这个脚本,就可以启动Java进程了。

用 ./hotspot -gdb 就会自动进入gdb调试,并停在main函数入口。

后面还可以加一些jvm的启动参数等。

这个./hotsopt 脚本是怎么工作的?

用 sh -x ./hotspot 来查看这个脚本的执行过程,可以发现实际上是设置了 LD_LIBRARY_PATH的环境变量,再调用了一个./gamma 的程序。


1

2

3

4

5

6

7

8

9

10

+ LD_LIBRARY_PATH=/home/hengyunabc/code/cpp/openjdk/hotspot/build/linux/linux_amd64_compiler2/jvmg:/usr/lib/jvm/java-7-oracle/jre/lib/amd64

+ export LD_LIBRARY_PATH

+ JPARMS=

+ LAUNCHER=/home/hengyunabc/code/cpp/openjdk/hotspot/build/linux/linux_amd64_compiler2/jvmg/gamma

+ [ ! -x /home/hengyunabc/code/cpp/openjdk/hotspot/build/linux/linux_amd64_compiler2/jvmg/gamma ]

+ GDBSRCDIR=/home/hengyunabc/code/cpp/openjdk/hotspot/build/linux/linux_amd64_compiler2/jvmg

+ cd /home/hengyunabc/code/cpp/openjdk/hotspot/build/linux/linux_amd64_compiler2/jvmg/../../..

+ pwd

+ BASEDIR=/home/hengyunabc/code/cpp/openjdk/hotspot/build

+ LD_PRELOAD= exec /home/hengyunabc/code/cpp/openjdk/hotspot/build/linux/linux_amd64_compiler2/jvmg/gamma

实际上是通过设置LD_LIBRARY_PATH 环境变量,去优先加载编绎好的libjvm.so。hotsopt jvm的代码都编绎链接在libjvm.so这个文件里。

查看./hotspot里的这个函数init_gdb,就知道它是怎么启动并设置好gdb的了:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

init_gdb() {

# Create a gdb script in case we should run inside gdb

    GDBSCR=/tmp/hsl.$$

    rm -f $GDBSCR

    cat >>$GDBSCR <<EOF

cd `pwd`

handle SIGUSR1 nostop noprint

handle SIGUSR2 nostop noprint

set args $JPARMS

file $LAUNCHER

directory $GDBSRCDIR

# Get us to a point where we can set breakpoints in libjvm.so

break InitializeJVM

run

# Stop in InitializeJVM

delete 1

# We can now set breakpoints wherever we like

EOF

}

所以,其实也可以这样开始调试。


1

2

export LD_LIBRARY_PATH=/home/hengyunabc/code/cpp/openjdk/hotspot/build/linux/linux_amd64_compiler2/jvmg:/usr/lib/jvm/java-7-Oracle/jre/lib/amd64

gdb

在gdb里执行file ./gamma,然后就可以调试了。

三、使用Eclipse来调试

尽管gdb功能强大,命令丰富,但是在查看调试的变量时,十分的不方便。特别是hotsopt里,很多东西都是用指针来存放的,有时要跳转好几层才能查看到想要的信息。

下载Eclipse的CDT版,新视觉影院6080或者安装CDT的插件。

导入Eclipse工程:

“File”, “Import”, “C/C++”, “Existing Code as Makefile Project”:

先择Linux GCC:

然后,就可以把项目导到Eclipse里了。会有很多错误提示,但是不影响我们的调试。

在Eclipse里调试:

首先,要设置要调试的文件的路径:

设置LD_LIBRARY_PATH:

然后就可以调试了。还有一个地方比较重要:

想在运行时输入gdb指令,可以在console view,在右边的下拉里,可以发现有一个gbd的console,还有一个gdb trace的console。 

四、一些有用的东东

jvmg1目录下是O1优化下的,fastdebug目录下是O3优化的。

java 进程的main入口在:openjdk/hotspot/src/share/tools/launcher/java.c 文件里。

在gdb里,用info sharedlibrary 命令查看实际使用到的是哪些so文件。

用file命令来判断一个可执行文件,so是32位的还是64位的。

查看一个so文件是否包含调试信息,可以用readelf -S xxx.so 命令来查看是否有debug相关的段。这个方法不一定准确,因为调试信息有可能放在外部文件里。

时间: 2024-12-28 02:45:28

编绎调试HotSpot JVM及在Eclipse里调试HotSpot一些步骤的相关文章

windows Service 之调试过程(附加到进程里调试,而且启动时间不能超过30秒)

最近第一次用C#写了一个windows service ,其实实现的内容比较简单.就是启动remoting 连接,但是调试相对初次写windws service 的我来说,比较烦.没有经验,而且没办法像调试其他windows 程序一样设置断点,无法看到运行过程.经过查看一些相关资料后,有了一点点调试的心得.特此留笔,以待今后使用. 相关源码: static void Main()        {            ServiceBase[] ServicesToRun; // 同一进程中可

怎么在eclipse里调试WebDriver的源代码(转)

当你看完WebDriver的工作原理这篇博客以后,是不是也跃跃欲试想印证文章里的理论是不是正确,想自己也看下webdriver的源代码,并且调试下,通过代码来更深入的了解WebDriver的工作原理.ok,没有问题,咱们接下来就告诉大家怎么把源代码加载到eclipse里去.具体内容如下: 前提条件 你需要先在eclipse创建一个java project,具体步骤就不细说了,相信大家有点基础的应该都可以创建成功的.然后去selenium官网下载selenium client.具体下载位置请看下图

Tomcat6源代码在Eclipse里调试简要说明

简易步骤: 一.下载ant (1)解压到c:\ant (2) 设置环境变量 ANT_HOME=c:\ant 二.下载tomcat6源代码 官方网站下,或svn下到本地 三.eclipse (1)eclipse导入源代码 (2)到第二步,Properties-->Libraries,删除只剩下jre (3)准备lib目录 ant.jar                                  commons-collections-3.2.jar              commons

多模块maven项目使用Eclipse的 AspectJ编绎期织入

Aspectj是Eclipse基金会下的子项目,AspectJ提供了两种方式实现切面代码织入 编绎期织入:分为三种情况 编绎class文件时织入 编绎后织入 类加载时织入 运行时织入 本文是在使用编绎class文件织入实践介绍 aspectJ提供了两种切面的实现方式 基于.aj文件描述 基于java注解 以下介绍是基于java注解 在单模块项目中使用AspectJ的编绎期织入特性时,只需要在pom文件加入aspectj依赖和aspectj编绎插件即可: <properties> <asp

Eclipse远程调试Tomcat

最近,一直在研究Tomcat的工作内幕,主要的方法就是参考<How Tomcat Works> 这本书和Tomcat 5.5.26的源代码. Tomcat的代码结构还是比较清晰的,注释也比较全.但是代码毕竟是静态的,难以彻底弄清类与类之间的协作关系,以及运行时对象的交互关系. 如果能对Tomcat的启动.处理请求和停止的过程进行断点调试,看清Tomcat的每一步行踪,那么就能解决上面的问题了. 于是,又一个问题出来了:如何使用Eclipse远程调试Tomcat ? 上网查了一些资料,相关的文章

使用Eclipse远程调试及原理

今天定位Linux Server端的Java应用程序的问题,使用了 Eclipse 远程调试 Java 应用程序,这恐怕是定位Server端最常见也是最根本的方法,居然至少有两位有好几年开发经验的同事都不知道这个方法,我也感觉十分诧异. 本文在介绍使用Eclipse远程调试Java应用程序之外,着重解析了远程调试的原理. JVM原理 众所周知,Java由于引入了虚拟机JVM,拥有了很好的跨平台和安全性,.java文件由Javac编译成.class文件也叫字节码文件,字节码文件由JVM执行,并由翻

apktool + eclipse 动态调试APK

用了会AndBug,尽管挺强大的可是作为习惯了OD.EDB作为动态调试工具的人,自然有些不习惯,于是乎寻求新的动态调试解决方式.但大多数都是NetBeans + apktool.想着还得多下一个IDE就各种烦躁,还是去寻求Eclipse的组合吧. http://code.google.com/p/android-apktool/wiki/SmaliDebugging 找到apktool的官网,看到有能够实现动态调试. 能够在反编译和回编的时候通过设置參数给目标APK中的manifest文件里增加

Android动态方式破解apk前奏篇(Eclipse动态调试smail源码)

一.前言 今天我们开始apk破解的另外一种方式:动态代码调试破解,之前其实已经在一篇文章中说到如何破解apk了: Android中使用静态方式破解Apk  主要采用的是静态方式,步骤也很简单,首先使用apktool来反编译apk,得到smail源码,然后分析smail代码,采用代码注入技术来跟踪代码,然后找到关键方法进行修改,进而破解,同时还可以使用一些开源的hook框架,比如:Xposed和Cydia Substrate,来进行关键方法的hook.所以这里我们可以看到我们破解的第一步是使用ap

Eclipse远程调试应用程序

第一步,在应用程序的配置文件run.xml中加入下面的配置项,启动应用程序: <target name="run" depends="checkBuilderFailedLogExist">  <!--ant antfile="../DBSchema/main.xml" target="run-all" /-->   <java classname="com.raisecom.nms.c