`
小滔哥
  • 浏览: 58112 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类

jmap/jstack/jstat等等从何而来

 
阅读更多

一、引言

    我们会发现$JAVA_HOME/bin/目录下的java,jmap,jstack,jstat,jinfo等等都是二进制的文件,而我们又很容易发现,java是与一个源文件java.c对应的,却看不到jmap,jstack,jstat等对应的源文件,那么这些工具又是怎么生成的呢,下面介绍下我是如何发现这些工具是怎样生成的,以jmap为例。

二、以jmap为例,介绍这些工具如何生成的。

    首先想到的是,build整个openjdk,然后根据build信息查找jmap是如何生成的。

    build openjdk ,这里有个详细的参考,rednaxelafx大神的作品。按照整个build过程,build出来openjdk,然后保存了build过程中的build信息,在这个build信息中搜索了下jmap,找到了下面信息。

build jmap 写道
cd ../launchers && make -f Makefile.launcher PROGRAM=jmap MAIN_CLASS=sun.tools.jmap.JMap MAIN_JAVA_ARGS="-J-Dsun.jvm.hotspot.debugger.useProcDebugger -J-Dsun.jvm.hotspot.debugger.useWindbgDebugger" MAIN_ARGS=""
make[5]: Entering directory `/home/chengtao/Downloads/openjdk7/openjdk/jdk/make/launchers'
=========================================================
LAUNCHER: jmap
MAIN_CLASS: sun.tools.jmap.JMap
MAIN_JAVA_ARGS: -J-Dsun.jvm.hotspot.debugger.useProcDebugger -J-Dsun.jvm.hotspot.debugger.useWindbgDebugger
ALL_ARGS: -J-ms8m -J-Dsun.jvm.hotspot.debugger.useProcDebugger -J-Dsun.jvm.hotspot.debugger.useWindbgDebugger sun.tools.jmap.JMap
 

  从这里面,我们可以看到,jmap或许是在这里生成的,但是我们有看不到gcc的编译信息,不知道是如何生成的,因此我进到了`/home/chengtao/Downloads/openjdk7/openjdk/jdk/make/launchers这个目录,执行了下上面的命令

make 写道
chengtao@ubuntu:~/Downloads/openjdk7/openjdk/jdk/make/launchers$ make -f Makefile.launcher PROGRAM=jmap MAIN_CLASS=sun.tools.jmap.JMap MAIN_JAVA_ARGS="-J-Dsun.jvm.hotspot.debugger.useProcDebugger -J-Dsun.jvm.hotspot.debugger.useWindbgDebugger" MAIN_ARGS=""

 输出了下面信息

 

make output 写道
=========================================================
LAUNCHER: jmap
MAIN_CLASS: sun.tools.jmap.JMap
MAIN_JAVA_ARGS: -J-Dsun.jvm.hotspot.debugger.useProcDebugger -J-Dsun.jvm.hotspot.debugger.useWindbgDebugger
ALL_ARGS: -J-ms8m -J-Dsun.jvm.hotspot.debugger.useProcDebugger -J-Dsun.jvm.hotspot.debugger.useWindbgDebugger sun.tools.jmap.JMap
=========================================================
/usr/bin/gcc -g -fno-strict-aliasing -fPIC -W -Wall -Wno-unused -Wno-parentheses -pipe -fno-omit-frame-pointer -D_LITTLE_ENDIAN -DNDEBUG -DARCH='"amd64"' -Damd64 -DLINUX -DRELEASE='"1.7.0-internal"' -DFULL_VERSION='"1.7.0-internal-chengtao_2012_11_20_22_47-b00"' -DJDK_MAJOR_VERSION='"1"' -DJDK_MINOR_VERSION='"7"' -D_LARGEFILE64_SOURCE -D_GNU_SOURCE -D_REENTRANT -D_LP64=1 -I. -I../../build/linux-amd64/tmp/sun/launcher/jmap/CClassHeaders -I../../src/solaris/javavm/export -I../../src/share/javavm/export -I../../src/share/bin -I../../src/solaris/bin -I../../src/share/native/java/util/zip/zlib-1.1.3 -DAPP_CLASSPATH='{ "/lib/tools.jar", "/lib/sa-jdi.jar", "/classes" }' -DMAIN_CLASS='"sun.tools.jmap.JMap"' -DJAVA_ARGS='{ "-J-ms8m", "-J-Dsun.jvm.hotspot.debugger.useProcDebugger", "-J-Dsun.jvm.hotspot.debugger.useWindbgDebugger", "sun.tools.jmap.JMap", }' -DLAUNCHER_NAME='"openjdk"' -DPROGNAME='"jmap"' -c -o ../../build/linux-amd64/tmp/sun/launcher/jmap/obj64/main.o \
-DRELEASE='"1.7.0-internal"' -DFULL_VERSION='"1.7.0-internal-chengtao_2012_11_20_22_47-b00"' -DJDK_MAJOR_VERSION='"1"' -DJDK_MINOR_VERSION='"7"' ../../src/share/bin/main.c
Rebuilding ../../build/linux-amd64/bin/jmap because of ../../build/linux-amd64/tmp/sun/launcher/jmap/obj64/main.o
/usr/bin/gcc -o ../../build/linux-amd64/bin/jmap -Xlinker -g -Xlinker -version-script=../java/main/java/mapfile-amd64 -Wl,--hash-style=both -Xlinker -z -Xlinker defs -L../../build/linux-amd64/lib/amd64 -Wl,-soname=lib.so -L ../../build/linux-amd64/lib/amd64/jli -Wl,--allow-shlib-undefined -Wl,-rpath -Wl,\$ORIGIN/../lib/amd64/jli -Wl,-rpath -Wl,\$ORIGIN/../jre/lib/amd64/jli \
../../build/linux-amd64/tmp/sun/launcher/jmap/obj64/main.o -lpthread -ljli -ldl -lc
/usr/bin/ld: cannot find -ljli

  从这里我们就很容易发现了,jmap是通过编译../../src/share/bin/main.c文件生成的,接下来,我们就来分析下这个文件。

 

    return JLI_Launch(margc, margv,
                   sizeof(const_jargs) / sizeof(char *), const_jargs,
                   sizeof(const_appclasspath) / sizeof(char *), const_appclasspath,
                   FULL_VERSION,
                   DOT_VERSION,

 这个文件里,只出现了这么一个语句, JLI_Launch这个函数则来自于java.c中定义,后面就跟java.c的逻辑是一样的了。至此,我们就清楚了jmap是如何来的。

 

三、jstack,jstat,jinfo等等的生成

    通过jmap的分析,我们不难知道这几个工具是如何来的了。这些工具的生成,依赖两个makefile,openjdk/jdk/make/launchers这个目录下的Makefile和Makefile.launch,在Makefile.launch文件中为各种工具定义了相应的变量值,而当gcc编译的时候,传递过去。在 ../../src/share/bin/main.c中依赖了,defines.h

#ifndef APP_CLASSPATH
#define APP_CLASSPATH        { "/lib/tools.jar", "/classes" }
#endif /* APP_CLASSPATH */
static const char* const_appclasspath[] = APP_CLASSPATH;
#else  /* !JAVA_ARGS */
#ifdef PROGNAME
static const char* const_progname = PROGNAME;
#else
static char* const_progname = NULL;
#endif

  到这里,我们就清楚了所有工具是如何生成的了,makefile中的变量值与生成的工具是一一对应的,例如生成jstack,传递jstack需要的PROGNAME,APP_CLASSPATH变量就可以了。这里的技巧就是只需要一个main.c,通过makefile中的变量,控制main.c中需要的变量的值,就可以生成多个工具了。

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics