關於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”(COMMA) }’)),
所以生成的elf文件javac中會得到該值爲{ “-J-ms8m”(COMMA) }
通過c/c++的main函數入口,創建jvm虛擬機後,通過執行相關功能的java代碼實現其功能,所以java相關的功能如編譯、運行、查看jvm信息等功能都是通過啓動一個jvm虛擬機或者通過jvmti等實現的。