关于makefile,请参考《gcc&makefile基础》
目录说明
openjdk源码中有很多目录,根据功能做了模块化划分,每个目录实现其相应的功能。
每个目录下的结构都差不多,分为src(源码)、make(makefile)、test(或没有)、其他特殊目录。
openjdk
│ common 一些公共文件,比如下载源码的shell脚本、生成make的autoconf等文件
│ corba 分布式通讯接口
└───hotspot 虚拟机实现
│ │ make makefile
│ │ test 单元测试文件
│ │ Agent 主要实现SA
│ └───src 源码目录
│ │ Cpu 处理器的代码,主要按照Sparc、x86和Zero三种计算机体系结构
│ │ Os 操作系统的代码,主要按照Linux、Windows、Solaris和Posix2
│ │ Os_cpu 同时依赖于操作系统和处理器的代码,如Linux+Sparc、Linux+x86、Linux+Zero...等模块。
│ └───Share 独立于操作系统和处理器类型的代码,这部分代码是HotSpot工程的核心业务,实现了HotSpot的主要功能
│ │ │ │ Tools 独立的虚拟机工具程序,如Hsdis...
│ │ │ └───vm 实现虚拟机各项功能
│ │ │ │ │ Adlc:平台描述文件。
│ │ │ │ │ Libadt:抽象数据结构。
│ │ │ │ │ Asm:汇编器。
│ │ │ │ │ Code:机器码生成。
│ │ │ │ │ C1:client编译器,即C1编译器。
│ │ │ │ │ Ci:动态编译器。
│ │ │ │ │ Compiler:调用动态编译器的接口。
│ │ │ │ │ Opto:Server编译器,即C2编译器。
│ │ │ │ │ Shark:基于LLVM实现的即时编译器。
│ │ │ │ │ Interpreter:解释器。
│ │ │ │ │ Classfile:Class文件解析和类的链接等。
│ │ │ │ │ Gc_interface:GC接口。
│ │ │ │ │ Gc_implementation:垃圾收集器的具体实现。
│ │ │ │ │ Memory:内存管理。
│ │ │ │ │ Oops:JVM内部对象表示。
│ │ │ │ │ Prims:HotSpot对外接口。
│ │ │ │ │ Runtime:运行时。
│ │ │ │ │ Services:JMX接口。
│ │ │ │ │ Utilizes:内部工具类和公共函数。
│ jaxp xml处理代码
│ jaxws ws实现api
│ jaxp xml处理代码
└───jdk源码
│ │ make makefile
│ │ test 单元测试文件
│ └───src 源码目录
│ │ bsd bsd实现
│ │ linux linux实现
│ │ macosx macos实现
│ │ share 公用代码
│ │ solaris solaris实现
│ │ windows window实现
└───langtools java语言工具实现,比如java, javac, javah, javap等
│ │ make makefile
│ │ test 单元测试文件
│ └───src 源码目录
│ │ └───share java源代码
│ │ │ │ bin 模板
│ │ │ │ sample 样例源码
│ │ │ └───classes java源码文件
│ │ │ │ │ com 存放了java提供的一些基础类实现,打包成tools.jar
│ │ │ │ │ javax
│ │ │ │ │ jdk
│ make make文件
│ nashorn java中js的运行时实现
│ test 测试文件
目标生成
java中提供的bin目录下的java、javac、javap等都不是完全通过c/c++编写实现的,是通过c/c++入口,启动虚拟机加载class文件实现的相关功能。
所有java提供的工具程序(bin目录下的可执行程序)入口都是jdk/src/bin/share/bin/main.c。
它们通过makeFile与jdk/src/share/bin/defines.h中的宏开关,来改变java的运行轨迹。
文件名为:/openjdk/jdk/make/CompileLaunchers.gmk
$(eval $(call SetupLauncher,javadoc, \
-DEXPAND_CLASSPATH_WILDCARDS \
-DNEVER_ACT_AS_SERVER_CLASS_MACHINE \
-DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "com.sun.tools.javadoc.Main"$(COMMA) }'))
$(eval $(call SetupLauncher,javah, \
-DEXPAND_CLASSPATH_WILDCARDS \
-DNEVER_ACT_AS_SERVER_CLASS_MACHINE \
-DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "com.sun.tools.javah.Main"$(COMMA) }'))
$(eval $(call SetupLauncher,javap, \
-DEXPAND_CLASSPATH_WILDCARDS \
-DNEVER_ACT_AS_SERVER_CLASS_MACHINE \
-DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "com.sun.tools.javap.Main"$(COMMA) }'))
BUILD_LAUNCHER_jconsole_CFLAGS_windows := -DJAVAW
BUILD_LAUNCHER_jconsole_LDFLAGS_windows := user32.lib
$(eval $(call SetupLauncher,jconsole, \
-DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "-J-Djconsole.showOutputViewer"$(COMMA) "sun.tools.jconsole.JConsole"$(COMMA) }' \
-DAPP_CLASSPATH='{ "/lib/jconsole.jar"$(COMMA) "/lib/tools.jar"$(COMMA) "/classes" }'))
$(eval $(call SetupLauncher,jdb, \
-DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "com.sun.tools.example.debug.tty.TTY"$(COMMA) }' \
-DAPP_CLASSPATH='{ "/lib/tools.jar"$(COMMA) "/lib/sa-jdi.jar"$(COMMA) "/classes" }'))
$(eval $(call SetupLauncher,jhat, \
-DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "com.sun.tools.hat.Main"$(COMMA) }'))
$(eval $(call SetupLauncher,jinfo, \
-DJAVA_ARGS='{ "-J-ms8m"$(COMMA) \
"-J-Dsun.jvm.hotspot.debugger.useProcDebugger"$(COMMA) \
"-J-Dsun.jvm.hotspot.debugger.useWindbgDebugger"$(COMMA) \
"sun.tools.jinfo.JInfo"$(COMMA) }' \
-DAPP_CLASSPATH='{ "/lib/tools.jar"$(COMMA) "/lib/sa-jdi.jar"$(COMMA) "/classes" }' \
,,,,,,,,,Info-privileged.plist))
$(eval $(call SetupLauncher,jmap, \
-DJAVA_ARGS='{ "-J-ms8m"$(COMMA) \
"-J-Dsun.jvm.hotspot.debugger.useProcDebugger"$(COMMA) \
"-J-Dsun.jvm.hotspot.debugger.useWindbgDebugger"$(COMMA) \
"sun.tools.jmap.JMap"$(COMMA) }' \
-DAPP_CLASSPATH='{ "/lib/tools.jar"$(COMMA) "/lib/sa-jdi.jar"$(COMMA) "/classes" }' \
,,,,,,,,,Info-privileged.plist))
$(eval $(call SetupLauncher,jps, \
-DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "sun.tools.jps.Jps"$(COMMA) }'))
在makeFile文件可以看到各种熟悉的命令jps,jmap,javap等命令,但它们参数不同。
文件名为:jdk/src/share/bin/defines.h
ifdef JAVA_ARGS
static const char* const_progname = "java";
static const char* const_jargs[] = JAVA_ARGS;
/*
* ApplicationHome is prepended to each of these entries; the resulting
* strings are concatenated (separated by PATH_SEPARATOR) and used as the
* value of -cp option to the launcher.
*/
#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
static const char** const_jargs = NULL;
static const char** const_appclasspath = NULL;
#endif /* JAVA_ARGS */
#ifdef LAUNCHER_NAME
static const char* const_launcher = LAUNCHER_NAME;
#else /* LAUNCHER_NAME */
static char* const_launcher = NULL;
#endif /* LAUNCHER_NAME */
#ifdef EXPAND_CLASSPATH_WILDCARDS
static const jboolean const_cpwildcard = JNI_TRUE;
#else
static const jboolean const_cpwildcard = JNI_FALSE;
#endif /* EXPAND_CLASSPATH_WILDCARDS */
#if defined(NEVER_ACT_AS_SERVER_CLASS_MACHINE)
static const jint const_ergo_class = NEVER_SERVER_CLASS;
#elif defined(ALWAYS_ACT_AS_SERVER_CLASS_MACHINE)
static const jint const_ergo_class = ALWAYS_SERVER_CLASS;
#else
static const jint const_ergo_class = DEFAULT_POLICY;
#endif /* NEVER_ACT_AS_SERVER_CLASS_MACHINE */
#endif /*_DEFINES_H */
如果定义了JAVA_ARGS宏,则会把jvm的参数从宏定义中获取
此处参照/CompileLaunchers.gmk文件在声明javac的地方,定义了该宏内容
-DJAVA_ARGS=’{ “-J-ms8m” ( C O M M A ) " c o m . s u n . t o o l s . j a v a c . M a i n " (COMMA) "com.sun.tools.javac.Main" (COMMA)"com.sun.tools.javac.Main"(COMMA) }’)),
所以生成的elf文件javac中会得到该值为{ “-J-ms8m” ( C O M M A ) " c o m . s u n . t o o l s . j a v a c . M a i n " (COMMA) "com.sun.tools.javac.Main" (COMMA)"com.sun.tools.javac.Main"(COMMA) }
通过c/c++的main函数入口,创建jvm虚拟机后,通过执行相关功能的java代码实现其功能,所以java相关的功能如编译、运行、查看jvm信息等功能都是通过启动一个jvm虚拟机或者通过jvmti等实现的。