1。首先在路径下写一个Hello.java的程序:--------------D:\项目管理\个人项目\手写java\hello_world
public class Hello
{
public static void main(String[] args)
{
System.out.println("Hfddlo World!");
}
}
进入到Java的安装目录:
输入:javac D:\项目管理\个人项目\手写java\hello_world\Hello.java -d D:\项目管理\个人项目\手写java\hello_world
javac 的代码:
jdk的bin目录下执行如下命令:
java -classpath D:\项目管理\个人项目\手写java\hello_world Hello
给java的Hello类加上包名:
将编译好的Hello.class放入到/com/test/ 目录下:
运行:java -classpath D:\项目管理\个人项目\手写java\hello_world com.test.Hello
java后面的参数
1. -cp是-classpath的缩写
2. --help 将此帮助消息输出到输出流
-X 将额外选项的帮助输出到错误流
-d <module name>
--describe-module <模块名称>
描述模块并退出
--dry-run 创建 VM 并加载主类, 但不执行 main 方法。
此 --dry-run 选项对于验证诸如
模块系统配置这样的命令行选项可能非常有用。
3. --boot-class-path <path>, -bootclasspath <path>
覆盖引导类文件的位置
--class-path <path>, -classpath <path>, -cp <path>
指定查找用户类文件和注释处理程序的位置
-d <directory> 指定放置生成的类文件的位置
-g 生成所有调试信息
--release <release> 针对特定 VM 版本进行编译。支持的目标: 6, 7, 8, 9
-s <directory> 指定放置生成的源文件的位置
-source <release> 提供与指定发行版的源兼容性
-Werror 出现警告时终止编译
源码追踪:
命令行运行java -version
程序会走到:D:\项目管理\个人项目\jdk源码解读\openjdk7\openjdk\jdk\src\share\bin\main.c 的第96行:
/*
* 程序的入口
*/
#ifdef JAVAW
char **__initenv;
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 */
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);
}
JLI_Launch在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 */
)
{...............................
/* 解析命令行的参数; 如果命令行参数错误* 就终止程序
*/
if (!ParseArguments(&argc, &argv, &mode, &what, &ret, jrepath))
{
return(ret);
}
............
}
进入这个函数看看::
/**
* bool为C中变量类型,jboolean 为JNI中变量类型,boolean为Java中变量类型;
jboolean在C语言的定义为:
typedef unsigned char jboolean;
unsigned char是无符号字节型,char类型变量的大小通常为1个字节(1字节=8个位),且属于整型;说明jboolean在C语言中取值为0或1,且有如下宏定义:
#define JNI_FALSE 0
#define JNI_TRUE 1
*/
static jboolean
ParseArguments(int *pargc, char ***pargv,
int *pmode, char **pwhat,
int *pret, const char *jrepath)
{.................
while ((arg = *argv) != 0 && *arg == '-') {
argv++; --argc;
if (JLI_StrCmp(arg, "-classpath") == 0 || JLI_StrCmp(arg, "-cp") == 0) {
ARG_CHECK (argc, ARG_ERROR1, arg);
SetClassPath(*argv);
mode = LM_CLASS;
argv++; --argc;
} else if (JLI_StrCmp(arg, "-jar") == 0) {
ARG_CHECK (argc, ARG_ERROR2, arg);
mode = LM_JAR;
} else if (JLI_StrCmp(arg, "-help") == 0 ||
JLI_StrCmp(arg, "-h") == 0 ||
JLI_StrCmp(arg, "-?") == 0) {
printUsage = JNI_TRUE;
return JNI_TRUE;
} else if (JLI_StrCmp(arg, "-version") == 0) {
printVersion = JNI_TRUE;
return JNI_TRUE;
} else if (JLI_StrCmp(arg, "-showversion") == 0) {
showVersion = JNI_TRUE;
} else if (JLI_StrCmp(arg, "-X") == 0) {
printXUsage = JNI_TRUE;
return JNI_TRUE;
...................
if (--argc >= 0) {
*pwhat = *argv++;
}
if (*pwhat == NULL) {
*pret = 1;
} else if (mode == LM_UNKNOWN) {
/* default to LM_CLASS if -jar and -cp option are
* not specified */
mode = LM_CLASS;
}
if (argc >= 0) {
*pargc = argc;
*pargv = argv;
}
*pmode = mode;
return JNI_TRUE;
}
.....
}
解析到了version,返回JNI_TRUE,
2.仍然是JLI_Launch()函数: ----------------------- 从命令行拿到类的路径
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);
}
JLI_LAUCH()下的 SetJavaLauncherPlatformProps()
/* 获取当前进程id,放入参数 -D sun。java。laucher。pid,这样jvm就知道他的创建者的进程ID */
SetJavaLauncherPlatformProps();
在来看看这个方法:
进去看看:创建虚拟机,调用客户自己写的java程序,主类的Main()函数进入。
static int
ContinueInNewThread(InvocationFunctions* ifn, int argc, char **argv,
int mode, char *what, int ret)
{
/*未指定堆大小 ----通过init args(初始的参数)结构返回其默认堆栈大小
* If user doesn't specify stack size, check if VM has a preference.
* Note that HotSpot no longer supports JNI_VERSION_1_1 but it will
* return its default stack size through the init args structure.
*/
if (threadStackSize == 0) {
struct JDK1_1InitArgs args1_1;
memset((void*)&args1_1, 0, sizeof(args1_1));
args1_1.version = JNI_VERSION_1_1;
ifn->GetDefaultJavaVMInitArgs(&args1_1); /* ignore return value */
if (args1_1.javaStackSize > 0) {
threadStackSize = args1_1.javaStackSize;
}
}
/**创建一个线程去创建
* jvm 虚拟机和调用java主类中的main()主函数方法
* */
{ /* Create a new thread to create JVM and invoke main method */
JavaMainArgs args;
int rslt;
args.argc = argc;
args.argv = argv;
args.mode = mode;
args.what = what;
args.ifn = *ifn;
rslt = ContinueInNewThread0(JavaMain, threadStackSize, (void*)&args);
/* If the caller has deemed there is an error we
* simply return that, otherwise we return the value of
* the callee
*/
return (ret != 0) ? ret : rslt;
}
}