原文链接:https://blog.csdn.net/p312011150/article/details/81513567
从学java至今已经有5年了,期间一直很好奇jdk实现但一直没有付出行动。今年发现自己的计算水平还很烂下定决心开始看jdk源码。
首先进入openjdk官网: http://openjdk.java.net/projects/jdk7u/
点击:
选择jdk7
先从src/share/bin/main.c 开始
这里进行判断是否是以javaw启动
#ifdef JAVAW
char **__initenv;
//调用windows窗口
int WINAPI
WinMain(HINSTANCE inst, HINSTANCE previnst, LPSTR cmdline, int cmdshow)
{
int margc;
char** margv;
const jboolean const_javaw = JNI_TRUE;
__initenv = _environ;
margc = __argc;
margv = __argv;
#else /* JAVAW */
int
main(int argc, char ** argv)
{
int margc;
char** margv;
const jboolean const_javaw = JNI_FALSE;
margc = argc;
margv = argv;
#endif /* JAVAW */
开始准备调用java虚拟机
return JLI_Launch(margc, margv,
sizeof(const_jargs) / sizeof(char *), const_jargs,
sizeof(const_appclasspath) / sizeof(char *), const_appclasspath,
FULL_VERSION,
DOT_VERSION,
(const_progname != NULL) ? const_progname : *margv,
(const_launcher != NULL) ? const_launcher : *margv,
(const_jargs != NULL) ? JNI_TRUE : JNI_FALSE,
const_cpwildcard, const_javaw, const_ergo_class);
}
接下来打开 src/share/bin/java.c
int
JLI_Launch(int argc, char ** argv, /* main argc, argc */
int jargc, const char** jargv, /* java args */
int appclassc, const char** appclassv, /* app classpath */
const char* fullversion, /* full version defined */
const char* dotversion, /* dot version defined */
const char* pname, /* program name */
const char* lname, /* launcher name */
jboolean javaargs, /* JAVA_ARGS */
jboolean cpwildcard, /* classpath wildcard*/
jboolean javaw, /* windows-only javaw */
jint ergo /* ergonomics class policy */
)
{
int mode = LM_UNKNOWN;
char *what = NULL;
char *cpath = 0;
char *main_class = NULL;
int ret;
InvocationFunctions ifn;
jlong start, end;
char jvmpath[MAXPATHLEN];
char jrepath[MAXPATHLEN];
_fVersion = fullversion;
_dVersion = dotversion;
_launcher_name = lname;
_program_name = pname;
_is_java_args = javaargs;
_wc_enabled = cpwildcard;
_ergo_policy = ergo;
InitLauncher(javaw);
DumpState();
/*
* Make sure the specified version of the JRE is running.
*
* There are three things to note about the SelectVersion() routine:
* 1) If the version running isn't correct, this routine doesn't
* return (either the correct version has been exec'd or an error
* was issued).
* 2) Argc and Argv in this scope are *not* altered by this routine.
* It is the responsibility of subsequent code to ignore the
* arguments handled by this routine.
* 3) As a side-effect, the variable "main_class" is guaranteed to
* be set (if it should ever be set). This isn't exactly the
* poster child for structured programming, but it is a small
* price to pay for not processing a jar file operand twice.
* (Note: This side effect has been disabled. See comment on
* bugid 5030265 below.)
*/
SelectVersion(argc, argv, &main_class);
if (JLI_IsTraceLauncher()) {
int i;
printf("Command line args:\n");
for (i = 0; i < argc ; i++) {
printf("argv[%d] = %s\n", i, argv[i]);
}
AddOption("-Dsun.java.launcher.diag=true", NULL);
}
CreateExecutionEnvironment(&argc, &argv,
jrepath, sizeof(jrepath),
jvmpath, sizeof(jvmpath));
ifn.CreateJavaVM = 0;
ifn.GetDefaultJavaVMInitArgs = 0;
if (JLI_IsTraceLauncher()) {
start = CounterGet();
}
if (!LoadJavaVM(jvmpath, &ifn)) {
return(6);
}
if (JLI_IsTraceLauncher()) {
end = CounterGet();
}
JLI_TraceLauncher("%ld micro seconds to LoadJavaVM\n",
(long)(jint)Counter2Micros(end-start));
++argv;
--argc;
if (IsJavaArgs()) {
/* Preprocess wrapper arguments */
TranslateApplicationArgs(jargc, jargv, &argc, &argv);
if (!AddApplicationOptions(appclassc, appclassv)) {
return(1);
}
} else {
/* Set default CLASSPATH */
cpath = getenv("CLASSPATH");
if (cpath == NULL) {
cpath = ".";
}
SetClassPath(cpath);
}
/* Parse command line options; if the return value of
* ParseArguments is false, the program should exit.
*/
if (!ParseArguments(&argc, &argv, &mode, &what, &ret, jrepath))
{
return(ret);
}
/* Override class path if -jar flag was specified */
if (mode == LM_JAR) {
SetClassPath(what); /* Override class path */
}
/* set the -Dsun.java.command pseudo property */
SetJavaCommandLineProp(what, argc, argv);
/* Set the -Dsun.java.launcher pseudo property */
SetJavaLauncherProp();
/* set the -Dsun.java.launcher.* platform properties */
SetJavaLauncherPlatformProps();
/* Show the splash screen if needed */
ShowSplashScreen();
return ContinueInNewThread(&ifn, argc, argv, mode, what, ret);
}
首先看上图的 InitLauncher 方法 该方法传入一个布尔值,无返回值。
打开文件 src/windows/bin/java_md.c
void
InitLauncher(boolean javaw)
{
INITCOMMONCONTROLSEX icx;
/*
* Required for javaw mode MessageBox output as well as for
* HotSpot -XX:+ShowMessageBoxOnError in java mode, an empty
* flag field is sufficient to perform the basic UI initialization.
*/
memset(&icx, 0, sizeof(INITCOMMONCONTROLSEX));
icx.dwSize = sizeof(INITCOMMONCONTROLSEX);
//平台api
InitCommonControlsEx(&icx);
_isjavaw = javaw;
JLI_SetTraceLauncher();
}
平台api可以使用高版本的IDA , 逆向lib文件了解其实现,如果没有高版本的IDA 你就要学习汇编了。
分析下这个方法 JLI_SetTraceLauncher 的实现
src/share/bin/jli_util.c
void
JLI_SetTraceLauncher()
{
if (getenv("_JAVA_LAUNCHER_DEBUG") != 0) {
_launcher_debug = JNI_TRUE;
JLI_TraceLauncher("----_JAVA_LAUNCHER_DEBUG----\n");
}
}
好了今天到这里,吃饭! 明天继续分析! 大家也要注意身体。