这一章节开始JVM
的编写,首先解决第一个问题,就是如何运行java程序,回想最开始学java时,写一个Hello.java的程序,使用javac Hello.java
将源代码转换为class文件,然后使用java Hello
运行程序。JVM是只认class文件的,如果想让JVM运行该Hello程序,就要通过java命令。本节将介绍java命令的常用方法,并实现java命令的解析。最终通过命令参数,读取对应的class数据。本节的代码均在classpath包下
java 命令简介
Java
应用程序需要一个入口点,这个入口点就是我们熟知的main()
方法。如果一个类包含public static void main(String[] args)
方法,这个类就可以用来启动Java应用程序,我们把这个类叫作主类.这个类是需要我们用命令行手动向JVM提供的;
Java命令一般有以下几种形式:
1 2 3 4
| java [-options] class [args] java [-options] -jar jarfile [args] javaw [-options] class [args] javaw [-options] -jar jarfile [args]
|
可以向 java
命令传递三组参数:选项、主类名(或者JAR文件名)
和 main() 方法参数。选项由减号-
开头。通常,第一个非选项参数给出主类的完全限定名(fully qualified class name)。但是如果用户提供了–jar
选项,第一个非选项参数表示JAR
文件名,java
命令必须从这个JAR文件中寻找主类。javaw
命令和java
命令几乎一样,唯一的差别在于,javaw
命令不显示命令行窗口,因此特别适合用于启动GUI
(图形用户界面)应用程序。
可以看到命令中都带有一个 [-options]
代表可选项, java命令行常用选项如下:
选项 |
用途 |
-version |
输出版本信息 |
-?/-help |
输出帮助信息 |
-cp/-classpath |
指定用户类路径 |
-Dproperty=value |
设置Java系统属性 |
-Xms<size> |
设置初始堆空间大小 |
-Xmx<size> |
设置最大堆空间大小 |
-Xss<size> |
设置线程栈空间大小 |
当然,java命令行里提供的选项有很多,这里并不打算全部实现,只是挑几个比较重要的去实现.
接下来我打算实现以下几种命令:
java -version
java -?
java -help
java -cp your/classpath yourClassName arg1 arg2 ...
java -classpath your/classpath yourClassName arg1 arg2 ...
命令行解析功能编码
定义Cmd
类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| public class Cmd { boolean isRightFmt = true; boolean helpFlag; boolean versionFlag; String cpOption = ""; String clazz; String[] args; public Cmd(String[] strs){ parseCmd(strs); }
public void parseCmd(String[] args) { int index = 1;
if (args.length<2){ isRightFmt = false; return; } if (!args[0].equals("java")) { isRightFmt = false; } else { if (args[1].equals("-help") || args[1].equals("-?")) { helpFlag = true; } else if (args[1].equals("-version")) { versionFlag = true; } else if (args[1].equals("-cp") || args[1].equals("classpath")) { if (args.length < 4) { isRightFmt = false; } index = 4; this.cpOption = args[2]; } else if (args[1].equals("-Xjre")) { if (args.length < 4) { isRightFmt = false; } index = 4; this.XjreOption = args[2]; }
this.clazz = args[index - 1]; this.args = new String[args.length - index]; for (int i = index; i < args.length; i++) { this.args[i - index] = args[i]; } } } public void printUsage() { System.out.println("Usage: java [-options] class [args...]\n"); } }
|
这里定义了要解析的成员变量,注意这里包含了一个我们自己定义的-Xjre
的选项,其具体含义见下一节,其它选项含义参见注释,主要功能在parseCmd()
方法中实现解析参数,根据对应的位置的选项,然后在主函数中去使用.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public static void main(String[] args) { Cmd cmd = new Cmd(args);
if (!cmd.isRightFmt) { cmd.printUsage(); } else { if (cmd.versionFlag) { System.out.println("java version \"1.8.0_20\"\n" + "Java(TM) SE Runtime Environment (build 1.8.0_20-b26)\n" + "Java HotSpot(TM) 64-Bit Server VM (build 25.20-b23, mixed mode)"); } else if (cmd.helpFlag || cmd.args == null) { cmd.printUsage(); } else { startJVM(cmd); } } }
|
首先检验命令行格式是否正确,如果不正确,输出使用信息,如果是查看版本,输出版本信息,这里暂时提供了一个临时的字符串,此功能待后续实现.如果是查看帮助信息,同样也使出使用信息.其它情况,传递给一个方法startJVM()
实现真正的开启虚拟机的逻辑,当然,此方法现在暂时内部是空实现,待后续实现。
本文作者:
Zachaxy
版权声明:
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。